diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 764008045b..1f2c362fdc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,11 +14,11 @@ jobs: include: - name: "Linux x64 (Ubuntu 24.04) - GCC 14" os: ubuntu-24.04 - build: { cc: gcc-14, cxx: g++-14, linker: ld } + build: { cc: gcc-14, cxx: g++-14, linker: ld, docs: true } - - name: "Linux x64 (Ubuntu 24.04) - Clang 18 with ASan and UBSan" + - name: "Linux x64 (Ubuntu 24.04) - Clang 19 with ASan and UBSan" os: ubuntu-24.04 - build: { cc: clang-18, cxx: clang++-18, linker: ld.lld-18, sanitize: true } + build: { cc: clang-19, cxx: clang++-19, linker: ld.lld-19, sanitize: true } - name: "macOS arm64 (14) - Xcode 15" os: macos-14 @@ -39,7 +39,7 @@ jobs: run: | sudo apt-get update sudo apt-get install \ - meson pkg-config \ + meson gi-docgen pkg-config \ libarchive-dev libcfitsio-dev libcgif-dev \ libexif-dev libexpat1-dev libffi-dev \ libfftw3-dev libheif-dev libheif-plugin-aomenc \ @@ -54,8 +54,12 @@ jobs: if: runner.os == 'macOS' run: | pip3 install meson --break-system-packages + # Run `brew update` to ensure we have the latest formulae. + # Note: GHA macOS runners set `HOMEBREW_NO_AUTO_UPDATE=1` + # by default, as updating can be time-consuming. + brew update brew install \ - ninja pkg-config \ + ninja pkgconf \ cfitsio cgif fftw fontconfig glib \ highway jpeg-xl libarchive libexif \ libheif libimagequant libmatio librsvg \ @@ -63,9 +67,9 @@ jobs: openexr openjpeg openslide pango \ poppler webp - - name: Install Clang 18 - if: runner.os == 'Linux' && matrix.build.cc == 'clang-18' - run: sudo apt-get install clang-18 libomp-18-dev lld-18 llvm-18 + - name: Install Clang 19 + if: runner.os == 'Linux' && matrix.build.cc == 'clang-19' + run: sudo apt-get install clang-19 libomp-19-dev lld-19 llvm-19 - name: Prepare macOS environment if: runner.os == 'macOS' @@ -75,7 +79,7 @@ jobs: - name: Prepare sanitizers if: matrix.build.sanitize env: - LLVM_PREFIX: /usr/lib/llvm-18 + LLVM_PREFIX: /usr/lib/llvm-19 run: | ASAN_DSO=`$CC -print-file-name=libclang_rt.asan-x86_64.so` echo "LDSHARED=$CC -shared" >> $GITHUB_ENV @@ -96,6 +100,7 @@ jobs: run: meson setup build -Ddebug=true + -Ddocs=${{ matrix.build.docs && 'true' || 'false' }} -Ddeprecated=false -Dmagick=disabled || (cat build/meson-logs/meson-log.txt && exit 1) @@ -104,8 +109,8 @@ jobs: run: meson compile -C build - name: Check libvips - run: | - meson test -C build \ + run: + meson test -C build || (cat build/meson-logs/testlog.txt && exit 1) - name: Install libvips diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fef6197973..f4a25351ee 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,7 +13,7 @@ jobs: id: linter with: style: file - version: 18 # Ubuntu 24.04 provides clang-format-18 + version: 19 # Ubuntu 24.04 provides clang-format-19 tidy-checks: '-*' # disable clang-tidy lines-changed-only: true # ignore bundled files diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000000..8871e27d43 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,25 @@ +cff-version: 1.2.0 +message: If you use this software, please cite it as below. +title: libvips +authors: + - family-names: libvips team +url: https://libvips.org +preferred-citation: + type: conference-paper + title: The libvips image processing library + authors: + - family-names: Cupitt + given-names: John + - family-names: Martinez + given-names: Kirk + - family-names: Fuller + given-names: Lovell + - family-names: Wolthuizen + given-names: Kleis Auke + collection-title: Electronic Imaging 2025 + collection-type: proceedings + month: 2 + year: 2025 + publisher: + name: Society for Imaging Science and Technology + url: "https://www.southampton.ac.uk/~km2/papers/2025/vips-ist-preprint.pdf" diff --git a/ChangeLog b/ChangeLog index e01c79ff5b..ac5201fb24 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,66 @@ +master + 8.17.0 - add `keep_duplicate_frames` option to GIF save [dloebl] - add Magic Kernel support [akimon658] +- tiff: add threadsafe warning/error handlers (requires libtiff 4.5.0+) [lovell] +- tiffload: add support for fail_on flag [lovell] +- tiffload: add support for unlimited flag (requires libtiff 4.7.0+) [lovell] +- much more reliable operation caching +- colour: add support for auto-selecting the rendering intent [kleisauke] +- add matrixmultiply +- better handling of malformed size values [Simcha Kosman] +- improve performance of vips_shrink() [kleisauke] +- svgload: add support for custom CSS via stylesheet option [lovell] +- heifload: `unlimited` flag removes all limits (requires libheif 1.19.0+) [lovell] +- heifsave: improve alpha channel detection [lovell] +- convi: ensure double sum precision for floats [lovell] +- improve guard against corrupt ICC profiles with older lcms2 versions [kleisauke] +- improve vips_sink_screen() thumbnail rendering +- heifload: improve detection of seek beyond EOF [lovell] +- add "oneshot" option to jp2kload [mbklein] +- share and reuse openslide connections +- drop support for openslide 3.3 +- fix vips_quadratic() +- rename `thumbnail`'s export/import profile options as input/output for + consistency +- restore vips_remosaic(), it was not being linked +- deprecate VipsSaveable, add VipsForeignSaveable +- move vips_image_preeval(), vips_image_eval(), vips_image_posteval() into the + public API +- jxlsave writes in chunks, for lower memory use on large images (but we now + need libjxl 0.11 at minimum) 8.16.1 - support multipage JXL -- fix PFM byte order on little-endian machines [agoode] +- fix PFM byte order on big-endian machines [agoode] +- morph: fix erode Highway path [kleisauke] +- morph: fix C-paths with masks containing zero [kleisauke] +- fix `--vips-info` CLI flag with GLib >= 2.80 [kleisauke] +- make `subsample-mode=on` and `lossless=true` mutually exclusive [kleisauke] +- fix SZI write with openslide4 [goran-hc] +- heifsave: prevent use of AV1 intra block copy feature [lovell] +- threadpool: improve cooperative downsizing [kleisauke] +- fix alpha shift during colourspace conversions [frederikrosenberg] +- heifsave: set image orientation using irot and imir transformations [lovell] +- XYZ2Yxy: guard against divide by zero +- fix MSVC compile error [na-trium-144] +- exif: ensure enumerated entries can be converted to string values [lovell] +- gifsave: add support for eval callback, ensure correct return code [lovell] +- tiffsave: honor disc threshold during pyramid save [kleisauke] +- fill_nearest: fix a leak +- colour: use suggested rendering intent as fallback [kleisauke] +- morph: fix Orc path with large masks [kleisauke] +- invertlut: fix final value in some cases +- matrixload: fix file format detect for some matrix types +- radload: improve sanity check of colour-related headers [lovell] +- heifsave: reject multiband images [lovell] +- heifload: prevent possible int overflow for large images [kleisauke] +- tiffload: add missing read loop [kleisauke] +- prevent possible use-after-free when debugging via `--vips-leak` flag [lovell] +- avoid possible overflow when multiplication result is cast up [lovell] 10/10/24 8.16.0 diff --git a/README.md b/README.md index f95ac71af5..a8faca4015 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ libvips is used as an image processing engine by: | [bimg](https://github.com/h2non/bimg) | | [sharp for Go](https://github.com/DAddYE/vips) | | [Ruby on Rails](https://edgeguides.rubyonrails.org/active_storage_overview.html) | -| [carrierwave-vips](https://github.com/eltiare/carrierwave-vips) | +| [CarrierWave](https://github.com/carrierwaveuploader/carrierwave#using-vips) | | [mediawiki](https://www.mediawiki.org/wiki/Extension:VipsScaler) | | [PhotoFlow](https://github.com/aferrero2707/PhotoFlow) | | [JVips](https://github.com/criteo/JVips) | diff --git a/cplusplus/examples/tomemory.cpp b/cplusplus/examples/tomemory.cpp new file mode 100644 index 0000000000..64b405c646 --- /dev/null +++ b/cplusplus/examples/tomemory.cpp @@ -0,0 +1,46 @@ +/* compile with: + * + * g++ -g -Wall tomemory.cpp `pkg-config vips-cpp --cflags --libs` + */ + +#include +#include + +int +main(int argc, char* argv[]) +{ + if (VIPS_INIT(argv[0])) + vips_error_exit(nullptr); + + for (int i = 0; i < 1000; i++) { + std::cout << "loop " << i << " ..." << std::endl; + + // create a uint8 RGBA VImage + // `black` makes a mono image, so you need to explicitly tag it as srgb + const int width = 50; + const int height = 50; + const int channels = 3; + vips::VImage image = + vips::VImage::black(width, height, vips::VImage::option() + ->set("bands", channels)) + .copy(vips::VImage::option() + ->set("interpretation", "srgb")) + .bandjoin(255); + + // C libvips API to print a vips subclass ... handy for debugging + std::cout << "built: "; + vips_object_print_summary(VIPS_OBJECT(image.get_image())); + + // render to an area of memory ... you can use `.data()`, but this is + // just as quick, and is threadsafe + size_t len; + void *data = image.write_to_memory(&len); + + std::cout << len << " bytes of data at address " << data << std::endl; + + // you own this pointer and must free it + g_free(data); + } + + return 0; +} diff --git a/cplusplus/gen-operators.py b/cplusplus/gen-operators.py index f76af70d0b..6407c67a23 100755 --- a/cplusplus/gen-operators.py +++ b/cplusplus/gen-operators.py @@ -4,10 +4,9 @@ # operators. # this needs pyvips -# # pip install --user pyvips -# Rebuild with: +# rebuild with: # meson compile -Cbuild vips-operators-header # meson compile -Cbuild vips-operators-source @@ -262,8 +261,14 @@ def add_nickname(gtype, a, b): all_nicknames = list(set(all_nicknames) - set(hidden_savers)) all_nicknames.sort() + indent = '\t' if declarations_only else '' + + print(f'''{indent}// {'headers' if declarations_only else 'bodies'} for vips operations +{indent}// this file is generated automatically, do not edit! +{indent}// clang-format off''') + for nickname in all_nicknames: - print(generate_operation(nickname, declarations_only, '\t' if declarations_only else '')) + print(generate_operation(nickname, declarations_only, indent)) parser = argparse.ArgumentParser(description='C++ binding generator') diff --git a/cplusplus/include/vips/VImage8.h b/cplusplus/include/vips/VImage8.h index 2e00951f6e..c40095ccd5 100644 --- a/cplusplus/include/vips/VImage8.h +++ b/cplusplus/include/vips/VImage8.h @@ -2082,6 +2082,7 @@ class VImage : public VObject { // headers for vips operations // this file is generated automatically, do not edit! + // clang-format off /** * Transform lch to cmc. @@ -3765,6 +3766,7 @@ class VImage : public VObject { * * **Optional parameters** * - **page** -- Load this page from the image, int. + * - **oneshot** -- Load images a frame at a time, bool. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. @@ -3781,6 +3783,7 @@ class VImage : public VObject { * * **Optional parameters** * - **page** -- Load this page from the image, int. + * - **oneshot** -- Load images a frame at a time, bool. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. @@ -3797,6 +3800,7 @@ class VImage : public VObject { * * **Optional parameters** * - **page** -- Load this page from the image, int. + * - **oneshot** -- Load images a frame at a time, bool. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. @@ -4520,7 +4524,7 @@ class VImage : public VObject { static VImage matload(const char *filename, VOption *options = nullptr); /** - * Invert an matrix. + * Invert a matrix. * @param options Set of options. * @return Output matrix. */ @@ -4556,6 +4560,14 @@ class VImage : public VObject { */ static VImage matrixload_source(VSource source, VOption *options = nullptr); + /** + * Multiply two matrices. + * @param right Second matrix to multiply. + * @param options Set of options. + * @return Output matrix. + */ + VImage matrixmultiply(VImage right, VOption *options = nullptr) const; + /** * Print matrix. * @@ -5413,6 +5425,15 @@ class VImage : public VObject { */ VImage remainder_const(std::vector c, VOption *options = nullptr) const; + /** + * Rebuild an mosaiced image. + * @param old_str Search for this string. + * @param new_str And swap for this string. + * @param options Set of options. + * @return Output image. + */ + VImage remosaic(const char *old_str, const char *new_str, VOption *options = nullptr) const; + /** * Replicate an image. * @param across Repeat this many times horizontally. @@ -5513,7 +5534,7 @@ class VImage : public VObject { VImage scRGB2XYZ(VOption *options = nullptr) const; /** - * Convert an scrgb image to srgb. + * Convert scrgb to srgb. * * **Optional parameters** * - **depth** -- Output device space depth in bits, int. @@ -5758,6 +5779,7 @@ class VImage : public VObject { * - **dpi** -- Render at this DPI, double. * - **scale** -- Scale output by this factor, double. * - **unlimited** -- Allow SVG of any size, bool. + * - **stylesheet** -- Custom CSS, const char *. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. @@ -5776,6 +5798,7 @@ class VImage : public VObject { * - **dpi** -- Render at this DPI, double. * - **scale** -- Scale output by this factor, double. * - **unlimited** -- Allow SVG of any size, bool. + * - **stylesheet** -- Custom CSS, const char *. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. @@ -5794,6 +5817,7 @@ class VImage : public VObject { * - **dpi** -- Render at this DPI, double. * - **scale** -- Scale output by this factor, double. * - **unlimited** -- Allow SVG of any size, bool. + * - **stylesheet** -- Custom CSS, const char *. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. @@ -5856,8 +5880,8 @@ class VImage : public VObject { * - **no_rotate** -- Don't use orientation tags to rotate image upright, bool. * - **crop** -- Reduce to fill target rectangle, then crop, VipsInteresting. * - **linear** -- Reduce in linear light, bool. - * - **import_profile** -- Fallback import profile, const char *. - * - **export_profile** -- Fallback export profile, const char *. + * - **input_profile** -- Fallback input profile, const char *. + * - **output_profile** -- Fallback output profile, const char *. * - **intent** -- Rendering intent, VipsIntent. * - **fail_on** -- Error level to fail on, VipsFailOn. * @@ -5878,8 +5902,8 @@ class VImage : public VObject { * - **no_rotate** -- Don't use orientation tags to rotate image upright, bool. * - **crop** -- Reduce to fill target rectangle, then crop, VipsInteresting. * - **linear** -- Reduce in linear light, bool. - * - **import_profile** -- Fallback import profile, const char *. - * - **export_profile** -- Fallback export profile, const char *. + * - **input_profile** -- Fallback input profile, const char *. + * - **output_profile** -- Fallback output profile, const char *. * - **intent** -- Rendering intent, VipsIntent. * - **fail_on** -- Error level to fail on, VipsFailOn. * @@ -5899,8 +5923,8 @@ class VImage : public VObject { * - **no_rotate** -- Don't use orientation tags to rotate image upright, bool. * - **crop** -- Reduce to fill target rectangle, then crop, VipsInteresting. * - **linear** -- Reduce in linear light, bool. - * - **import_profile** -- Fallback import profile, const char *. - * - **export_profile** -- Fallback export profile, const char *. + * - **input_profile** -- Fallback input profile, const char *. + * - **output_profile** -- Fallback output profile, const char *. * - **intent** -- Rendering intent, VipsIntent. * - **fail_on** -- Error level to fail on, VipsFailOn. * @@ -5920,8 +5944,8 @@ class VImage : public VObject { * - **no_rotate** -- Don't use orientation tags to rotate image upright, bool. * - **crop** -- Reduce to fill target rectangle, then crop, VipsInteresting. * - **linear** -- Reduce in linear light, bool. - * - **import_profile** -- Fallback import profile, const char *. - * - **export_profile** -- Fallback export profile, const char *. + * - **input_profile** -- Fallback input profile, const char *. + * - **output_profile** -- Fallback output profile, const char *. * - **intent** -- Rendering intent, VipsIntent. * - **fail_on** -- Error level to fail on, VipsFailOn. * @@ -5937,9 +5961,10 @@ class VImage : public VObject { * * **Optional parameters** * - **page** -- First page to load, int. - * - **subifd** -- Subifd index, int. * - **n** -- Number of pages to load, -1 for all, int. * - **autorotate** -- Rotate image using orientation tag, bool. + * - **subifd** -- Subifd index, int. + * - **unlimited** -- Remove all denial of service limits, bool. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. @@ -5956,9 +5981,10 @@ class VImage : public VObject { * * **Optional parameters** * - **page** -- First page to load, int. - * - **subifd** -- Subifd index, int. * - **n** -- Number of pages to load, -1 for all, int. * - **autorotate** -- Rotate image using orientation tag, bool. + * - **subifd** -- Subifd index, int. + * - **unlimited** -- Remove all denial of service limits, bool. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. @@ -5975,9 +6001,10 @@ class VImage : public VObject { * * **Optional parameters** * - **page** -- First page to load, int. - * - **subifd** -- Subifd index, int. * - **n** -- Number of pages to load, -1 for all, int. * - **autorotate** -- Rotate image using orientation tag, bool. + * - **subifd** -- Subifd index, int. + * - **unlimited** -- Remove all denial of service limits, bool. * - **memory** -- Force open via memory, bool. * - **access** -- Required access pattern for this file, VipsAccess. * - **fail_on** -- Error level to fail on, VipsFailOn. diff --git a/cplusplus/meson.build b/cplusplus/meson.build index a47ad6ccf4..66ecf2855f 100644 --- a/cplusplus/meson.build +++ b/cplusplus/meson.build @@ -39,7 +39,7 @@ custom_target('vips-operators-source', output: 'vips-operators.cpp' ) -if get_option('doxygen') +if get_option('cpp-docs') doxygen = find_program('doxygen') doxygen_data = configuration_data() doxygen_data.set('VIPS_MAJOR_VERSION', version_major) diff --git a/cplusplus/vips-operators.cpp b/cplusplus/vips-operators.cpp index d503bfe01c..27ddfe8c7c 100644 --- a/cplusplus/vips-operators.cpp +++ b/cplusplus/vips-operators.cpp @@ -2316,6 +2316,19 @@ VImage::matrixload_source(VSource source, VOption *options) return out; } +VImage +VImage::matrixmultiply(VImage right, VOption *options) const +{ + VImage out; + + call("matrixmultiply", (options ? options : VImage::option()) + ->set("left", *this) + ->set("out", &out) + ->set("right", right)); + + return out; +} + void VImage::matrixprint(VOption *options) const { @@ -3061,6 +3074,20 @@ VImage::remainder_const(std::vector c, VOption *options) const return out; } +VImage +VImage::remosaic(const char *old_str, const char *new_str, VOption *options) const +{ + VImage out; + + call("remosaic", (options ? options : VImage::option()) + ->set("in", *this) + ->set("out", &out) + ->set("old_str", old_str) + ->set("new_str", new_str)); + + return out; +} + VImage VImage::replicate(int across, int down, VOption *options) const { diff --git a/doc/Cite.md b/doc/Cite.md deleted file mode 100644 index a8f880c3d6..0000000000 --- a/doc/Cite.md +++ /dev/null @@ -1,18 +0,0 @@ - - Cite - 3 - libvips - - - - Cite - References to cite for libvips - - -Martinez, K. and Cupitt, J. (2005) -VIPS -- a highly tuned image processing software architecture. In Proceedings of IEEE International -Conference on Image Processing 2, pp. 574-577, Genova. - -Cupitt, J. and Martinez, K. (1996) -VIPS: An image processing system for large images, Proc. SPIE, vol. 2663, pp. 19--28. - diff --git a/doc/Cite.xml b/doc/Cite.xml deleted file mode 100644 index 871eb86fd5..0000000000 --- a/doc/Cite.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - Cite 3 libvips - - - Cite References to cite for libvips - - - Martinez, K. and Cupitt, J. (2005) VIPS – a highly tuned image processing software architecture. In Proceedings of IEEE International Conference on Image Processing 2, pp. 574-577, Genova. - - - Cupitt, J. and Martinez, K. (1996) VIPS: An image processing system for large images, Proc. SPIE, vol. 2663, pp. 19–28. - - - - diff --git a/doc/Developer-checklist.xml b/doc/Developer-checklist.xml deleted file mode 100644 index c4227e7ecf..0000000000 --- a/doc/Developer-checklist.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - Developer checklist 3 libvips - - - Dev checklist Checklist for libvips users - - - libvips is a slightly unusual library and you may need to take some of its stranger features into account when you design software that uses it. - - - Codestin Search App - - The thumbnail operation combines load and resize into one step. This lets it take advantage of format library features, such as shrink on load, and can lead to a large improvement in speed and a large drop in memory use. - - - For example, with this JPEG image: - - -$ vipsheader nina.jpg -nina.jpg: 6048x4032 uchar, 3 bands, srgb, jpegload - - - I see: - - -$ /usr/bin/time -f %M:%e vips resize nina.jpg x.jpg 0.1 -123648:0.23 - - - 124 MB of RAM and 0.23s to shink by a factor of 10. With thumbnail it’s: - - -$ /usr/bin/time -f %M:%e vips thumbnail nina.jpg x.jpg 605 -68864:0.08 - - - Now it’s 68 MB of memory and 0.08s – half the memory use, and 3x faster. In fact the improvement is better than that, since the vips command takes a while to start and needs a fair amount of memory: - - -$ /usr/bin/time -f %M:%e vips > /dev/null -31232:0.02 - - - 31 MB and 0.02s, so thumbnail is really 2.5x less memory and 4x faster. - - - You can see much larger improvements with other formats, and quality will often be better as well, since thumbnail will automatically premultiply and can render vector images directly at the correct size. - - - - Codestin Search App - - It’s just there for emergencies. It can’t do any of the rendering tricks, so it’s no faster than resize. Use thumbnail if you can. - - - - Codestin Search App - - This is a hint you pass to new_from_file and friends that signals that you will only scan this image in the direction that the underlying load library supports. This can give a useful improvement in speed and reduction in memory use in many cases. - - - See the How it opens files chapter for background on this feature. - - - - Codestin Search App - - libvips is demand-driven, and uses partial images as intermediates. This means you can construct long pipelines of image processing operations, they won’t use much memory, and they’ll (usually) join efficiently. - - - libvips is horizontally threaded, meaning that threads run along the pipeline of operations you are evaluating, not up and down images. This means that libvips can (usually) parallelise longer pipelines more efficiently than short ones. - - - If you can, aim for long pipelines of processing operations. - - - - Codestin Search App - - If an image is reused repeatedly in one pipeline, it’ll be recomputed each time. You can sometimes get a big speedup by keeping images like this in memory rather than recalculating their pixels, see (for example), copy_memory() in pyvips. - - - This can raise memory use, of course. - - - - Codestin Search App - - If you can, put large resizes right at the start (see thumbnail above), then area filters (sharpen, for example), and finally any point operations. - - - - Codestin Search App - - libvips after version 8.13 has a system for enabling and disabling image load libraries at runtime, see: - - - https://www.libvips.org/2022/05/28/What’s-new-in-8.13.html - - - You can usually improve security and avoid memory spikes by only enabling the image formats you really need. If you are handling untrusted data, I would set the VIPS_BLOCK_UNTRUSTED env var and only use the loaders we have tested for security. - - - Older versions of libvips need compile-time configuration. - - - - Codestin Search App - - libvips image open is always fast and safe, as long as you have disabled load via imagemagick. This means you can open an image and sanity-check it before further processing. - - - There are two main checks that are very worthwhile: - - - - - Sanity check image dimensions to protect you from decompression bombs like those described at https://www.bamsoftware.com/hacks/deflate.html - - - - - Check for interlaced (also called progressive) images. - - - These are the ones that appear in low detail first, then progressively sharpen as they are downloaded. - - - The downside is that you don’t get the final pixels until the whole image is in memory, which prevents any streaming processing and hugely increases memory use. For example: - - - - -$ /usr/bin/time -f %M:%e vipsthumbnail big-progressive.jpg -3732224:4.23 -$ vips copy big-progressive.jpg x.jpg -$ /usr/bin/time -f %M:%e vipsthumbnail x.jpg -72448:0.26 - - - So this progressive jpeg takes 4gb of memory and 4.3s to thumbnail, but exactly the same image as a regular jpeg takes 72mb and 0.26s. - - - I would detect these horrors before processing by looking for the interlaced metadata item and either ban them, or if your users insist on uploading in this terrible format, push them to a separate low-priority queue on a special container. Keep them away from your main image path. - - - - Codestin Search App - - The default memory allocator on most glibc-based Linux systems (e.g. Debian, Red Hat) is unsuitable for long-running, multi-threaded processes that involve lots of small memory allocations. - - - To help avoid fragmentation and improve performance on these systems, the use of an alternative memory allocator such as jemalloc is recommended. - - - Those using musl-based Linux (e.g. Alpine) and non-Linux systems are unaffected. - - - - Codestin Search App - - The libvips operation cache is not useful for image proxies (i.e. processing many different images). Consider disabling this with vips_cache_set_max(0);. - - - - - diff --git a/doc/Examples.xml b/doc/Examples.xml deleted file mode 100644 index 56751d0a66..0000000000 --- a/doc/Examples.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - Examples 3 libvips - - - libvips examples A few example Python programs using libvips - - - This page shows a few libvips examples using Python. They will work with small syntax changes in any language with a libvips binding. - - - The libvips test suite is written in Python and exercises every operation in the API. It’s also a useful source of examples. - - - Codestin Search App - -#!/usr/bin/python3 - -import sys -import pyvips - -left = 10 -top = 10 -width = 64 -height = 64 - -image = pyvips.Image.new_from_file(sys.argv[1]) -roi = image.crop(left, top, width, height) -print('average:', roi.avg()) - - - - Codestin Search App - - This makes a 100,000 x 100,000 black image, then inserts all the images you pass on the command-line into it at random positions. libvips is able to run this program in sequential mode: it’ll open all the input images at the same time, and stream pixels from them as it needs them to generate the output. - - - To test it, first make a large 1-bit image. This command will take the green channel and write as a 1-bit fax image. wtc.jpg is a test 10,000 x 10,000 jpeg: - - -$ vips extract_band wtc.jpg x.tif[squash,compression=ccittfax4,keep=none] 1 - - - Now make 1,000 copies of that image in a subdirectory: - - -$ mkdir test -$ for i in {1..1000}; do cp x.tif test/$i.tif; done - - - And run this Python program on them: - - -$ time python try255.py x.tif[squash,compression=ccittfax4,strip,bigtiff] test/* -real 1m59.924s -user 4m5.388s -sys 0m8.936s - - - It completes in just under two minutes on this laptop, and needs about 7gb of RAM to run. It would need about the same amount of memory for a full-colour RGB image, I was just keen to keep disc usage down. - - - If you wanted to handle transparency, or if you wanted mixed CMYK and RGB images, you’d need to do some more work to convert them all into the same colourspace before inserting them. - - -#!/usr/bin/python3 -#file try255.py - -import sys -import random -import pyvips - -# this makes a 8-bit, mono image of 100,000 x 100,000 pixels, each pixel zero -im = pyvips.Image.black(100000, 100000) - -for filename in sys.argv[2:]: - tile = pyvips.Image.new_from_file(filename, access='sequential') - - im = im.insert(tile, - random.randint(0, im.width - tile.width), - random.randint(0, im.height - tile.height)) - -im.write_to_file(sys.argv[1]) - - - - - diff --git a/doc/How-it-opens-files.xml b/doc/How-it-opens-files.xml deleted file mode 100644 index d61930345c..0000000000 --- a/doc/How-it-opens-files.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - Opening files 3 libvips - - - Opening How libvips opens files - - - libvips has at least four different ways of opening image files, each best for different file types, file sizes and image use cases. libvips tries hard to pick the best strategy in each case and mostly you don’t need to know what it is doing behind the scenes, except unfortunately when you do. - - - 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. vips_image_new_from_file() has the official documentation. - - - Codestin Search App - - libvips caches recent operations. This means that if a file changes between one load and the next, the second load will return the old image, even though the file has been replaced. - - - You can force libvips to load a file and ignore any cached value by setting the revalidate flag, see #VipsForeignLoad. - - - - Codestin Search App - - This is the fastest and simplest one. The file is mapped directly into the process’s 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 computer’s operating system: your OS will use spare memory to cache recently used chunks of the file. - - - 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. - - - libvips has a special direct write mode where pixels can be written directly to the file image. This is used for the draw operators. - - - - Codestin Search App - - 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. - - - These libraries are generally single-threaded, so only one thread may read at once, making them slower than simple direct access. Additionally, tiles are often compressed, meaning that each time a tile is fetched it must be decompressed. libvips keeps a cache of recently-decompressed tiles to try to avoid repeatedly decompressing the same tile. - - - libvips can load tiled tiff, tiled OpenEXR, FITS and OpenSlide images in this manner. - - - - Codestin Search App - - 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. - - - For small images (less than 100mb when decompressed), libvips allocates a large area of memory and decompresses the entire image to that. It then uses that memory buffer of decompressed pixels to feed the pipeline. For large images, libvips decompresses to a temporary file on disc, then loads that temporary file in direct access mode (see above). Note that on open libvips just reads the image header and is quick: the image decompress happens on the first pixel access. - - - You can control this process with environment variables, command-line flags and API calls as you choose, see vips_image_new_from_file(). They let you set the threshold at which libvips switches between memory and disc and where on disc the temporary files are held. - - - This is the slowest and most memory-hungry way to read files, but it’s unavoidable for many file formats. Unless you can use the next one! - - - - Codestin Search App - - This a fairly recent addition to libvips and is a hybrid of the previous two. - - - Imagine how this command might be executed: - - -$ vips flip fred.jpg jim.jpg vertical - - - meaning, read fred.jpg, flip it up-down, and write as jim.jpg. - - - In order to write jim.jpg top-to-bottom, it’ll have to read fred.jpg bottom-to-top. Unfortunately libjpeg only supports top-to-bottom reading and writing, so libvips must convert fred.jpg to a random access format before it can run the flip operation. - - - However many useful operations do not require true random access.  For example: - - -$ vips shrink fred.png jim.png 10 10 - - - meaning shrink fred.png by a factor of 10 in both axes and write as jim.png. - - - You can imagine this operation running without needing fred.png to be completely decompressed first. You just read 10 lines from fred.png for every one line you write to jim.png. - - - To help in this case, libvips has a hint you can give to loaders to say I will only need pixels from this image in top-to-bottom order. With this hint set, libvips will hook up the pipeline of operations directly to the read-a-line interface provided by the image library, and add a small cache of the most recent 100 or so lines. - - - This is done automatically in command-line operation. In programs, you need to set access to #VIPS_ACCESS_SEQUENTIAL in calls to functions like vips_image_new_from_file(). - - - - - diff --git a/doc/How-it-works.xml b/doc/How-it-works.xml deleted file mode 100644 index b237b3e570..0000000000 --- a/doc/How-it-works.xml +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - - How libvips works 3 libvips - - - Internals A high-level technical overview of libvips’s evaluation system - - - Compared to most image processing libraries, VIPS needs little RAM and runs quickly, especially on machines with more than one CPU. VIPS achieves this improvement by only keeping the pixels currently being processed in RAM and by having an efficient, threaded image IO system. This page explains how these features are implemented. - - - Images - - - VIPS images have three dimensions: width, height and bands. Bands usually (though not always) represent colour. These three dimensions can be any size up to 2 ** 31 elements. Every band element in an image has to have the same format. A format is an 8-, 16- or 32-bit int, signed or unsigned, 32- or 64-bit float, and 64- or 128-bit complex. - - - Regions - - - An image can be very large, much larger than the available memory, so you can’t just access pixels with a pointer *. - - - Instead, you read pixels from an image with a region. This is a rectangular sub-area of an image. In C, the API looks like: - - -VipsImage *image = vips_image_new_from_file(filename, NULL); -VipsRegion *region = vips_region_new(image); - -// ask for a 100x100 pixel region at 0x0 (top left) -VipsRect r = { .left = 0, .top = 0, .width = 100, .height = 100 }; -if (vips_region_prepare(region, &r)) - vips_error(...); - -// get a pointer to the pixel at x, y, where x, y must -// be within the region - -// as long as you stay within the valid area for the region, -// you can address pixels with regular pointer arithmetic - -// compile with -DDEBUG and the macro will check bounds for you - -// add VIPS_REGION_LSKIP() to move down a line -VipsPel *pixel = VIPS_REGION_ADDR(region, x, y); - -// you can call vips_region_prepare() many times - -// everything in libvips is a GObject ... when you're done, -// just free with -g_object_unref(region); - - - The action that vips_region_prepare() takes varies with the type of image. If the image is a file on disc, for example, then VIPS will arrange for a section of the file to be read in. - - - (* there is an image access mode where you can just use a pointer, but it’s rarely used) - - - Partial images - - - A partial image is one where, instead of storing a value for each pixel, VIPS stores a function which can make any rectangular area of pixels on demand. - - - If you use vips_region_prepare() on a region created on a partial image, VIPS will allocate enough memory to hold the pixels you asked for and use the stored function to calculate values for just those pixels *. - - - The stored function comes in three parts: a start function, a generate function and a stop function. The start function creates a state, the generate function uses the state plus a requested area to calculate pixel values and the stop function frees the state again. Breaking the stored function into three parts is good for SMP scaling: resource allocation and synchronisation mostly happens in start functions, so generate functions can run without having to talk to each other. - - - VIPS makes a set of guarantees about parallelism that make this simple to program. Start and stop functions are mutually exclusive and a state is never used by more than one generate. In other words, a start / generate / generate / stop sequence works like a thread. - - - - - - - - - - (* in fact VIPS keeps a cache of calculated pixel buffers and will return a pointer to a previously-calculated buffer if it can) - - - Operations - - - VIPS operations read input images and write output images, performing some transformation on the pixels. When an operation writes to an image the action it takes depends upon the image type. For example, if the image is a file on disc then VIPS will start a data sink to stream pixels to the file, or if the image is a partial one then it will just attach start / generate / stop functions. - - - Like most threaded image processing systems, all VIPS operations have to be free of side-effects. In other words, operations cannot modify images, they can only create new images. This could result in a lot of copying if an operation is only making a small change to a large image so VIPS has a set of mechanisms to copy image areas by just adjusting pointers. Most of the time no actual copying is necessary and you can perform operations on large images at low cost. - - - SIMD optimisations - - - VIPS uses Highway, a C++ library, to optimise various operations with SIMD/vector instructions. These optimised code paths are flexible and can adapt to different instruction sets, including those with scalable vectors (size unknown at compile time). At runtime, dynamic dispatch selects the best available implementation based on the processor’s capabilities, ensuring optimal performance. - - - SIMD typically speeds operations up by a factor of three or four. - - - Joining operations together - - - The region create / prepare / prepare / free calls you use to get pixels from an image are an exact parallel to the start / generate / generate / stop calls that images use to create pixels. In fact, they are the same: a region on a partial image holds the state created by that image for the generate function that will fill the region with pixels. - - - - - - - - - - VIPS joins image processing operations together by linking the output of one operation (the start / generate / stop sequence) to the input of the next (the region it uses to get pixels for processing). This link is a single function call, and very fast. Additionally, because of the the split between allocation and processing, once a pipeline of operations has been set up, VIPS is able to run without allocating and freeing memory. - - - This graph (generated by vipsprofile, the vips profiler) shows memory use over time for a vips pipeline running on a large image. The bottom trace shows total memory, the upper traces show threads calculating useful results (green), threads blocked on synchronisation (red) and memory allocations (white ticks). - - - - - - - - - - Because the intermediate image is just a small region in memory, a pipeline of operations running together needs very little RAM. In fact, intermediates are small enough that they can fit in L2 cache on most machines, so an entire pipeline can run without touching main memory. And finally, because each thread runs a very cheap copy of just the writeable state of the entire pipeline, threads can run with few locks. VIPS needs just four lock operations per output tile, regardless of the pipeline length or complexity. - - - Data sources - - - VIPS has data sources which can supply pixels for processing from a variety of sources. VIPS can stream images from files in VIPS native format, from tiled TIFF files, from binary PPM/PGM/PBM/PFM, from Radiance (HDR) files, from FITS images and from tiled OpenEXR images. VIPS will automatically unpack other formats to temporary disc files for you but this can obviously generate a lot of disc traffic. It also has a special sequential mode for streaming operations on non-random-access formats. Another section in these docs explains how libvips opens a file. One of the sources uses the ImageMagick (or optionally GraphicsMagick library, so VIPS can read any image format that these libraries can read. - - - VIPS images are held on disc as a 64-byte header containing basic image information like width, height, bands and format, then the image data as a single large block of pixels, left-to-right and top-to-bottom, then an XML extension block holding all the image metadata, such as ICC profiles and EXIF blocks. - - - When reading from a large VIPS image (or any other format with the same structure on disc, such as binary PPM), VIPS keeps a set of small rolling windows into the file, some small number of scanlines in size. As pixels are demanded by different threads VIPS will move these windows up and down the file. As a result, VIPS can process images much larger than RAM, even on 32-bit machines. - - - Data sinks - - - In a demand-driven system, something has to do the demanding. VIPS has a variety of data sinks that you can use to pull image data though a pipeline in various situations. There are sinks that will build a complete image in memory, sinks to draw to a display, sinks to loop over an image (useful for statistical operations, for example) and sinks to stream an image to disc. - - - The disc sink looks something like this: - - - - - - - - - - The sink keeps two buffers*, each as wide as the image. It starts threads as rapidly as it can up to the concurrency limit, filling each buffer with tiles** of calculated pixels, each thread calculating one tile at once. A separate background thread watches each buffer and, as soon as the last tile in a buffer finishes, writes that complete set of scanlines to disc using whatever image write library is appropriate. VIPS can write with libjpeg, libtiff, libpng and others. It then wipes the buffer and repositions it further down the image, ready for the next set of tiles to stream in. - - - These features in combination mean that, once a pipeline of image processing operations has been built, VIPS can run almost lock-free. This is very important for SMP scaling: you don’t want the synchronization overhead to scale with either the number of threads or the complexity of the pipeline of operations being performed. As a result, VIPS scales almost linearly with increasing numbers of threads: - - - - - - - - - - Number of CPUs is on the horizontal axis, speedup is on the vertical axis. Taken from the [[Benchmarks]] page. - - - (* there can actually be more than one, it allocate enough buffers to ensure that there are at least two tiles for every thread) - - - (** tiles can be any shape and size, VIPS has a tile hint system that operations use to tell sinks what tile geometry they prefer) - - - Operation cache - - - Because VIPS operations are free of side-effects*, you can cache them. Every time you call an operation, VIPS searches the cache for a previous call to the same operation with the same arguments. If it finds a match, you get the previous result again. This can give a huge speedup. - - - By default, VIPS caches the last 100 operation calls. You can also control the cache size by memory use or by files opened. - - - (* Some vips operations DO have side effects, for example, vips_draw_circle() will draw a circle on an image. These operations emit an invalidate signal on the image they are called on and this signal makes all downstream operations and caches drop their contents.) - - - Operation database and APIs - - - VIPS has around 300 image processing operations written in this style. Each operation is a GObject class. You can use the standard GObject calls to walk the class hierarchy and discover operations, and libvips adds a small amount of extra introspection metadata to handle things like optional arguments. - - - The C API is a set of simple wrappers which create class instances for you. The C++ API is a little fancier and adds things like automatic object lifetime management. The command-line interface uses introspection to run any vips operation in the class hierarchy. - - - There are bindings for many other languages on many platforms. Most of these bindings use the introspection system to generate the binding at run-time. - - - Snip - - - The VIPS GUI, nip2, has its own scripting language called Snip. Snip is a lazy, higher-order, purely functional, object oriented language. Almost all of nip2’s menus are implemented in it, and nip2 workspaces are Snip programs. - - - VIPS operations listed in the operation database appear as Snip functions. For example, abs can be used from Snip as: - - -// absolute value of image b -a = vips_call "abs" [b] []; - - - However, abs won’t work on anything except the primitive vips image type. It can’t be used on any class, or list or number. Definitions in _stdenv.dev wrap each VIPS operation as a higher level Snip operation. For example: - - -abs x - = oo_unary_function abs_op x, is_class x - = vips_call "abs" [x] [], is_image x - = abs_cmplx x, is_complex x - = abs_num x, is_real x - = abs_list x, is_real_list x - = abs_list (map abs_list x), is_matrix x - = error (_ "bad arguments to " ++ "abs") -{ - abs_op = Operator "abs" abs Operator_type.COMPOUND false; - - abs_list l = (sum (map square l)) ** 0.5; - - abs_num n - = n, n >= 0 - = -n; - - abs_cmplx c = ((re c)**2 + (im c)**2) ** 0.5; -} - - - This defines the behaviour of abs for the base Snip types (number, list, matrix, image and so on), then classes will use that to define operator behaviour on higher-level objects. - - - Now you can use: - - -// absolute value of anything -a = abs b; - - - and you ought to get sane behaviour for any object, including things like the Matrix class. - - - You can write Snip classes which present functions to the user as menu items. For example, Math.def has this: - - -Math_arithmetic_item = class - Menupullright "_Arithmetic" "basic arithmetic for objects" { - - Absolute_value_item = class - Menuaction "A_bsolute Value" "absolute value of x" { - action x = map_unary abs x; - } -} - - - Now the user can select an object and click Math / Abs to find the absolute value of that object. - - - - diff --git a/doc/Making-image-pyramids.xml b/doc/Making-image-pyramids.xml deleted file mode 100644 index 8c2f6510fd..0000000000 --- a/doc/Making-image-pyramids.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - Image pyramids 3 libvips - - - Pyramids How to use libvips to make image pyramids - - - libvips includes vips_dzsave(), an operation that can build image pyramids compatible with DeepZoom, Zoomify and Google Maps image viewers. It’s fast and can generate pyramids for large images using only a small amount of memory. - - - The TIFF writer, vips_tiffsave() can also build tiled pyramidal TIFF images, but that’s very simple to use. This page concentrates on the DeepZoom builder. - - - Run dzsave with no arguments to see a summary: - - -$ vips dzsave -save image to deepzoom file -usage: - dzsave in filename -where: - in - Image to save, input VipsImage - filename - Filename to save to, input gchararray -optional arguments: - basename - Base name to save to, input gchararray - layout - Directory layout, input VipsForeignDzLayout - default: dz - allowed: dz, zoomify, google, iiif, iiif3 - suffix - Filename suffix for tiles, input gchararray - overlap - Tile overlap in pixels, input gint - default: 1 - min: 0, max: 8192 - tile-size - Tile size in pixels, input gint - default: 254 - min: 1, max: 8192 - centre - Center image in tile, input gboolean - default: false - depth - Pyramid depth, input VipsForeignDzDepth - default: onepixel - allowed: onepixel, onetile, one - angle - Rotate image during save, input VipsAngle - default: d0 - allowed: d0, d90, d180, d270 - container - Pyramid container type, input VipsForeignDzContainer - default: fs - allowed: fs, zip - properties - Write a properties file to the output directory, input -gboolean - default: false - compression - ZIP deflate compression level, input gint - default: 0 - min: -1, max: 9 - strip - Strip all metadata from image, input gboolean - default: false - background - Background value, input VipsArrayDouble -operation flags: sequential nocache - - - You can also call vips_dzsave() from any language with a libvips binding, or by using .dz or .szi as an output file suffix. - - - Codestin Search App - - The --layout option sets the basic mode of operation. With no --layout, dzsave writes DeepZoom pyramids. For example: - - -$ vips dzsave huge.tif mydz - - - This will create a directory called mydz_files containing the image tiles, and write a file called mydz.dzi containing the image metadata.  - - - You can use the --suffix option to control how tiles are written. For example: - - -$ vips dzsave huge.tif mydz --suffix .jpg[Q=90] - - - will write JPEG tiles with the quality factor set to 90. You can set any format write options you like, see the API docs for vips_jpegsave() for details. - - - - Codestin Search App - - Use --layout zoomify to put dzsave into zoomify mode. For example: - - -$ vips dzsave huge.tif myzoom --layout zoomify - - - This will create a directory called myzoom containing a file called ImageProperties.xml with the image metadata in, and a series of directories called TileGroupn, each containing 256 image tiles. - - - As with DeepZoom, you can use --suffix to set jpeg quality. - - - - Codestin Search App - - Use --layout google to write Google maps-style pyramids. These are compatible with Leaflet. For example: - - -$ vips dzsave wtc.tif gmapdir --layout google - - - Will create a directory called gmapdir containing blank.png, the file to display for blank tiles, and a set of numbered directories, one for each zoom level. The pyramid can be sparse (blank tiles are not written). - - - As with DeepZoom, you can use --suffix to set jpeg quality. - - - Use --background to set the background colour. This is the colour displayed for bits of the pyramid not in the image (image edges, for example). By default, the image background is white. - - - Use --centre to add a border to the image large enough to centre the image within the lowest resolution tile. By default, images are not centred. - - - For example: - - -$ vips dzsave wtc.tif gmapdir --layout google --background 0 --centre - - - - Codestin Search App - - You can use --tile-size and --overlap to control how large the tiles are and how they overlap (obviously). They default to the correct values for the selected layout. - - - You can use --depth to control how deep the pyramid should be. Possible values are onepixel, onetile and one. onepixel means the image is shrunk until it fits within a single pixel. onetile means shrink until it fits with a tile. one means only write one pyramid layer (the highest resolution one). It defaults to the correct value for the selected layout. --depth one is handy for slicing up a large image into tiles (rather than a pyramid). - - - You can use --angle to do a 90, 180 or 270 degree rotate of an image during pyramid write. - - - You can use --container to set the container type. Normally dzsave will write a tree of directories, but with --container zip you’ll get a zip file instead. Use .zip as the directory suffix to turn on zip format automatically: - - -$ vips dzsave wtc.tif mypyr.zip - - - to write a zipfile containing the tiles. You can use .szi as a suffix to enable zip output as well. - - - - Codestin Search App - - You can use .dz as a filename suffix, meaning send the image to vips_dzsave(). This means you can write the output of any vips operation to a pyramid. For example: - - -$ vips extract_area huge.svs mypy.dz[layout=google] 100 100 10000 10000 - - - The arguments to extract_area are image-in, image-out, left, top, width, height. So this command will cut out a 10,000 by 10,000 pixel area from near the top-left-hand corner of an Aperio slide image, then build a pyramid in Google layout using just those pixels. - - - If you are working from OpenSlide images, you can use the shrink-on-load feature of many of those formats. For example: - - -$ vips dzsave CMU-1.mrxs[level=1] x - - - Will pull out level 1 (the half-resolution level of an MRXS slide) and make a pyramid from that. - - - - Codestin Search App - - If you are building vips from source you do need to check the summary at the end of configure carefully. You must have the libarchive-dev package for vips_dzsave() to work. - - - - - diff --git a/doc/Using-vipsthumbnail.xml b/doc/Using-vipsthumbnail.xml deleted file mode 100644 index ef4c9daef0..0000000000 --- a/doc/Using-vipsthumbnail.xml +++ /dev/null @@ -1,310 +0,0 @@ - - - - - - - Using vipsthumbnail 3 libvips - - - vipsthumbnail Introduction to vipsthumbnail, with examples - - - libvips ships with a handy command-line image thumbnailer, vipsthumbnail. This page introduces it, with some examples. - - - The thumbnailing functionality is implemented by vips_thumbnail() and vips_thumbnail_buffer() (which thumbnails an image held as a string), see the docs for details. You can use these functions from any language with a libvips binding. For example, from PHP you could write: - - -$filename = "image.jpg"; -$image = Vips\Image::thumbnail($filename, 200, ["height" => 200]); -$image->writeToFile("my-thumbnail.jpg"); - - - You can also call thumbnail_source from the CLI, for example: - - -$ cat k2.jpg | \ - vips thumbnail_source [descriptor=0] .jpg[Q=90] 128 | \ - cat > x.jpg - - - Codestin Search App - - vipsthumbnail supports the usual range of vips command-line options. A few of them are useful: - - - --vips-cache-trace shows each operation as libvips starts it. It can be handy to see exactly what operations vipsthumbnail is running for you. - - - --vips-leak turns on the libvips memory leak checker. As well as reporting leaks (hopefully there are none) it also tracks and reports peak memory use. - - - --vips-progress runs a progress indicator during computation. It can be useful to see where libvips is looping and how often. - - - --vips-info shows a higher level view of the operations that vipsthumbnail is running. - - - - Codestin Search App - - vipsthumbnail can process many images in one command. For example: - - -$ vipsthumbnail *.jpg - - - will make a thumbnail for every JPEG in the current directory. See the Output directory section below to see how to change where thumbnails are written. - - - vipsthumbnail will process images one after the other. You can get a good speedup by running several vipsthumbnails in parallel, depending on how much load you want to put on your system. For example: - - -$ parallel vipsthumbnail ::: *.jpg - - - - Codestin Search App - - You can set the bounding box of the generated thumbnail with the --size option. For example: - - -$ vipsthumbnail shark.jpg --size 200x100 - - - Use a single number to set a square bounding box. You can omit either number but keep the x to mean resize just based on that axis, for example: - - -$ vipsthumbnail shark.jpg --size 200x - - - Will resize to 200 pixels across, no matter what the height of the input image is. - - - You can append < or > to mean only resize if the image is smaller or larger than the target. - - - You can append ! to force a resize to the exact target size, breaking the aspect ratio. - - - - Codestin Search App - - vipsthumbnail normally shrinks images to fit within the box set by --size. You can use the --smartcrop option to crop to fill the box instead. Excess pixels are trimmed away using the strategy you set. For example: - - -$ vipsthumbnail owl.jpg --smartcrop attention -s 128 - - - Where owl.jpg is an off-centre composition: - - - - - - - - - - Gives this result: - - - - - - - - - - First it shrinks the image to get the vertical axis to 128 pixels, then crops down to 128 pixels across using the attention strategy. This one searches the image for features which might catch a human eye, see vips_smartcrop() for details. - - - - Codestin Search App - - 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. - - - vipsthumbnail has an option to perform image shrinking in linear space, that is, a colourspace where values are proportional to photon numbers. For example: - - -$ vipsthumbnail fred.jpg --linear - - - The downside is that in linear mode, none of the very fast shrink-on-load tricks that vipsthumbnail normally uses are possible, since the shrinking is done at encode time, not decode time, and is done in terms of CRT voltage, not photons. This can make linear light thumbnailing of large images extremely slow. - - - For example, for a 10,000 x 10,000 pixel JPEG I see: - - -$ time vipsthumbnail wtc.jpg -real 0m0.317s -user 0m0.292s -sys 0m0.016s -$ time vipsthumbnail wtc.jpg --linear -real 0m4.660s -user 0m4.640s -sys 0m0.016s - - - - Codestin Search App - - You set the thumbnail write parameters with the -o option. This is a pattern which the input filename is pasted into to produce the output filename. For example: - - -$ vipsthumbnail fred.jpg jim.tif -o tn_%s.jpg - - - For each of the files to be thumbnailed, vipsthumbnail will drop the extension (.jpg and .tif in this case) and then substitute the name into the -o option, replacing the %s So this example will write thumbnails to tn_fred.jpg and tn_jim.jpg. - - - If the pattern given to -o is an absolute path, any path components are dropped from the input filenames. This lets you write all of your thumbnails to a specific directory, if you want. For example: - - -$ vipsthumbnail fred.jpg ../jim.tif -o /mythumbs/tn_%s.jpg - - - Now both thumbnails will be written to /mythumbs, even though the source images are in different directories. - - - Conversely, if -o is set to a relative path, any path component from the input file is prepended. For example: - - -$ vipsthumbnail fred.jpg ../jim.tif -o mythumbs/tn_%s.jpg - - - Now both input files will have thumbnails written to a subdirectory of their current directory. - - - - Codestin Search App - - You can use -o to specify the thumbnail image format too. For example: - - -$ vipsthumbnail fred.jpg ../jim.tif -o tn_%s.png - - - Will write thumbnails in PNG format. - - - You can give options to the image write operation as a list of comma-separated arguments in square brackets. For example: - - -$ vipsthumbnail fred.jpg ../jim.tif -o tn_%s.jpg[Q=90,optimize_coding] - - - will write JPEG images with quality 90, and will turn on the libjpeg coding optimizer. - - - Check the image write operations to see all the possible options. For example: - - -$ vips jpegsave -save image to jpeg file -usage: - jpegsave in filename -where: - in - Image to save, input VipsImage - filename - Filename to save to, input gchararray -optional arguments: - Q - Q factor, input gint - default: 75 - min: 1, max: 100 - profile - Filename of ICC profile to embed, input gchararray - optimize-coding - Compute optimal Huffman coding tables, input gboolean - default: false - interlace - Generate an interlaced (progressive) jpeg, input gboolean - default: false - trellis-quant - Apply trellis quantisation to each 8x8 block, input gboolean - default: false - overshoot-deringing - Apply overshooting to samples with extreme values, input gboolean - default: false - optimize-scans - Split spectrum of DCT coefficients into separate scans, input gboolean - default: false - quant-table - Use predefined quantization table with given index, input gint - default: 0 - min: 0, max: 8 - subsample-mode - Select chroma subsample operation mode, input VipsForeignSubsample - default enum: auto - allowed enums: auto, on, off - restart-interval - Add restart markers every specified number of mcu, input gint - default: 0 - min: 0, max: 2147483647 - keep - Which metadata to retain, input VipsForeignKeep - default flags: exif:xmp:iptc:icc:other:all - allowed flags: none, exif, xmp, iptc, icc, other, all - background - Background value, input VipsArrayDouble - - - The keep option is especially useful. Many image have very large IPTC, ICC or XMP metadata items embedded in them, and removing these can give a large saving. - - - For example: - - -$ vipsthumbnail 42-32157534.jpg -$ ls -l tn_42-32157534.jpg --rw-r–r– 1 john john 6682 Nov 12 21:27 tn_42-32157534.jpg - - - keep=none almost halves the size of the thumbnail: - - -$ vipsthumbnail 42-32157534.jpg -o x.jpg[optimize_coding,keep=none] -$ ls -l x.jpg --rw-r–r– 1 john john 3600 Nov 12 21:27 x.jpg - - - - Codestin Search App - - vipsthumbnail 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. - - - For example: - - -$ vipsthumbnail shark.jpg -$ ls -l tn_shark.jpg --rw-r–r– 1 john john 7295 Nov  9 14:33 tn_shark.jpg - - - Now transform to sRGB and don’t attach a profile (you can also use keep=none, though that will remove all metadata from the image): - - -$ vipsthumbnail shark.jpg --export-profile srgb -o tn_shark.jpg[profile=none] -$ ls -l tn_shark.jpg --rw-r–r– 1 john john 4229 Nov  9 14:33 tn_shark.jpg - - - (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. For example, perhaps you somehow know that a JPEG is in Adobe98 space, even though it has no embedded profile. - - -$ vipsthumbnail kgdev.jpg --import-profile /my/profiles/a98.icm - - - - Codestin Search App - - Putting all this together, I suggest this as a sensible set of options: - - -$ vipsthumbnail fred.jpg \ - --size 128 \ - --export-profile srgb \ - -o tn_%s.jpg[optimize_coding,keep=none] - - - - - diff --git a/doc/binding.md b/doc/binding.md index e35ebe63ac..12420221b5 100644 --- a/doc/binding.md +++ b/doc/binding.md @@ -1,45 +1,37 @@ - - How to write bindings - 3 - libvips - +Title: Advanced > Writing bindings - - Binding - Writing bindings for libvips - - -There are full libvips bindings for quite a few environments now: C, C++, -command-line, Ruby, PHP, Lua, Python and JavaScript (node). +There are full libvips bindings for quite a few environments now, including +C, C++, command-line, Ruby, PHP, Lua, Python, Crystal, Elixir, and JavaScript +(Node.js). 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. -# Don't bind the top-level C API +## Don't bind the top-level C API -The libvips C API (vips_add() and so on) was designed to be easy for humans -to write. It is inconvenient and dangerous to use from other languages due -to its heavy use of varargs. +The libvips C API ([method@Image.add] and so on) was designed to be easy +for humans to write. It is inconvenient and dangerous to use from other +languages due to its heavy use of varargs. It's much better to use the layer below. This lower layer is structured as: -- Create operator. You can use vips_operation_new() to make a new - `VipsOperation` object from an operator nickname, like `"add"`. +- Create operator. You can use [ctor@Operation.new] to make a new + [class@Operation] object from an operator nickname, like `"add"`. -- Set parameters. You can loop over the operation with vips_argument_map() to - get the name and type of each input argument. For each argument, you - need to get the value from your language, convert to a `GValue`, then - use g_object_set_property() to set that value on the operator. +- Set parameters. You can use [method@Object.get_args] to + get the name and type of all arguments. For each argument, you need to + get the value from your language, convert to a [struct@GObject.Value], then + use [method@GObject.Object.set_property] to set that value on the operator. -- Execute with vips_cache_operation_build(). +- Execute with [func@cache_operation_build]. -- Extract results. Again, you loop over the operator arguments with - vips_argument_map(), but instead of inputs, this time you look for output - arguments. You extract their value with g_object_get_property(), and pass +- Extract results. Again, you loop over the arguments, + but instead of inputs, this time you look for output arguments. You + extract their value with [method@GObject.Object.get_property], and pass the value back to your language. -For example, you can execute vips_invert() like this: +For example, you can execute [method@Image.invert] like this: ```c /* compile with @@ -60,7 +52,7 @@ main(int argc, char **argv) GValue gvalue = G_VALUE_INIT; if (VIPS_INIT(argv[0])) - /* This shows the vips error buffer and quits with a fail exit + /* This shows the libvips error buffer and quits with a fail exit * code. */ vips_error_exit(NULL); @@ -94,7 +86,7 @@ main(int argc, char **argv) */ g_object_unref(in); - /* Call the operation. This will look up the operation+args in the vips + /* Call the operation. This will look up the operation+args in the libvips * operation cache and either return a previous operation, or build * this one. In either case, we have a new ref we must release. */ @@ -129,7 +121,7 @@ main(int argc, char **argv) } ``` -# Compiled language which can call C +## Compiled language which can call C The C++ binding uses this lower layer to define a function called `VImage::call()` which can call any libvips operator with a set of variable @@ -159,7 +151,7 @@ to get type-checked calls for at least the required operator arguments. The `VImage` class also adds automatic reference counting, constant expansion, operator overloads, and various other useful features. -# Dynamic language with FFI +## Dynamic language with FFI 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++, @@ -167,8 +159,8 @@ but use FFI to call into libvips and run operations. 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 `Image` class as libvips operators. In effect, the binding is generated at -runtime. +the [class@Image] class as libvips operators. In effect, the binding is generated +at runtime. # gobject-introspection @@ -195,11 +187,11 @@ users is likely to be tricky. If you have a choice, I would recommend simply using FFI. -# Documentation +## Documentation -You can generate searchable docs from a .gir (the thing that -is built from scanning libvips and which in turn turn the typelib is -made from) with g-ir-doc-tool, for example: +You can generate searchable docs from a `.gir` (the thing that is built +from scanning libvips and which in turn the typelib is made from) with +`g-ir-doc-tool`, for example: ```bash $ g-ir-doc-tool --language=Python -o ~/mydocs Vips-8.0.gir diff --git a/doc/binding.xml b/doc/binding.xml deleted file mode 100644 index ecaa616dc9..0000000000 --- a/doc/binding.xml +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - How to write bindings 3 libvips - - - Binding Writing bindings for libvips - - - There are full libvips bindings for quite a few environments now: C, C++, command-line, Ruby, PHP, Lua, Python and JavaScript (node). - - - 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. - - - Codestin Search App - - The libvips C API (vips_add() and so on) was designed to be easy for humans to write. It is inconvenient and dangerous to use from other languages due to its heavy use of varargs. - - - It’s much better to use the layer below. This lower layer is structured as: - - - - - Create operator. You can use vips_operation_new() to make a new VipsOperation object from an operator nickname, like "add". - - - - - Set parameters. You can loop over the operation with vips_argument_map() to get the name and type of each input argument. For each argument, you need to get the value from your language, convert to a GValue, then use g_object_set_property() to set that value on the operator. - - - - - Execute with vips_cache_operation_build(). - - - - - Extract results. Again, you loop over the operator arguments with vips_argument_map(), but instead of inputs, this time you look for output arguments. You extract their value with g_object_get_property(), and pass the value back to your language. - - - - - For example, you can execute vips_invert() like this: - - -/* compile with - * - * gcc -g -Wall callvips.c `pkg-config vips --cflags --libs` - * - */ - -#include <vips/vips.h> - -int -main(int argc, char **argv) -{ - VipsImage *in; - VipsImage *out; - VipsOperation *op; - VipsOperation *new_op; - GValue gvalue = G_VALUE_INIT; - - if (VIPS_INIT(argv[0])) - /* This shows the vips error buffer and quits with a fail exit - * code. - */ - vips_error_exit(NULL); - - /* This will print a table of any ref leaks on exit, very handy for - * development. - */ - vips_leak_set(TRUE); - - if (argc != 3) - vips_error_exit("usage: %s input-filename output-filename", - argv[0]); - - if (!(in = vips_image_new_from_file(argv[1], NULL))) - vips_error_exit(NULL); - - /* Create a new operator from a nickname. NULL for unknown operator. - */ - op = vips_operation_new("invert"); - - /* Init a gvalue as an image, set it to in, use the gvalue to set the - * operator property. - */ - g_value_init(&gvalue, VIPS_TYPE_IMAGE); - g_value_set_object(&gvalue, in); - g_object_set_property(G_OBJECT(op), "in", &gvalue); - g_value_unset(&gvalue); - - /* We no longer need in: op will hold a ref to it as long as it needs - * it. - */ - g_object_unref(in); - - /* 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 must release. - */ - if (!(new_op = vips_cache_operation_build(op))) { - g_object_unref(op); - vips_error_exit(NULL); - } - g_object_unref(op); - op = new_op; - - /* Now get the result from op. g_value_get_object() does not ref the - * object, so we need to make a ref for out to hold. - */ - g_value_init(&gvalue, VIPS_TYPE_IMAGE); - g_object_get_property(G_OBJECT(op), "out", &gvalue); - out = VIPS_IMAGE(g_value_get_object(&gvalue)); - g_object_ref(out); - g_value_unset(&gvalue); - - /* All done: we can unref op. The output objects from op actually hold - * refs back to it, so before we can unref op, we must unref them. - */ - vips_object_unref_outputs(VIPS_OBJECT(op)); - g_object_unref(op); - - if (vips_image_write_to_file(out, argv[2], NULL)) - vips_error_exit(NULL); - - g_object_unref(out); - - return 0; -} - - - - Codestin Search App - - The C++ binding uses this lower layer to define a function called VImage::call() which can call any libvips operator with a set of variable arguments. - - - A small Python program walks the set of all libvips operators and generates a set of static bindings. For example: - - -VImage -VImage::invert(VOption *options) const -{ - VImage out; - - call("invert", (options ? options : VImage::option()) - ->set("in", *this) - ->set("out", &out)); - - return out; -} - - - So from C++ you can call any libvips operator (though without static typechecking) with VImage::call(), or use the member functions on VImage to get type-checked calls for at least the required operator arguments. - - - The VImage class also adds automatic reference counting, constant expansion, operator overloads, and various other useful features. - - - - Codestin Search App - - 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. - - - 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 Image class as libvips operators. In effect, the binding is generated at runtime. - - - - Codestin Search App - - 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 gobject-introspection 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 it’s as simple as: - - -from gi.repository import Vips - - - You can now use all of the libvips introspection machinery, as noted above. - - - Unfortunately g-o-i has some strong disadvantages. It is not very portable, since you will need a g-o-i layer for whatever platform you are targeting; it does not cross-compile well, since typelibs include a lot of very-low level data (such as exact structure layouts); and installation for your users is likely to be tricky. - - - If you have a choice, I would recommend simply using FFI. - - - - Codestin Search App - - You can generate searchable docs from a .gir (the thing that is built from scanning libvips and which in turn turn the typelib is made from) with g-ir-doc-tool, for example: - - -$ g-ir-doc-tool --language=Python -o ~/mydocs Vips-8.0.gir - - - Then to view them, either: - - -$ yelp ~/mydocs - - - Or perhaps: - - -$ cd ~/mydocs -$ yelp-build html . - - - To make HTML docs. This is an easy way to see what you can call in the library. - - - - - diff --git a/doc/check-sections.py b/doc/check-sections.py new file mode 100755 index 0000000000..8b0dfe1f4f --- /dev/null +++ b/doc/check-sections.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +import sys +import argparse +import xml.etree.ElementTree as ET +from pathlib import Path + + +def register_all_namespaces(filename): + namespaces = dict([node for _, node in ET.iterparse(filename, events=['start-ns'])]) + for ns in namespaces: + ET.register_namespace(ns, namespaces[ns]) + + +def check_sections(args): + tree = ET.parse(args.gir) + root = tree.getroot() + + register_all_namespaces(args.gir) + namespace = { + 'goi': 'http://www.gtk.org/introspection/core/1.0', + 'glib': 'http://www.gtk.org/introspection/glib/1.0', + } + + namespace_node = root.find('goi:namespace', namespace) + + file_dict = {} + for file in args.files: + content = Path(file).read_text() + comment_start_idx = content.find('', comment_start_idx) + section_covers = content[comment_start_idx + 5:comment_end_idx] + + file_dict[section_covers] = {'file': file, 'content': content} + + tag_parser_dict = { + f'{{{namespace['goi']}}}alias': lambda n, _ : f'[alias@{n.attrib['name']}]', + f'{{{namespace['goi']}}}bitfield': lambda n, _ : f'[flags@{n.attrib['name']}]', + f'{{{namespace['goi']}}}callback': lambda n, _ : f'[callback@{n.attrib['name']}]', + f'{{{namespace['goi']}}}class': lambda n, _ : f'[class@{n.attrib['name']}]', + f'{{{namespace['goi']}}}constructor': lambda n, p : f'[ctor@{p}{n.attrib['name']}]', + f'{{{namespace['goi']}}}method': lambda n, p : f'[method@{p}{n.attrib['name']}]', + f'{{{namespace['goi']}}}constant': lambda n, _ : f'[const@{n.attrib['name']}]', + f'{{{namespace['goi']}}}enumeration': lambda n, _ : f'[enum@{n.attrib['name']}]', + f'{{{namespace['goi']}}}function-macro': lambda n, _ : f'[func@{n.attrib['name']}]', + f'{{{namespace['goi']}}}function': lambda n, p : f'[func@{p}{n.attrib['name']}]', + # each struct has its own documentation + # f'{{{namespace['goi']}}}record': lambda n, _ : f'[struct@{n.attrib['name']}]', + # struct and enum members do not need to be listed + # f'{{{namespace['goi']}}}field': lambda n, p : f'[struct@Vips.{p}{n.attrib['name']}]', + # f'{{{namespace['goi']}}}member': lambda n, p : f'[enum@Vips.{p}{n.attrib['name']}]', + } + + exitcode = 0 + + parent_map = {c: p for p in namespace_node.iter() for c in p} + for node in parent_map: + if 'moved-to' in node.attrib: + continue + + child = node.find('goi:doc', namespace) + if child is None: + continue + + filename = child.attrib['filename'] + section = next((k for k in file_dict.keys() if filename.startswith(k)), None) + if section is None: + continue + + parser_method = tag_parser_dict.get(node.tag, None) + if parser_method is None: + continue + + parent_name = parent_map.get(node, {}).attrib.get('name') or '' + if parent_name == 'Vips': + parent_name = '' + if parent_name: + parent_name += '.' + + symbol = parser_method(node, parent_name) + if f'* {symbol}' not in file_dict[section]['content']: + print(f"ERROR: Symbol '{symbol}' is not listed in '{file_dict[section]['file']}'", + file=sys.stderr) + exitcode = 1 + + sys.exit(exitcode) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--gir', help='input GIR file', type=Path) + parser.add_argument('files', help='markdown files', type=Path, nargs=argparse.REMAINDER) + + args = parser.parse_args() + check_sections(args) + + +if __name__ == '__main__': + main() diff --git a/doc/cite.md b/doc/cite.md new file mode 100644 index 0000000000..e9c4641612 --- /dev/null +++ b/doc/cite.md @@ -0,0 +1,15 @@ +Title: Citing libvips + +Cupitt, J., Martinez, K., Fuller, L. and Wolthuizen, K. A. (2025) +[The libvips image processing library]( +https://www.southampton.ac.uk/~km2/papers/2025/vips-ist-preprint.pdf). In Proceedings of Electronic +Imaging 2025, Burlingame. + +Martinez, K. and Cupitt, J. (2005) +[VIPS -- a highly tuned image processing software architecture]( +http://eprints.ecs.soton.ac.uk/12371). In Proceedings of IEEE +International Conference on Image Processing 2, pp. 574-577, Genova. + +Cupitt, J. and Martinez, K. (1996) +[VIPS: An image processing system for large images]( +http://eprints.soton.ac.uk/252227), Proc. SPIE, vol. 2663, pp. 19--28. diff --git a/doc/Developer-checklist.md b/doc/developer-checklist.md similarity index 77% rename from doc/Developer-checklist.md rename to doc/developer-checklist.md index e2057ffac6..3c73497748 100644 --- a/doc/Developer-checklist.md +++ b/doc/developer-checklist.md @@ -1,40 +1,32 @@ - - Developer checklist - 3 - libvips - - - - Dev checklist - Checklist for libvips users - +Title: Using > Checklist for programmers using libvips libvips is a slightly unusual library and you may need to take some of its stranger features into account when you design software that uses it. -## If you can, use `thumbnail`, not `resize` +## If you can, use [ctor@Image.thumbnail], not [method@Image.resize] -The `thumbnail` operation combines load and resize into one step. This lets it -take advantage of format library features, such as shrink on load, and can -lead to a large improvement in speed and a large drop in memory use. +The [ctor@Image.thumbnail] operation combines load and resize into one step. +This lets it take advantage of format library features, such as shrink on +load, and can lead to a large improvement in speed and a large drop in memory +use. For example, with this JPEG image: -``` +```bash $ vipsheader nina.jpg nina.jpg: 6048x4032 uchar, 3 bands, srgb, jpegload ``` I see: -``` +```bash $ /usr/bin/time -f %M:%e vips resize nina.jpg x.jpg 0.1 123648:0.23 ``` 124 MB of RAM and 0.23s to shink by a factor of 10. With `thumbnail` it's: -``` +```bash $ /usr/bin/time -f %M:%e vips thumbnail nina.jpg x.jpg 605 68864:0.08 ``` @@ -43,30 +35,32 @@ Now it's 68 MB of memory and 0.08s -- half the memory use, and 3x faster. In fact the improvement is better than that, since the `vips` command takes a while to start and needs a fair amount of memory: -``` +```bash $ /usr/bin/time -f %M:%e vips > /dev/null 31232:0.02 ``` -31 MB and 0.02s, so `thumbnail` is really 2.5x less memory and 4x faster. +31 MB and 0.02s, so [ctor@Image.thumbnail] is really 2.5x less memory and +4x faster. You can see much larger improvements with other formats, and quality will -often be better as well, since `thumbnail` will automatically premultiply and -can render vector images directly at the correct size. +often be better as well, since [ctor@Image.thumbnail] will automatically +premultiply and can render vector images directly at the correct size. -## Don't use `thumbnail_image` +## Don't use [method@Image.thumbnail_image] It's just there for emergencies. It can't do any of the rendering tricks, -so it's no faster than `resize`. Use `thumbnail` if you can. +so it's not faster than [method@Image.resize]. Use [ctor@Image.thumbnail] if +you can. ## Use sequential mode if you can -This is a hint you pass to `new_from_file` and friends that signals that you +This is a hint you pass to [ctor@Image.new_from_file] and friends that signals that you will only scan this image in the direction that the underlying load library supports. This can give a useful improvement in speed and reduction in memory use in many cases. -See [the "How it opens files" chapter](How-it-opens-files.html) for background +See [the "How it opens files" chapter](how-it-opens-files.html) for background on this feature. ## Use longer pipelines if you can @@ -93,18 +87,19 @@ This can raise memory use, of course. ## Adjust the order of operations in pipelines -If you can, put large resizes right at the start (see `thumbnail` above), -then area filters (sharpen, for example), and finally any point operations. +If you can, put large resizes right at the start (see [ctor@Image.thumbnail] +above), then area filters (sharpen, for example), and finally any point +operations. ## Only enable the load libraries you need libvips after version 8.13 has a system for enabling and disabling image load libraries at runtime, see: -https://www.libvips.org/2022/05/28/What's-new-in-8.13.html + You can usually improve security and avoid memory spikes by only enabling -the image formats you really need. If you are handling untrusted data, +the image formats you really need. If you are handling untrusted data, I would set the `VIPS_BLOCK_UNTRUSTED` env var and only use the loaders we have tested for security. @@ -120,7 +115,7 @@ There are two main checks that are very worthwhile: 1. Sanity check image dimensions to protect you from decompression bombs like those described at - https://www.bamsoftware.com/hacks/deflate.html + 2. Check for interlaced (also called progressive) images. @@ -131,7 +126,7 @@ There are two main checks that are very worthwhile: is in memory, which prevents any streaming processing and hugely increases memory use. For example: -``` +```bash $ /usr/bin/time -f %M:%e vipsthumbnail big-progressive.jpg 3732224:4.23 $ vips copy big-progressive.jpg x.jpg diff --git a/doc/Examples.md b/doc/examples.md similarity index 61% rename from doc/Examples.md rename to doc/examples.md index 7e501effc8..6089f20e37 100644 --- a/doc/Examples.md +++ b/doc/examples.md @@ -1,21 +1,12 @@ - - Examples - 3 - libvips - - - - libvips examples - A few example Python programs using libvips - +Title: Using > Python examples This page shows a few libvips examples using Python. They will work with small syntax changes in any language with a libvips binding. The libvips test suite is written in Python and exercises every operation -in the API. It's also a useful source of examples. +in the API. It's also a useful source of examples. -# Average a region of interest box on an image +## Average a region of interest box on an image ```python #!/usr/bin/python3 @@ -33,7 +24,50 @@ roi = image.crop(left, top, width, height) print('average:', roi.avg()) ``` -# Build huge image mosaic +## libvips and numpy + +You can use `pyvips.Image.new_from_memory()` to make a libvips image from +an area of memory. The memory array needs to be laid out band-interleaved, +as a set of scanlines, with no padding between lines. + +```python +#!/usr/bin/python3 + +import sys +import time + +import pyvips +from PIL import Image +import numpy as np + +if len(sys.argv) != 3: + print(f'usage: {sys.argv[0]} input-filename output-filename') + sys.exit(-1) + +# load with PIL +start_pillow = time.time() +pillow_img = np.asarray(Image.open(sys.argv[1])) +print('Pillow Time:', time.time()-start_pillow) +print('original shape', pillow_img.shape) + +# load with vips to a numpy array +start_vips = time.time() +img = pyvips.Image.new_from_file(sys.argv[1], access='sequential') +np_3d = img.numpy() +print('Vips Time:', time.time()-start_vips) +print('final shape', np_3d.shape) + +# verify we have the same result +print('Sum of the Differences:', np.sum(np_3d-pillow_img)) + +# make a vips image from the numpy array +vi = pyvips.Image.new_from_array(np_3d) + +# and write back to disc for checking +vi.write_to_file(sys.argv[2]) +``` + +## Build huge image mosaic This makes a 100,000 x 100,000 black image, then inserts all the images you pass on the command-line into it at random positions. libvips is able to run @@ -66,7 +100,7 @@ sys 0m8.936s It completes in just under two minutes on this laptop, and needs about 7gb of RAM to run. It would need about the same amount of memory for a -full-colour RGB image, I was just keen to keep disc usage down. +full-colour RGB image, I was just keen to keep disc usage down. If you wanted to handle transparency, or if you wanted mixed CMYK and RGB images, you'd need to do some more work to convert them all into the same diff --git a/doc/extending.md b/doc/extending.md new file mode 100644 index 0000000000..aeddd45148 --- /dev/null +++ b/doc/extending.md @@ -0,0 +1,348 @@ +Title: Advanced > Writing operators + +This section runs quickly through adding a simple operator to libvips. +For more information, see [class@Operation] and [class@Region]. A good +starting point for a new operation is a similar one in libvips. + +All libvips operations are subclasses of [class@Operation], which in turn +subclasses [class@Object] and then [class@GObject.Object]. You add an +operation to libvips by defining a new subclass of [class@Operation] and +arranging for its `class_init()` to be called, perhaps by calling its +`get_type()` function. + +## The class and object structures + +First you need to define a new object struct and a new class struct. + +```c +typedef struct _Negative { + VipsOperation parent_instance; + + VipsImage *in; + VipsImage *out; + + int image_max; + +} Negative; + +typedef struct _NegativeClass { + VipsOperationClass parent_class; + + /* No new class members needed for this op. + */ + +} NegativeClass; +``` + +This operation will find the photographic negative of an unsigned 8-bit +image, optionally letting you specify the value which the pixels "pivot" +about. It doesn't need any class members (ie. values common to all operations +of this type), so the second struct is empty. See the source to +[method@Image.invert] for a more complete version of this operation that's +actually in the library. + +[class@GObject.Object] has a handy macro to write some of the boilerplate for +you. + +```c +G_DEFINE_TYPE(Negative, negative, VIPS_TYPE_OPERATION); +``` + +[func@GObject.DEFINE_TYPE] defines a function called `negative_get_type()`, +which registers this new class and returns its [alias@GObject.Type] (a +pointer-sized integer). `negative_get_type()` in turn needs two functions, +`negative_init()`, to initialise a new instance, and `negative_class_init()`, +to initialise a new class. + +## Class and object initialisation + +`negative_init()` is very simple, it just sets the default value for our +optional parameter. + +```c +static void +negative_init(Negative *negative) +{ + negative->image_max = 255; +} +``` + +`negative_class_init()` is more complicated: it has to set various fields in +various superclasses and define the operation's parameters. + +```c +static void +negative_class_init(NegativeClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + VipsObjectClass *object_class = VIPS_OBJECT_CLASS(class); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "negative"; + object_class->description = "photographic negative"; + object_class->build = negative_build; + + VIPS_ARG_IMAGE(class, "in", 1, + "Input", + "Input image", + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET(Negative, in)); + + VIPS_ARG_IMAGE(class, "out", 2, + "Output", + "Output image", + VIPS_ARGUMENT_REQUIRED_OUTPUT, + G_STRUCT_OFFSET(Negative, out)); + + VIPS_ARG_INT(class, "image_max", 4, + "Image maximum", + "Maximum value in image: pivot about this", + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET(Negative, image_max), + 0, 255, 255); +} +``` + +In [class@GObject.Object], it needs to set the getters and setters for this +class. libvips has a generic get/set system, so any subclass of +[class@VipsObject] needs to use the libvips ones. + +In [class@VipsObject], it needs to set the operation +[property@VipsObject:nickname] and [property@VipsObject:description], and set +a build function (see below). [property@VipsObject:nickname] is used to refer +to this operation in the API, [property@VipsObject:description] is used to +explain this operation to users and will be translated into their language. + +Finally, it needs to define the arguments the constructor for this class +takes. There are a set of handy macros for doing this, see [func@ARG_INT] +and friends. + +The first few parameters are always the same and mean: class pointer for +argument, argument name, argument priority (bindings expect required arguments +in order of priority), long argument name (this one is internationalised +and displayed to users), description (again, users can see this), some flags +describing the argument, and finally the position of the member in the struct. + +Integer arguments take three more values: the minimum, maximum and +default value for the argument. + +## The `build()` function + +The build function is the thing [class@VipsObject] calls during object construction, +after all arguments have been supplied and before the object is used. It +has two roles: to verify that arguments are correct, and then to construct +the object. After `build()`, the object is expected to be ready for use. + +```c +static int +negative_build(VipsObject *object) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); + Negative *negative = (Negative *) object; + + if (VIPS_OBJECT_CLASS(negative_parent_class)->build(object)) + return -1; + + if (vips_check_uncoded(class->nickname, negative->in) || + vips_check_format(class->nickname, negative->in, VIPS_FORMAT_UCHAR)) + return -1; + + g_object_set(object, "out", vips_image_new(), NULL); + + if (vips_image_pipelinev(negative->out, + VIPS_DEMAND_STYLE_THINSTRIP, negative->in, NULL)) + return -1; + + if (vips_image_generate(negative->out, + vips_start_one, + negative_generate, + vips_stop_one, + negative->in, negative)) + return -1; + + return 0; +} +``` + +`negative_build()` first chains up to the superclass: this will check that +all input arguments have been supplied and are sane. + +Next, it adds its own checks. This is a demo operation, so we just work for +uncoded, unsigned 8-bit images. There are a lot of convenience functions +like [func@check_format], see the docs. + +Next, it creates the output image. This needs to be set with [method@Object.set] +so that libvips can see that it has been assigned. libvips will also handle the +reference counting for you. + +[method@Image.pipelinev] links our new image onto the input image and notes +that this operation prefers to work in lines. You can request other input +geometries, see [enum@DemandStyle]. + +The geometry hint is just a hint, an operation needs to be able to supply any +size [class@Region] on request. If you must have a certain size request, you +can put a cache in the pipeline after your operation, see +[method@Image.linecache] and [method@Image.tilecache]. You can also make requests +to your operation ordered, see [method@Image.sequential]. + +Finally, [method@Image.generate] attaches a set of callbacks to the output +image to generate chunks of it on request. [func@start_one] and [func@stop_one] +are convenience functions that make the input region for you, see below. + +## The `generate()` function + +The `generate()` function does the actual image processing. `negative_generate()` +(of type [callback@GenerateFn], supplied to [method@Image.generate] above) is +called whenever some pixels of our output image are required. + +```c +static int +negative_generate(VipsRegion *out_region, + void *vseq, void *a, void *b, gboolean *stop) +{ + /* The area of the output region we have been asked to make. + */ + VipsRect *r = &out_region->valid; + + /* The sequence value ... the thing returned by vips_start_one(). + */ + VipsRegion *ir = (VipsRegion *) vseq; + + VipsImage *in = (VipsImage *) a; + Negative *negative = (Negative *) b; + int line_size = r->width * negative->in->Bands; + + int x, y; + + /* Request matching part of input region. + */ + if (vips_region_prepare(ir, r)) + return -1; + + for (y = 0; y < r->height; y++) { + unsigned char *p = (unsigned char *) + VIPS_REGION_ADDR(ir, r->left, r->top + y); + unsigned char *q = (unsigned char *) + VIPS_REGION_ADDR(out_region, r->left, r->top + y); + + for (x = 0; x < line_size; x++) + q[x] = negative->image_max - p[x]; + } + + return 0; +} +``` + +This has to calculate a section of the output image. The output +[class@Region], `out_region`, contains a [struct@Rect] called `valid` +which is the area needing calculation. This call to `negative_generate()` +must somehow make this part of `out_region` contain pixel data. + +`vseq` is the sequence value. This is the per-thread state for this generate, +created (in this example) by [func@start_one]. In this simple case it's +just a [class@Region] defined on the input image. If you need more per-thread +state you can write your own start and stop functions and have a struct +you create and pass as a sequence value. There are plenty of examples in +the libvips source code, see [method@Image.rank]. + +`a` and `b` are the last two arguments to [method@Image.generate] above. +`stop` is a bool pointer you can set to stop computation early. +[method@Image.min] on an unsigned int image, for example, will set `stop` +as soon as it sees a zero, and will not scan the entire image. + +The first thing `negative_generate()` does is use [method@Region.prepare] to +ask for the corresponding pixels from the input image. Operations which do +coordinate transforms or which need an area of input for each output point +will need to calculate a new rect before calling [method@Region.prepare]. + +Finally, it can calculate some pixels. `negative_generate()` loops over the +valid area of the output and calls [func@REGION_ADDR] for each line. This +macro is reasonably quick, but it's best not to call it for each pixel. Once +per line is fine though. + +## Adding to libvips + +To add the operation to libvips, just call `negative_get_type()`. You can +include the source in your program, or use [GModule]( +https://docs.gtk.org/gmodule/) to make a binary plugin that will be loaded +by libvips at startup. There are some [example plugins available]( +https://github.com/jcupitt/vips-gmic). + +You can then use `negative` from any of the libvips interfaces. For example, +in Python you'd use it like this: + +```python +out = in.negative(image_max=128) +``` + +From the command-line it'd look like this: + +```bash +$ vips negative in.png out.tif --image-max 128 +``` + +And from C like this: + +```c +VipsImage *in; +VipsImage *out; +if (vips_call("negative", in, &out, "image_max", 128, NULL)) + ... error +``` + +Unfortunately that will do almost no compile-time type checking, so all +libvips operations have a tiny extra wrapper to add a bit of safety. For +example: + +```c +static int +negative(VipsImage *in, VipsImage **out, ...) +{ + va_list ap; + int result; + + va_start(ap, out); + result = vips_call_split("negative", ap, in, out); + va_end(ap); + + return result; +} +``` + +And now you can write: + +```c +if (negative(in, &out, "image_max", 128, NULL)) + ... error +``` + +and it's at least a bit safer. + +## Other types of operation + +Change the `_build()` function to make other types of operation. + +Use [method@Image.generate] with [func@start_many] to make operations which +demand pixels from more than one image at once, such as image plus image. + +Use [method@Image.sink] instead of [method@Image.generate] to loop over an +image and calculate a value. libvips uses this for the statistics operations, +like [method@Image.avg]. + +Use [method@Image.wio_input] to get an entire image into memory so you can +read it with a pointer. This will obviously not scale well to very large +images, but some operations, like FFTs or flood-fill, need the whole image +to be available at once. + +Make area operations, like filters, by enlarging the [struct@Rect] that +`_generate()` is given before calling [method@Region.prepare]. You can enlarge +the input image, so that the output image is the same size as the original +input, by using [method@Image.embed] within the `_build()` function. + +Make things like flips and rotates by making larger changes to the [struct@Rect] +in `_generate()`. + +Make zero-copy operations, like [method@Image.insert], with +[method@Region.region]. diff --git a/doc/extending.xml b/doc/extending.xml deleted file mode 100644 index 492efa76a7..0000000000 --- a/doc/extending.xml +++ /dev/null @@ -1,462 +0,0 @@ - - - - - Extending VIPS - 3 - VIPS Library - - - - Extending - How to add operations to VIPS - - - - Codestin Search App - - This section runs quickly through adding a simple operator to VIPS. - For more information, see #VipsOperation and #VipsRegion. A good - starting point for a new operation is a similar one in the VIPS library. - - - - All VIPS operations are subclasses of #VipsOperation, which in turn - subclasses #VipsObject and then %GObject. You add an operation to VIPS - by defining a new subclass of #VipsOperation and arranging for its - class_init() to be called, perhaps by calling its get_type() - function. - - - - - Codestin Search App - - - First you need to define a new - object struct and a new class struct. - - -typedef struct _Negative { - VipsOperation parent_instance; - - VipsImage *in; - VipsImage *out; - - int image_max; - -} Negative; - -typedef struct _NegativeClass { - VipsOperationClass parent_class; - - /* No new class members needed for this op. - */ - -} NegativeClass; - - - - - This operation will find the photographic negative of an unsigned - 8-bit image, optionally letting you specify the value which the pixels - "pivot" about. It doesn't need any class members (ie. values common - to all operations of this type), so the second struct is empty. See - the source to vips_invert() for a more complete version of this - operation that's actually in the library. - - - - %GObject has a handy macro to write some of the boilerplate for you. - - -G_DEFINE_TYPE(Negative, negative, VIPS_TYPE_OPERATION); - - - G_DEFINE_TYPE() defines a function called negative_get_type(), - which registers this new class and returns its %GType (a - pointer-sized integer). negative_get_type() in turn needs two - functions, negative_init(), to initialise a new instance, and - negative_class_init(), to initialise a new class. - - - - - Codestin Search App - - negative_init() is very simple, it just sets the default value for - our optional parameter. - - -static void -negative_init(Negative *negative) -{ - negative->image_max = 255; -} - - - - - negative_class_init() is more complicated: it has to set various - fields in various superclasses and define the operation's parameters. - - -static void -negative_class_init(NegativeClass *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(class); - VipsObjectClass *object_class = VIPS_OBJECT_CLASS(class); - - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; - - object_class->nickname = "negative"; - object_class->description = "photographic negative"; - object_class->build = negative_build; - - VIPS_ARG_IMAGE(class, "in", 1, - "Input", - "Input image", - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET(Negative, in)); - - VIPS_ARG_IMAGE(class, "out", 2, - "Output", - "Output image", - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET(Negative, out)); - - VIPS_ARG_INT(class, "image_max", 4, - "Image maximum", - "Maximum value in image: pivot about this", - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET(Negative, image_max), - 0, 255, 255); -} - - - - - In %GObject, it needs to set the getters and setters for this class. vips - has a generic get/set system, so any subclass of #VipsObject needs to - use the vips ones. - - - - In #VipsObject, it needs to set the operation @nickname and @description, - and set a build function (see below). @nickname is used to refer to - this operation in the API, @description is used to explain this - operation to users and will be translated into their language. - - - - Finally, it needs to define the arguments the constructor for this class - takes. There are a set of handy macros for doing this, see - VIPS_ARG_INT() and friends. - - - - The first few - parameters are always the same and mean: class pointer for argument, - argument name, argument priority (bindings expect required arguments in - order of priority), long argument name (this one is internationalised - and displayed to users), description (again, users can see this), - some flags describing the argument, and finally the position of the - member in the struct. - - - - Integer arguments take three more values: the minimum, maximum and - default value for the argument. - - - - - Codestin Search App - - The build function is the thing #VipsObject calls during object - construction, after all arguments have been supplied and before the - object is used. It has two roles: to verify that arguments are correct, - and then to construct the object. After build(), the object is expected - to be ready for use. - - -static int -negative_build(VipsObject *object) -{ - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); - Negative *negative = (Negative *) object; - - if (VIPS_OBJECT_CLASS(negative_parent_class)->build(object)) - return -1; - - if (vips_check_uncoded(class->nickname, negative->in) || - vips_check_format(class->nickname, negative->in, VIPS_FORMAT_UCHAR)) - return -1; - - g_object_set(object, "out", vips_image_new(), NULL); - - if (vips_image_pipelinev(negative->out, - VIPS_DEMAND_STYLE_THINSTRIP, negative->in, NULL)) - return -1; - - if (vips_image_generate(negative->out, - vips_start_one, - negative_generate, - vips_stop_one, - negative->in, negative)) - return -1; - - return 0; -} - - - - - negative_build() first chains up to the superclass: this will check - that all input arguments have been supplied and are sane. - - - - Next, it adds its own checks. This is a demo operation, so we just - work for uncoded, unsigned 8-bit images. There are a lot of - convenience functions like vips_check_format(), see the docs. - - - - Next, it creates the output image. This needs to be set with - g_object_set() so that vips can see that it has been assigned. vips - will also handle the reference counting for you. - - - - vips_image_pipelinev() links our new image onto the input image and - notes that this operation prefers to work in lines. You can request - other input geometries, see #VipsDemandStyle. - - - - The geometry hint is just a hint, an operation needs to be able to - supply any size - #VipsRegion on request. If you must have a certain size request, you can - put a cache in the pipeline after your operation, see vips_linecache() - and vips_tilecache(). You can also make requests to your operation - ordered, see vips_sequential(). - - - - Finally, vips_image_generate() attaches a set of callbacks to the - output image to generate chunks of it on request. vips_start_one() - and vips_stop_one() are convenience functions that make the input - region for you, see below. - - - - - Codestin Search App - - - The generate() function does the actual image processing. - negative_generate() (of type #VipsGenerateFn, supplied to - vips_image_generate() above) is - called whenever some pixels of our output image are required. - - -static int -negative_generate(VipsRegion *out_region, - void *vseq, void *a, void *b, gboolean *stop) -{ - /* The area of the output region we have been asked to make. - */ - VipsRect *r = &out_region->valid; - - /* The sequence value ... the thing returned by vips_start_one(). - */ - VipsRegion *ir = (VipsRegion *) vseq; - - VipsImage *in = (VipsImage *) a; - Negative *negative = (Negative *) b; - int line_size = r->width * negative->in->Bands; - - int x, y; - - /* Request matching part of input region. - */ - if (vips_region_prepare(ir, r)) - return -1; - - for (y = 0; y < r->height; y++) { - unsigned char *p = (unsigned char *) - VIPS_REGION_ADDR(ir, r->left, r->top + y); - unsigned char *q = (unsigned char *) - VIPS_REGION_ADDR(out_region, r->left, r->top + y); - - for (x = 0; x < line_size; x++) - q[x] = negative->image_max - p[x]; - } - - return 0; -} - - - - - This has to calculate a section of the output image. The output - #VipsRegion, @out_region, contains a #VipsRect called @valid which is the - area needing calculation. This call to negative_generate() must - somehow make this part of @out_region contain pixel data. - - - - @vseq is the sequence value. This is the - per-thread state for this generate, created (in this example) by - vips_start_one(). In this simple case it's just a #VipsRegion defined on - the input image. If you need more per-thread state you can write your - own start and stop functions and have a struct you create and pass as a - sequence value. There are plenty of examples in the VIPS source code, - see vips_rank(). - - - - @a and @b are the last two arguments to vips_image_generate() above. - @stop is a bool pointer you can set to stop computation early. vips_min() - on an unsigned int image, for example, will set @stop as soon as it sees - a zero, and will not scan the entire image. - - - - The first thing negative_generate() does is - use vips_region_prepare() to - ask for the corresponding pixels from the input image. Operations which - do coordinate transforms or which need an area of input for each output - point will need to calculate a new rect before calling - vips_region_prepare(). - - - - Finally, it can calculate some pixels. negative_generate() loops - over the valid area of the output and calls VIPS_REGION_ADDR() for each - line. This macro is reasonaly quick, but it's best not to call it for - each pixel. Once per line is fine though. - - - - - Codestin Search App - - To add the operation to vips, just call negative_get_type(). You can - include the source in your program, or use %GModule to make a binary - plugin that will be loaded by libvips at startup. There are some example - plugins available. - - - - You - can then use @negative from any of the vips interfaces. For example, - in Python you'd use it like this: - - -out = in.negative(image_max = 128) - - - - - From the command-line it'd look like this: - - -$ vips negative in.png out.tif --image-max 128 - - - - - And from C like this: - - -VipsImage *in; -VipsImage *out; -if (vips_call("negative", in, &out, "image_max", 128, NULL)) -... error - - - - - Unfortunately that will do almost no compile-time type checking, - so all vips operations have a tiny extra wrapper to add a bit of - safety. For example: - - -static int -negative(VipsImage *in, VipsImage **out, ...) -{ - va_list ap; - int result; - - va_start(ap, out); - result = vips_call_split("negative", ap, in, out); - va_end(ap); - - return result; -} - - - - - And now you can write: - - -if (negative(in, &out, "image_max", 128, NULL)) -... error - - - and it's at least a bit safer. - - - - - Codestin Search App - - Change the _build() function to make other types of operation. - - - - Use vips_image_generate() with vips_start_many() to make operations - which demand pixels from more than one image at once, such as image - plus image. - - - - Use vips_sink() instead of vips_image_generate() to loop over an image - and calculate a value. vips uses this for the statistics operations, - like vips_avg(). - - - - Use vips_image_wio_input() to get an entire image into memory so you - can read it with a pointer. This will obviously not scale well to - very large images, but some operations, like FFTs or flood-fill, need - the whole image to be available at once. - - - - Make area operations, like filters, by enlarging the #VipsRect that - _generate() is given before calling vips_region_prepare(). You can - enlarge the input image, so that the output image is the same size as - the original input, by using vips_embed() within the _build() function. - - - - Make things like flips and rotates by making larger changes to the - #VipsRect in _generate(). - - - - Make zero-copy operations, like vips_insert(), with vips_region_region(). - - - - - diff --git a/doc/file-format.md b/doc/file-format.md new file mode 100644 index 0000000000..756ddf7c6e --- /dev/null +++ b/doc/file-format.md @@ -0,0 +1,89 @@ +Title: Technical background > The libvips file format + +libvips has a simple, native file format. It's very fast, there is no image +size limit, and it supports arbitrary metadata. Although few other programs +can read these images (though recent versions of ImageMagick do have basic +support for the `.v` format), it can be useful as an intermediate format +for command-line processing. For example: + +```bash +$ vips invert input.tif t.v +$ vips gamma t.v output.tif +``` + +is faster than using `.tif` for the temporary intermediate image. This +section documents the libvips file format. + +libvips comes with a command-line program called `vipsedit` which is useful +for destructively changing fields in a `.v` image. The `vipsheader` program +can be used to extract any metadata. + +libvips files come in three parts. First, there is a 64-byte header, containing +an identifying magic number and a set of very basic fields, such as image +width in pixels. Next, the image data is stored as a set of band-interleaved +scanlines, from the top of the image to the bottom. Finally, after the +pixel data comes an optional block of XML containing any extra metadata, +such as an ICC profile or the EXIF data. + +## The header + +The fields in the libvips header are always stored least-significant byte first +(Intel ordering). Only the most basic information about the image is in +the header: most metadata is stored in the XML extension block after the +pixel data. + +If the first four bytes of the file are in order 08 f2 a6 b6, the image +data (see the next section) is stored in Intel byte order (LSB first) +and will need to be swapped if read on a SPARC-style machine (MSB first). +If the magic number is b6 a6 f2 08, the image data is in SPARC order and +will need to swapped if read on an Intel-style machine. libvips does this +swapping automatically. + +| Bytes | Type | libvips name | Meaning | +|---------|-----------------------|------------------|-------------------------------------------| +| 0 - 3 | | | Magic number: 08 f2 a6 b6, or b6 a6 f2 08 | +| 4 - 7 | int32 | `width` | Width of image, in pixels | +| 8 - 11 | int32 | `height` | Height of image, in pixels | +| 12 - 15 | int32 | `bands` | Number of image bands (channels) | +| 16 - 19 | | | Unused | +| 20 - 23 | [enum@BandFormat] | `format` | Band format | +| 24 - 27 | [enum@Coding] | `coding` | Image coding | +| 28 - 31 | [enum@Interpretation] | `interpretation` | Pixel interpretation | +| 32 - 35 | float32 | `xres` | Horizontal resolution, in pixels per mm | +| 36 - 39 | float32 | `yres` | Vertical resolution, in pixels per mm | +| 40 - 47 | | | Unused | +| 48 - 51 | int32 | `xoffset` | Horizontal offset of origin, in pixels | +| 52 - 55 | int32 | `yoffset` | Vertical offset of origin, in pixels | +| 56 - 63 | | | Unused | + +## The image data + +If `coding` is set to [enum@Vips.Coding.NONE], pixels are stored in native C +format, that is, the native format of the machine that wrote the data. If you +open a big-endian image on a little-endian machine, libvips will automatically +byte-swap for you. libvips has 10 band formats, see [enum@BandFormat]. +Image data is stored as a simple list of scanlines, from the top of the +image to the bottom. Pixels are band-interleaved, so RGBRGBRGBRGB, for +example. There is no padding at the end of scanlines. + +If `coding` is set to [enum@Vips.Coding.LABQ], each pixel is four bytes, with +10 bits for L\* and 11 bits for each of a\* and b\*. These 32 bits are packed +into 4 bytes, with the most significant 8 bits of each value in the first +3 bytes, and the left-over bits packed into the final byte as 2:3:3. + +If `coding` is set to [enum@Vips.Coding.RAD], each pixel is RGB or XYZ float, +with 8 bits of mantissa and then 8 bits of exponent, shared between the +three channels. This coding style is used by the Radiance family of programs +(and the HDR format) commonly used for HDR imaging. + +Other values of `coding` can set other coding styles. Use +[func@IMAGE_SIZEOF_IMAGE] to calculate the size of the image data section. + +## The metadata + +Following the image data is a chunk of XML holding a simple list of name-value +pairs. Binary data is encoded with base64. Use [method@Image.set] and friends +to set and get image metadata. + +You can use `vipsheader -f getext some_file.v` to get the XML from a libvips +image, and `vipsedit --setext some_file.v < file.xml` to replace the XML. diff --git a/doc/file-format.xml b/doc/file-format.xml deleted file mode 100644 index dc9afe0d15..0000000000 --- a/doc/file-format.xml +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - The VIPS file format - 3 - VIPS Library - - - - File format - The VIPS file format - - - - Codestin Search App - - VIPS has a simple, native file format. It's very fast, there is no image - size limit, and it supports - arbitrary metadata. Although few other programs can read these images - (though recent versions of ImageMagick do have basic support for - .vips - format), it can be useful as an intermediate format for command-line - processing. For example: - - -$ vips invert input.tif t.v -$ vips gamma t.v output.tif - - - is faster than using .tif for the temporary intermediate - image. This section documents the VIPS file format. - - - - VIPS comes with a command-line program called - vipsedit which is useful for destructively changing - fields in a vips image. The vipsheader program can be - used to extract any metadata. - - - - VIPS files come in three parts. First, there is a 64-byte header, - containing an identifying magic number and a set of very basic fields, - such as image width in pixels. Next, the image data is stored as a set - of band-interleaved scanlines, from the top of the image to the bottom. - Finally, after the pixel data comes an optional block of XML containing - any extra metadata, such as an ICC profile or the EXIF data. - - - - - Codestin Search App - - The fields in the VIPS header are always stored least-significant byte - first (Intel ordering). Only the most basic information about the image - is in the header: most metadata is stored in the XML extension block - after the pixel data. - - - - If the first four bytes of the file are in order 08 f2 a6 b6, the image - data (see the next section) - is stored in Intel byte order (LSB first) and will need to be swapped - if read on a SPARC-style machine (MSB first). - If the magic number is b6 a6 f2 08, the image data is in SPARC order - and will need to swapped if read on an Intel-style machine. libvips does - this swapping automatically. - - - Codestin Search App - - - - Bytes - Type - VIPS name - Meaning - - - - - - 0 -- 3 - - - VIPS magic number: 08 f2 a6 b6, or b6 a6 f2 08 - - - - 4 -- 7 - int32 - width - Width of image, in pixels - - - - 8 -- 11 - int32 - height - Height of image, in pixels - - - - 12 -- 15 - int32 - bands - Number of image bands - - - - 16 -- 19 - - - Unused - - - - 20 -- 23 - #VipsBandFormat - format - Band format - - - - 24 -- 27 - #VipsCoding - coding - Image coding - - - - 28 -- 31 - #VipsInterpretation - interpretation - Pixel interpretation - - - - 32 -- 35 - float32 - xres - Horizontal resolution, in pixels per millimetre - - - - 36 -- 39 - float32 - yres - Vertical resolution, in pixels per millimetre - - - - 40 -- 47 - - - Unused - - - - 48 -- 51 - int32 - xoffset - Horizontal offset of origin, in pixels - - - - 52 -- 55 - int32 - yoffset - Vertical offset of origin, in pixels - - - - 56 -- 63 - - - Unused - - - - -
-
- -
- - - Codestin Search App - - If coding is set to #VIPS_CODING_NONE, pixels are stored in - native C format, that is, the native format of the - machine that wrote the data. If you open a big-endian image on a - little-endian machine, VIPS will automatically byte-swap for you. - VIPS has 10 band formats, see #VipsBandFormat. - Image data is stored as a simple list of scanlines, from the top of the - image to the bottom. Pixels are band-interleaved, so RGBRGBRGBRGB, - for example. There is no padding at the end of scanlines. - - - - If coding is set to #VIPS_CODING_LABQ, each pixel is four - bytes, with 10 bits for L* and 11 bits for each of a* and b*. These - 32 bits are packed into 4 bytes, with the most significant 8 bits of each - value in the first 3 bytes, and the left-over bits packed into the final - byte as 2:3:3. - - - - If coding is set to #VIPS_CODING_RAD, each pixel is - RGB or XYZ float, with 8 bits of mantissa - and then 8 bits of exponent, shared between the three channels. This - coding style is used by the Radiance family of programs (and the HDR - format) commonly used for HDR imaging. - - - - Other values of coding can set other coding styles. Use - VIPS_IMAGE_SIZEOF_IMAGE() to calculate the size of the image data - section. - - - - - - Codestin Search App - - Following the image data is a chunk of XML holding a simple list of - name-value pairs. Binary data is encoded with base64. Use - vips_image_set() and friends to set and get image metadata. - - - - You can use vipsheader -f getext some_file.v to get - the XML from a VIPS image, and - vipsedit --setext some_file.v < file.xml to - replace the XML. - - - - -
diff --git a/doc/fixup-gir-for-doc.py b/doc/fixup-gir-for-doc.py new file mode 100755 index 0000000000..c6e507ac78 --- /dev/null +++ b/doc/fixup-gir-for-doc.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + +import argparse +import xml.etree.ElementTree as ET +from pathlib import Path + + +def register_all_namespaces(filename): + namespaces = dict([node for _, node in ET.iterparse(filename, events=['start-ns'])]) + for ns in namespaces: + ET.register_namespace(ns, namespaces[ns]) + + +def fixup_gir_for_doc(args): + tree = ET.parse(args.in_path) + root = tree.getroot() + + register_all_namespaces(args.in_path) + namespace = { + 'goi': 'http://www.gtk.org/introspection/core/1.0' + } + + namespace_node = root.find('goi:namespace', namespace) + image_node = namespace_node.find('goi:class[@name="Image"]', namespace) + blob_node = namespace_node.find('goi:record[@name="Blob"]', namespace) + + # A list of functions that needs to be converted to an Image constructor. + # Note that all functions containing "load" are already converted. + image_ctors = [ + 'black', + 'eye', + 'fractsurf', + 'gaussmat', + 'gaussnoise', + 'grey', + 'identity', + 'logmat', + 'mask_butterworth', + 'mask_butterworth_band', + 'mask_butterworth_ring', + 'mask_fractal', + 'mask_gaussian', + 'mask_gaussian_band', + 'mask_gaussian_ring', + 'mask_ideal', + 'mask_ideal_band', + 'mask_ideal_ring', + 'perlin', + 'sdf', + 'sines', + 'system', + 'text', + 'thumbnail', + 'thumbnail_buffer', + 'thumbnail_source', + 'tonelut', + 'worley', + 'xyz', + 'zone', + ] + + # Functions that take multiple images as input argument ... make them + # part of the Image class. + # Keep-in-sync with gen-function-list.py + image_funcs = [ + 'arrayjoin', + 'bandjoin', + 'bandrank', + 'composite', + 'sum', + 'switch', + ] + + for node in namespace_node.findall('goi:function', namespace): + name = node.get('name') + if name == 'profile_load': + namespace_node.remove(node) + + node.tag = 'constructor' + blob_node.append(node) + elif 'load' in name or name in image_ctors: + namespace_node.remove(node) + + node.tag = 'constructor' + image_node.append(node) + elif name in image_funcs: + namespace_node.remove(node) + image_node.append(node) + + tree.write(args.out_path, encoding='utf-8', xml_declaration=True) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('in_path', help='input file', type=Path) + parser.add_argument('out_path', help='output file', type=Path) + + args = parser.parse_args() + fixup_gir_for_doc(args) + + +if __name__ == '__main__': + main() diff --git a/doc/function-list.md b/doc/function-list.md new file mode 100644 index 0000000000..283e5f635c --- /dev/null +++ b/doc/function-list.md @@ -0,0 +1,359 @@ +Title: Operator index / Alphabetical + +libvips has a set of operators, each of which computes some useful image +processing operation. Each operator is implemented as a [class@GObject.Object] +class, for example `VipsGamma`. Classes are identified by their unique +[property@VipsObject:nickname], in this case `gamma`. + +From the command-line, C++ and most language bindings, you use the nickname +to call the operator. For example in C++: + +```c++ +vips::VImage fred = ...; +vips::VImage jim = fred.gamma(); +``` + +or Python: + +```python +fred = jim.gamma() +``` + +libvips has a set of C wrapper functions for calling operators, in this +case [method@Image.gamma]: + +```c +VipsImage *fred = ...; +VipsImage *jim; + +if (vips_gamma(fred, &jim, NULL)) + ...error; +``` + +Some operators have many C convenience functions. + +# All libvips operators + +This table lists all the libvips operators with their C convenience functions +and a short description. It's supposed to be useful for searching. See the +API docs each function links to for more details. + +| Operator | Description | C functions | +| -------- | ----------- | ----------- | +| `CMC2LCh` | Transform lch to cmc | [method@Image.CMC2LCh] | +| `CMYK2XYZ` | Transform cmyk to xyz | [method@Image.CMYK2XYZ] | +| `HSV2sRGB` | Transform hsv to srgb | [method@Image.HSV2sRGB] | +| `LCh2CMC` | Transform lch to cmc | [method@Image.LCh2CMC] | +| `LCh2Lab` | Transform lch to lab | [method@Image.LCh2Lab] | +| `Lab2LCh` | Transform lab to lch | [method@Image.Lab2LCh] | +| `Lab2LabQ` | Transform float lab to labq coding | [method@Image.Lab2LabQ] | +| `Lab2LabS` | Transform float lab to signed short | [method@Image.Lab2LabS] | +| `Lab2XYZ` | Transform cielab to xyz | [method@Image.Lab2XYZ] | +| `LabQ2Lab` | Unpack a labq image to float lab | [method@Image.LabQ2Lab] | +| `LabQ2LabS` | Unpack a labq image to short lab | [method@Image.LabQ2LabS] | +| `LabQ2sRGB` | Convert a labq image to srgb | [method@Image.LabQ2sRGB] | +| `LabS2Lab` | Transform signed short lab to float | [method@Image.LabS2Lab] | +| `LabS2LabQ` | Transform short lab to labq coding | [method@Image.LabS2LabQ] | +| `XYZ2CMYK` | Transform xyz to cmyk | [method@Image.XYZ2CMYK] | +| `XYZ2Lab` | Transform xyz to lab | [method@Image.XYZ2Lab] | +| `XYZ2Yxy` | Transform xyz to yxy | [method@Image.XYZ2Yxy] | +| `XYZ2scRGB` | Transform xyz to scrgb | [method@Image.XYZ2scRGB] | +| `Yxy2XYZ` | Transform yxy to xyz | [method@Image.Yxy2XYZ] | +| `abs` | Absolute value of an image | [method@Image.abs] | +| `add` | Add two images | [method@Image.add] | +| `addalpha` | Append an alpha channel | [method@Image.addalpha] | +| `affine` | Affine transform of an image | [method@Image.affine] | +| `analyzeload` | Load an analyze6 image | [ctor@Image.analyzeload] | +| `arrayjoin` | Join an array of images | [func@Image.arrayjoin] | +| `autorot` | Autorotate image by exif tag | [method@Image.autorot] | +| `avg` | Find image average | [method@Image.avg] | +| `bandbool` | Boolean operation across image bands | [method@Image.bandbool], [method@Image.bandand], [method@Image.bandor], [method@Image.bandeor], [method@Image.bandmean] | +| `bandfold` | Fold up x axis into bands | [method@Image.bandfold] | +| `bandjoin` | Bandwise join a set of images | [func@Image.bandjoin], [method@Image.bandjoin2] | +| `bandjoin_const` | Append a constant band to an image | [method@Image.bandjoin_const], [method@Image.bandjoin_const1] | +| `bandmean` | Band-wise average | [method@Image.bandmean] | +| `bandrank` | Band-wise rank of a set of images | [func@Image.bandrank] | +| `bandunfold` | Unfold image bands into x axis | [method@Image.bandunfold] | +| `black` | Make a black image | [ctor@Image.black] | +| `boolean` | Boolean operation on two images | [method@Image.boolean], [method@Image.andimage], [method@Image.orimage], [method@Image.eorimage], [method@Image.lshift], [method@Image.rshift] | +| `boolean_const` | Boolean operations against a constant | [method@Image.boolean_const], [method@Image.andimage_const], [method@Image.orimage_const], [method@Image.eorimage_const], [method@Image.lshift_const], [method@Image.rshift_const], [method@Image.boolean_const1], [method@Image.andimage_const1], [method@Image.orimage_const1], [method@Image.eorimage_const1], [method@Image.lshift_const1], [method@Image.rshift_const1] | +| `buildlut` | Build a look-up table | [method@Image.buildlut] | +| `byteswap` | Byteswap an image | [method@Image.byteswap] | +| `canny` | Canny edge detector | [method@Image.canny] | +| `case` | Use pixel values to pick cases from an array of images | [method@Image.case] | +| `cast` | Cast an image | [method@Image.cast], [method@Image.cast_uchar], [method@Image.cast_char], [method@Image.cast_ushort], [method@Image.cast_short], [method@Image.cast_uint], [method@Image.cast_int], [method@Image.cast_float], [method@Image.cast_double], [method@Image.cast_complex], [method@Image.cast_dpcomplex] | +| `clamp` | Clamp values of an image | [method@Image.clamp] | +| `colourspace` | Convert to a new colorspace | [method@Image.colourspace] | +| `compass` | Convolve with rotating mask | [method@Image.compass] | +| `complex` | Perform a complex operation on an image | [method@Image.complex], [method@Image.polar], [method@Image.rect], [method@Image.conj] | +| `complex2` | Complex binary operations on two images | [method@Image.complex2], [method@Image.cross_phase] | +| `complexform` | Form a complex image from two real images | [method@Image.complexform] | +| `complexget` | Get a component from a complex image | [method@Image.complexget], [method@Image.real], [method@Image.imag] | +| `composite` | Blend an array of images with an array of blend modes | [func@Image.composite] | +| `composite2` | Blend a pair of images with a blend mode | [method@Image.composite2] | +| `conv` | Convolution operation | [method@Image.conv] | +| `conva` | Approximate integer convolution | [method@Image.conva] | +| `convasep` | Approximate separable integer convolution | [method@Image.convasep] | +| `convf` | Float convolution operation | [method@Image.convf] | +| `convi` | Int convolution operation | [method@Image.convi] | +| `convsep` | Separable convolution operation | [method@Image.convsep] | +| `copy` | Copy an image | [method@Image.copy] | +| `countlines` | Count lines in an image | [method@Image.countlines] | +| `csvload` | Load csv | [ctor@Image.csvload] | +| `csvload_source` | Load csv | [ctor@Image.csvload_source] | +| `csvsave` | Save image to csv | [method@Image.csvsave] | +| `csvsave_target` | Save image to csv | [method@Image.csvsave_target] | +| `dE00` | Calculate de00 | [method@Image.dE00] | +| `dE76` | Calculate de76 | [method@Image.dE76] | +| `dECMC` | Calculate decmc | [method@Image.dECMC] | +| `deviate` | Find image standard deviation | [method@Image.deviate] | +| `divide` | Divide two images | [method@Image.divide] | +| `draw_circle` | Draw a circle on an image | [method@Image.draw_circle], [method@Image.draw_circle1] | +| `draw_flood` | Flood-fill an area | [method@Image.draw_flood], [method@Image.draw_flood1] | +| `draw_image` | Paint an image into another image | [method@Image.draw_image] | +| `draw_line` | Draw a line on an image | [method@Image.draw_line], [method@Image.draw_line1] | +| `draw_mask` | Draw a mask on an image | [method@Image.draw_mask], [method@Image.draw_mask1] | +| `draw_rect` | Paint a rectangle on an image | [method@Image.draw_rect], [method@Image.draw_rect1], [method@Image.draw_point], [method@Image.draw_point1] | +| `draw_smudge` | Blur a rectangle on an image | [method@Image.draw_smudge] | +| `dzsave` | Save image to deepzoom file | [method@Image.dzsave] | +| `dzsave_buffer` | Save image to dz buffer | [method@Image.dzsave_buffer] | +| `dzsave_target` | Save image to deepzoom target | [method@Image.dzsave_target] | +| `embed` | Embed an image in a larger image | [method@Image.embed] | +| `extract_area` | Extract an area from an image | [method@Image.extract_area], [method@Image.crop] | +| `extract_band` | Extract band from an image | [method@Image.extract_band] | +| `eye` | Make an image showing the eye's spatial response | [ctor@Image.eye] | +| `falsecolour` | False-color an image | [method@Image.falsecolour] | +| `fastcor` | Fast correlation | [method@Image.fastcor] | +| `fill_nearest` | Fill image zeros with nearest non-zero pixel | [method@Image.fill_nearest] | +| `find_trim` | Search an image for non-edge areas | [method@Image.find_trim] | +| `fitsload` | Load a fits image | [ctor@Image.fitsload] | +| `fitsload_source` | Load fits from a source | [ctor@Image.fitsload_source] | +| `fitssave` | Save image to fits file | [method@Image.fitssave] | +| `flatten` | Flatten alpha out of an image | [method@Image.flatten] | +| `flip` | Flip an image | [method@Image.flip] | +| `float2rad` | Transform float rgb to radiance coding | [method@Image.float2rad] | +| `fractsurf` | Make a fractal surface | [ctor@Image.fractsurf] | +| `freqmult` | Frequency-domain filtering | [method@Image.freqmult] | +| `fwfft` | Forward fft | [method@Image.fwfft] | +| `gamma` | Gamma an image | [method@Image.gamma] | +| `gaussblur` | Gaussian blur | [method@Image.gaussblur] | +| `gaussmat` | Make a gaussian image | [ctor@Image.gaussmat] | +| `gaussnoise` | Make a gaussnoise image | [ctor@Image.gaussnoise] | +| `getpoint` | Read a point from an image | [method@Image.getpoint] | +| `gifload` | Load gif with libnsgif | [ctor@Image.gifload] | +| `gifload_buffer` | Load gif with libnsgif | [ctor@Image.gifload_buffer] | +| `gifload_source` | Load gif from source | [ctor@Image.gifload_source] | +| `gifsave` | Save as gif | [method@Image.gifsave] | +| `gifsave_buffer` | Save as gif | [method@Image.gifsave_buffer] | +| `gifsave_target` | Save as gif | [method@Image.gifsave_target] | +| `globalbalance` | Global balance an image mosaic | [method@Image.globalbalance] | +| `gravity` | Place an image within a larger image with a certain gravity | [method@Image.gravity] | +| `grey` | Make a grey ramp image | [ctor@Image.grey] | +| `grid` | Grid an image | [method@Image.grid] | +| `heifload` | Load a heif image | [ctor@Image.heifload] | +| `heifload_buffer` | Load a heif image | [ctor@Image.heifload_buffer] | +| `heifload_source` | Load a heif image | [ctor@Image.heifload_source] | +| `heifsave` | Save image in heif format | [method@Image.heifsave] | +| `heifsave_buffer` | Save image in heif format | [method@Image.heifsave_buffer] | +| `heifsave_target` | Save image in heif format | [method@Image.heifsave_target] | +| `hist_cum` | Form cumulative histogram | [method@Image.hist_cum] | +| `hist_entropy` | Estimate image entropy | [method@Image.hist_entropy] | +| `hist_equal` | Histogram equalisation | [method@Image.hist_equal] | +| `hist_find` | Find image histogram | [method@Image.hist_find] | +| `hist_find_indexed` | Find indexed image histogram | [method@Image.hist_find_indexed] | +| `hist_find_ndim` | Find n-dimensional image histogram | [method@Image.hist_find_ndim] | +| `hist_ismonotonic` | Test for monotonicity | [method@Image.hist_ismonotonic] | +| `hist_local` | Local histogram equalisation | [method@Image.hist_local] | +| `hist_match` | Match two histograms | [method@Image.hist_match] | +| `hist_norm` | Normalise histogram | [method@Image.hist_norm] | +| `hist_plot` | Plot histogram | [method@Image.hist_plot] | +| `hough_circle` | Find hough circle transform | [method@Image.hough_circle] | +| `hough_line` | Find hough line transform | [method@Image.hough_line] | +| `icc_export` | Output to device with icc profile | [method@Image.icc_export] | +| `icc_import` | Import from device with icc profile | [method@Image.icc_import] | +| `icc_transform` | Transform between devices with icc profiles | [method@Image.icc_transform] | +| `identity` | Make a 1d image where pixel values are indexes | [ctor@Image.identity] | +| `ifthenelse` | Ifthenelse an image | [method@Image.ifthenelse] | +| `insert` | Insert image @sub into @main at @x, @y | [method@Image.insert] | +| `invert` | Invert an image | [method@Image.invert] | +| `invertlut` | Build an inverted look-up table | [method@Image.invertlut] | +| `invfft` | Inverse fft | [method@Image.invfft] | +| `join` | Join a pair of images | [method@Image.join] | +| `jp2kload` | Load jpeg2000 image | [ctor@Image.jp2kload] | +| `jp2kload_buffer` | Load jpeg2000 image | [ctor@Image.jp2kload_buffer] | +| `jp2kload_source` | Load jpeg2000 image | [ctor@Image.jp2kload_source] | +| `jp2ksave` | Save image in jpeg2000 format | [method@Image.jp2ksave] | +| `jp2ksave_buffer` | Save image in jpeg2000 format | [method@Image.jp2ksave_buffer] | +| `jp2ksave_target` | Save image in jpeg2000 format | [method@Image.jp2ksave_target] | +| `jpegload` | Load jpeg from file | [ctor@Image.jpegload] | +| `jpegload_buffer` | Load jpeg from buffer | [ctor@Image.jpegload_buffer] | +| `jpegload_source` | Load image from jpeg source | [ctor@Image.jpegload_source] | +| `jpegsave` | Save image to jpeg file | [method@Image.jpegsave] | +| `jpegsave_buffer` | Save image to jpeg buffer | [method@Image.jpegsave_buffer] | +| `jpegsave_mime` | Save image to jpeg mime | [method@Image.jpegsave_mime] | +| `jpegsave_target` | Save image to jpeg target | [method@Image.jpegsave_target] | +| `jxlload` | Load jpeg-xl image | [ctor@Image.jxlload] | +| `jxlload_buffer` | Load jpeg-xl image | [ctor@Image.jxlload_buffer] | +| `jxlload_source` | Load jpeg-xl image | [ctor@Image.jxlload_source] | +| `jxlsave` | Save image in jpeg-xl format | [method@Image.jxlsave] | +| `jxlsave_buffer` | Save image in jpeg-xl format | [method@Image.jxlsave_buffer] | +| `jxlsave_target` | Save image in jpeg-xl format | [method@Image.jxlsave_target] | +| `labelregions` | Label regions in an image | [method@Image.labelregions] | +| `linear` | Calculate (a * in + b) | [method@Image.linear], [method@Image.linear1] | +| `linecache` | Cache an image as a set of lines | [method@Image.linecache] | +| `logmat` | Make a laplacian of gaussian image | [ctor@Image.logmat] | +| `magickload` | Load file with imagemagick | [ctor@Image.magickload] | +| `magickload_buffer` | Load buffer with imagemagick | [ctor@Image.magickload_buffer] | +| `magicksave` | Save file with imagemagick | [method@Image.magicksave] | +| `magicksave_buffer` | Save image to magick buffer | [method@Image.magicksave_buffer] | +| `mapim` | Resample with a map image | [method@Image.mapim] | +| `maplut` | Map an image though a lut | [method@Image.maplut] | +| `mask_butterworth` | Make a butterworth filter | [ctor@Image.mask_butterworth] | +| `mask_butterworth_band` | Make a butterworth_band filter | [ctor@Image.mask_butterworth_band] | +| `mask_butterworth_ring` | Make a butterworth ring filter | [ctor@Image.mask_butterworth_ring] | +| `mask_fractal` | Make fractal filter | [ctor@Image.mask_fractal] | +| `mask_gaussian` | Make a gaussian filter | [ctor@Image.mask_gaussian] | +| `mask_gaussian_band` | Make a gaussian filter | [ctor@Image.mask_gaussian_band] | +| `mask_gaussian_ring` | Make a gaussian ring filter | [ctor@Image.mask_gaussian_ring] | +| `mask_ideal` | Make an ideal filter | [ctor@Image.mask_ideal] | +| `mask_ideal_band` | Make an ideal band filter | [ctor@Image.mask_ideal_band] | +| `mask_ideal_ring` | Make an ideal ring filter | [ctor@Image.mask_ideal_ring] | +| `match` | First-order match of two images | [method@Image.match] | +| `math` | Apply a math operation to an image | [method@Image.math], [method@Image.sin], [method@Image.cos], [method@Image.tan], [method@Image.asin], [method@Image.acos], [method@Image.atan], [method@Image.sinh], [method@Image.cosh], [method@Image.tanh], [method@Image.asinh], [method@Image.acosh], [method@Image.atanh], [method@Image.exp], [method@Image.exp10], [method@Image.log], [method@Image.log10] | +| `math2` | Binary math operations | [method@Image.math2], [method@Image.pow], [method@Image.wop], [method@Image.atan2] | +| `math2_const` | Binary math operations with a constant | [method@Image.math2_const], [method@Image.andimage_const], [method@Image.orimage_const], [method@Image.eorimage_const], [method@Image.lshift_const], [method@Image.rshift_const], [method@Image.math2_const1], [method@Image.andimage_const1], [method@Image.orimage_const1], [method@Image.eorimage_const1], [method@Image.lshift_const1], [method@Image.rshift_const1] | +| `matload` | Load mat from file | [ctor@Image.matload] | +| `matrixinvert` | Invert a matrix | [method@Image.matrixinvert] | +| `matrixload` | Load matrix | [ctor@Image.matrixload] | +| `matrixload_source` | Load matrix | [ctor@Image.matrixload_source] | +| `matrixmultiply` | Multiply two matrices | [method@Image.matrixmultiply] | +| `matrixprint` | Print matrix | [method@Image.matrixprint] | +| `matrixsave` | Save image to matrix | [method@Image.matrixsave] | +| `matrixsave_target` | Save image to matrix | [method@Image.matrixsave_target] | +| `max` | Find image maximum | [method@Image.max] | +| `maxpair` | Maximum of a pair of images | [method@Image.maxpair] | +| `measure` | Measure a set of patches on a color chart | [method@Image.measure] | +| `merge` | Merge two images | [method@Image.merge] | +| `min` | Find image minimum | [method@Image.min] | +| `minpair` | Minimum of a pair of images | [method@Image.minpair] | +| `morph` | Morphology operation | [method@Image.morph] | +| `mosaic` | Mosaic two images | [method@Image.mosaic] | +| `mosaic1` | First-order mosaic of two images | [method@Image.mosaic1] | +| `msb` | Pick most-significant byte from an image | [method@Image.msb] | +| `multiply` | Multiply two images | [method@Image.multiply] | +| `niftiload` | Load nifti volume | [ctor@Image.niftiload] | +| `niftiload_source` | Load nifti volumes | [ctor@Image.niftiload_source] | +| `niftisave` | Save image to nifti file | [method@Image.niftisave] | +| `openexrload` | Load an openexr image | [ctor@Image.openexrload] | +| `openslideload` | Load file with openslide | [ctor@Image.openslideload] | +| `openslideload_source` | Load source with openslide | [ctor@Image.openslideload_source] | +| `pdfload` | Load pdf from file | [ctor@Image.pdfload] | +| `pdfload_buffer` | Load pdf from buffer | [ctor@Image.pdfload_buffer] | +| `pdfload_source` | Load pdf from source | [ctor@Image.pdfload_source] | +| `percent` | Find threshold for percent of pixels | [method@Image.percent] | +| `perlin` | Make a perlin noise image | [ctor@Image.perlin] | +| `phasecor` | Calculate phase correlation | [method@Image.phasecor] | +| `pngload` | Load png from file | [ctor@Image.pngload] | +| `pngload_buffer` | Load png from buffer | [ctor@Image.pngload_buffer] | +| `pngload_source` | Load png from source | [ctor@Image.pngload_source] | +| `pngsave` | Save image to file as png | [method@Image.pngsave] | +| `pngsave_buffer` | Save image to buffer as png | [method@Image.pngsave_buffer] | +| `pngsave_target` | Save image to target as png | [method@Image.pngsave_target] | +| `ppmload` | Load ppm from file | [ctor@Image.ppmload] | +| `ppmload_source` | Load ppm base class | [ctor@Image.ppmload_source] | +| `ppmsave` | Save image to ppm file | [method@Image.ppmsave] | +| `ppmsave_target` | Save to ppm | [method@Image.ppmsave_target] | +| `premultiply` | Premultiply image alpha | [method@Image.premultiply] | +| `prewitt` | Prewitt edge detector | [method@Image.prewitt] | +| `profile` | Find image profiles | [method@Image.profile] | +| `profile_load` | Load named icc profile | [ctor@Blob.profile_load] | +| `project` | Find image projections | [method@Image.project] | +| `quadratic` | Resample an image with a quadratic transform | [method@Image.quadratic] | +| `rad2float` | Unpack radiance coding to float rgb | [method@Image.rad2float] | +| `radload` | Load a radiance image from a file | [ctor@Image.radload] | +| `radload_buffer` | Load rad from buffer | [ctor@Image.radload_buffer] | +| `radload_source` | Load rad from source | [ctor@Image.radload_source] | +| `radsave` | Save image to radiance file | [method@Image.radsave] | +| `radsave_buffer` | Save image to radiance buffer | [method@Image.radsave_buffer] | +| `radsave_target` | Save image to radiance target | [method@Image.radsave_target] | +| `rank` | Rank filter | [method@Image.rank], [method@Image.median] | +| `rawload` | Load raw data from a file | [ctor@Image.rawload] | +| `rawsave` | Save image to raw file | [method@Image.rawsave] | +| `rawsave_buffer` | Write raw image to buffer | [method@Image.rawsave_buffer] | +| `rawsave_target` | Write raw image to target | [method@Image.rawsave_target] | +| `recomb` | Linear recombination with matrix | [method@Image.recomb] | +| `reduce` | Reduce an image | [method@Image.reduce] | +| `reduceh` | Shrink an image horizontally | [method@Image.reduceh] | +| `reducev` | Shrink an image vertically | [method@Image.reducev] | +| `relational` | Relational operation on two images | [method@Image.relational], [method@Image.equal], [method@Image.notequal], [method@Image.less], [method@Image.lesseq], [method@Image.more], [method@Image.moreeq] | +| `relational_const` | Relational operations against a constant | [method@Image.relational_const], [method@Image.equal_const], [method@Image.notequal_const], [method@Image.less_const], [method@Image.lesseq_const], [method@Image.more_const], [method@Image.moreeq_const], [method@Image.relational_const1], [method@Image.equal_const1], [method@Image.notequal_const1], [method@Image.less_const1], [method@Image.lesseq_const1], [method@Image.more_const1], [method@Image.moreeq_const1] | +| `remainder` | Remainder after integer division of two images | [method@Image.remainder] | +| `remainder_const` | Remainder after integer division of an image and a constant | [method@Image.remainder_const], [method@Image.remainder_const1] | +| `remosaic` | Rebuild an mosaiced image | [method@Image.remosaic] | +| `replicate` | Replicate an image | [method@Image.replicate] | +| `resize` | Resize an image | [method@Image.resize] | +| `rot` | Rotate an image | [method@Image.rot] | +| `rot45` | Rotate an image | [method@Image.rot45] | +| `rotate` | Rotate an image by a number of degrees | [method@Image.rotate] | +| `round` | Perform a round function on an image | [method@Image.round], [method@Image.floor], [method@Image.ceil], [method@Image.rint] | +| `sRGB2HSV` | Transform srgb to hsv | [method@Image.sRGB2HSV] | +| `sRGB2scRGB` | Convert an srgb image to scrgb | [method@Image.sRGB2scRGB] | +| `scRGB2BW` | Convert scrgb to bw | [method@Image.scRGB2BW] | +| `scRGB2XYZ` | Transform scrgb to xyz | [method@Image.scRGB2XYZ] | +| `scRGB2sRGB` | Convert scrgb to srgb | [method@Image.scRGB2sRGB] | +| `scale` | Scale an image to uchar | [method@Image.scale] | +| `scharr` | Scharr edge detector | [method@Image.scharr] | +| `sdf` | Create an sdf image | [ctor@Image.sdf] | +| `sequential` | Check sequential access | [method@Image.sequential] | +| `sharpen` | Unsharp masking for print | [method@Image.sharpen] | +| `shrink` | Shrink an image | [method@Image.shrink] | +| `shrinkh` | Shrink an image horizontally | [method@Image.shrinkh] | +| `shrinkv` | Shrink an image vertically | [method@Image.shrinkv] | +| `sign` | Unit vector of pixel | [method@Image.sign] | +| `similarity` | Similarity transform of an image | [method@Image.similarity] | +| `sines` | Make a 2d sine wave | [ctor@Image.sines] | +| `smartcrop` | Extract an area from an image | [method@Image.smartcrop] | +| `sobel` | Sobel edge detector | [method@Image.sobel] | +| `spcor` | Spatial correlation | [method@Image.spcor] | +| `spectrum` | Make displayable power spectrum | [method@Image.spectrum] | +| `stats` | Find many image stats | [method@Image.stats] | +| `stdif` | Statistical difference | [method@Image.stdif] | +| `subsample` | Subsample an image | [method@Image.subsample] | +| `subtract` | Subtract two images | [method@Image.subtract] | +| `sum` | Sum an array of images | [func@Image.sum] | +| `svgload` | Load svg with rsvg | [ctor@Image.svgload] | +| `svgload_buffer` | Load svg with rsvg | [ctor@Image.svgload_buffer] | +| `svgload_source` | Load svg from source | [ctor@Image.svgload_source] | +| `switch` | Find the index of the first non-zero pixel in tests | [func@Image.switch] | +| `system` | Run an external command | [ctor@Image.system] | +| `text` | Make a text image | [ctor@Image.text] | +| `thumbnail` | Generate thumbnail from file | [ctor@Image.thumbnail] | +| `thumbnail_buffer` | Generate thumbnail from buffer | [ctor@Image.thumbnail_buffer] | +| `thumbnail_image` | Generate thumbnail from image | [method@Image.thumbnail_image] | +| `thumbnail_source` | Generate thumbnail from source | [ctor@Image.thumbnail_source] | +| `tiffload` | Load tiff from file | [ctor@Image.tiffload] | +| `tiffload_buffer` | Load tiff from buffer | [ctor@Image.tiffload_buffer] | +| `tiffload_source` | Load tiff from source | [ctor@Image.tiffload_source] | +| `tiffsave` | Save image to tiff file | [method@Image.tiffsave] | +| `tiffsave_buffer` | Save image to tiff buffer | [method@Image.tiffsave_buffer] | +| `tiffsave_target` | Save image to tiff target | [method@Image.tiffsave_target] | +| `tilecache` | Cache an image as a set of tiles | [method@Image.tilecache] | +| `tonelut` | Build a look-up table | [ctor@Image.tonelut] | +| `transpose3d` | Transpose3d an image | [method@Image.transpose3d] | +| `unpremultiply` | Unpremultiply image alpha | [method@Image.unpremultiply] | +| `vipsload` | Load vips from file | [ctor@Image.vipsload] | +| `vipsload_source` | Load vips from source | [ctor@Image.vipsload_source] | +| `vipssave` | Save image to file in vips format | [method@Image.vipssave] | +| `vipssave_target` | Save image to target in vips format | [method@Image.vipssave_target] | +| `webpload` | Load webp from file | [ctor@Image.webpload] | +| `webpload_buffer` | Load webp from buffer | [ctor@Image.webpload_buffer] | +| `webpload_source` | Load webp from source | [ctor@Image.webpload_source] | +| `webpsave` | Save as webp | [method@Image.webpsave] | +| `webpsave_buffer` | Save as webp | [method@Image.webpsave_buffer] | +| `webpsave_mime` | Save image to webp mime | [method@Image.webpsave_mime] | +| `webpsave_target` | Save as webp | [method@Image.webpsave_target] | +| `worley` | Make a worley noise image | [ctor@Image.worley] | +| `wrap` | Wrap image origin | [method@Image.wrap] | +| `xyz` | Make an image where pixel values are coordinates | [ctor@Image.xyz] | +| `zone` | Make a zone plate | [ctor@Image.zone] | +| `zoom` | Zoom an image | [method@Image.zoom] | diff --git a/doc/function-list.xml b/doc/function-list.xml deleted file mode 100644 index 3699839199..0000000000 --- a/doc/function-list.xml +++ /dev/null @@ -1,1657 +0,0 @@ - - - - - - VIPS function list - 3 - VIPS Library - - - - Using VIPS - List of VIPS functions and operators - - - - Codestin Search App - - VIPS has a set of operators each of which computes some useful image - processing operation. Each operator is - implemented as a %GObject class, for example VipsGamma. - Classes are identified by their unique nickname, in this - case gamma. - - From the command-line, C++ and most language bindings, you use the - nickname to call the operator. For example in C++: - - - vips::VImage fred = ...; - vips::VImage jim = fred.gamma(); - - - or Python: - - - fred = jim.gamma() - - - VIPS has a set of C wrapper functions for calling operators, in this - case vips_gamma(): - - - VipsImage *fred = ...; - VipsImage *jim; - - if (vips_gamma(fred, &jim, NULL)) - ...error; - - - Some operators have many C convenience functions. - - - - This table lists all the VIPS operators with their C convenience - functions and a short description. It's supposed to be useful for - searching. See the API docs each function links to for more details. - - - - - Codestin Search App - - - - Operator - Description - C functions - - - - - - CMC2LCh - Transform lch to cmc - vips_CMC2LCh() - - - CMYK2XYZ - Transform cmyk to xyz - vips_CMYK2XYZ() - - - HSV2sRGB - Transform hsv to srgb - vips_HSV2sRGB() - - - LCh2CMC - Transform lch to cmc - vips_LCh2CMC() - - - LCh2Lab - Transform lch to lab - vips_LCh2Lab() - - - Lab2LCh - Transform lab to lch - vips_Lab2LCh() - - - Lab2LabQ - Transform float lab to labq coding - vips_Lab2LabQ() - - - Lab2LabS - Transform float lab to signed short - vips_Lab2LabS() - - - Lab2XYZ - Transform cielab to xyz - vips_Lab2XYZ() - - - LabQ2Lab - Unpack a labq image to float lab - vips_LabQ2Lab() - - - LabQ2LabS - Unpack a labq image to short lab - vips_LabQ2LabS() - - - LabQ2sRGB - Convert a labq image to srgb - vips_LabQ2sRGB() - - - LabS2Lab - Transform signed short lab to float - vips_LabS2Lab() - - - LabS2LabQ - Transform short lab to labq coding - vips_LabS2LabQ() - - - XYZ2CMYK - Transform xyz to cmyk - vips_XYZ2CMYK() - - - XYZ2Lab - Transform xyz to lab - vips_XYZ2Lab() - - - XYZ2Yxy - Transform xyz to yxy - vips_XYZ2Yxy() - - - XYZ2scRGB - Transform xyz to scrgb - vips_XYZ2scRGB() - - - Yxy2XYZ - Transform yxy to xyz - vips_Yxy2XYZ() - - - abs - Absolute value of an image - vips_abs() - - - add - Add two images - vips_add() - - - addalpha - Append an alpha channel - vips_addalpha() - - - affine - Affine transform of an image - vips_affine() - - - analyzeload - Load an analyze6 image - vips_analyzeload() - - - arrayjoin - Join an array of images - vips_arrayjoin() - - - autorot - Autorotate image by exif tag - vips_autorot() - - - avg - Find image average - vips_avg() - - - bandbool - Boolean operation across image bands - vips_bandbool(), vips_bandand(), vips_bandor(), vips_bandeor(), vips_bandmean() - - - bandfold - Fold up x axis into bands - vips_bandfold() - - - bandjoin - Bandwise join a set of images - vips_bandjoin(), vips_bandjoin2() - - - bandjoin_const - Append a constant band to an image - vips_bandjoin_const(), vips_bandjoin_const1() - - - bandmean - Band-wise average - vips_bandmean() - - - bandrank - Band-wise rank of a set of images - vips_bandrank() - - - bandunfold - Unfold image bands into x axis - vips_bandunfold() - - - black - Make a black image - vips_black() - - - boolean - Boolean operation on two images - vips_boolean(), vips_andimage(), vips_orimage(), vips_eorimage(), vips_lshift(), vips_rshift() - - - boolean_const - Boolean operations against a constant - vips_boolean_const(), vips_andimage_const(), vips_orimage_const(), vips_eorimage_const(), vips_lshift_const(), vips_rshift_const(), vips_boolean_const1(), vips_andimage_const1(), vips_orimage_const1(), vips_eorimage_const1(), vips_lshift_const1(), vips_rshift_const1() - - - buildlut - Build a look-up table - vips_buildlut() - - - byteswap - Byteswap an image - vips_byteswap() - - - canny - Canny edge detector - vips_canny() - - - case - Use pixel values to pick cases from an array of images - vips_case() - - - cast - Cast an image - vips_cast(), vips_cast_uchar(), vips_cast_char(), vips_cast_ushort(), vips_cast_shortcast_uint(), vips_cast_int(), vips_cast_float(), vips_cast_double(), vips_cast_complex(), vips_cast_dpcomplex() - - - clamp - Clamp values of an image - vips_clamp() - - - colourspace - Convert to a new colorspace - vips_colourspace() - - - compass - Convolve with rotating mask - vips_compass() - - - complex - Perform a complex operation on an image - vips_complex(), vips_polar(), vips_rect(), vips_conj() - - - complex2 - Complex binary operations on two images - vips_complex2(), vips_cross_phase() - - - complexform - Form a complex image from two real images - vips_complexform() - - - complexget - Get a component from a complex image - vips_complexget(), vips_real(), vips_imag() - - - composite - Blend an array of images with an array of blend modes - vips_composite() - - - composite2 - Blend a pair of images with a blend mode - vips_composite2() - - - conv - Convolution operation - vips_conv() - - - conva - Approximate integer convolution - vips_conva() - - - convasep - Approximate separable integer convolution - vips_convasep() - - - convf - Float convolution operation - vips_convf() - - - convi - Int convolution operation - vips_convi() - - - convsep - Separable convolution operation - vips_convsep() - - - copy - Copy an image - vips_copy() - - - countlines - Count lines in an image - vips_countlines() - - - csvload - Load csv - vips_csvload() - - - csvload_source - Load csv - vips_csvload_source() - - - csvsave - Save image to csv - vips_csvsave() - - - csvsave_target - Save image to csv - vips_csvsave_target() - - - dE00 - Calculate de00 - vips_dE00() - - - dE76 - Calculate de76 - vips_dE76() - - - dECMC - Calculate decmc - vips_dECMC() - - - deviate - Find image standard deviation - vips_deviate() - - - divide - Divide two images - vips_divide() - - - draw_circle - Draw a circle on an image - vips_draw_circle(), vips_draw_circle1() - - - draw_flood - Flood-fill an area - vips_draw_flood(), vips_draw_flood1() - - - draw_image - Paint an image into another image - vips_draw_image() - - - draw_line - Draw a line on an image - vips_draw_line(), vips_draw_line1() - - - draw_mask - Draw a mask on an image - vips_draw_mask(), vips_draw_mask1() - - - draw_rect - Paint a rectangle on an image - vips_draw_rect(), vips_draw_rect1(), vips_draw_point(), vips_draw_point1() - - - draw_smudge - Blur a rectangle on an image - vips_draw_smudge() - - - dzsave - Save image to deepzoom file - vips_dzsave() - - - dzsave_buffer - Save image to dz buffer - vips_dzsave_buffer() - - - dzsave_target - Save image to deepzoom target - vips_dzsave_target() - - - embed - Embed an image in a larger image - vips_embed() - - - extract_area - Extract an area from an image - vips_extract_area(), vips_crop() - - - extract_band - Extract band from an image - vips_extract_band() - - - eye - Make an image showing the eye's spatial response - vips_eye() - - - falsecolour - False-color an image - vips_falsecolour() - - - fastcor - Fast correlation - vips_fastcor() - - - fill_nearest - Fill image zeros with nearest non-zero pixel - vips_fill_nearest() - - - find_trim - Search an image for non-edge areas - vips_find_trim() - - - fitsload - Load a fits image - vips_fitsload() - - - fitsload_source - Load fits from a source - vips_fitsload_source() - - - fitssave - Save image to fits file - vips_fitssave() - - - flatten - Flatten alpha out of an image - vips_flatten() - - - flip - Flip an image - vips_flip() - - - float2rad - Transform float rgb to radiance coding - vips_float2rad() - - - fractsurf - Make a fractal surface - vips_fractsurf() - - - freqmult - Frequency-domain filtering - vips_freqmult() - - - fwfft - Forward fft - vips_fwfft() - - - gamma - Gamma an image - vips_gamma() - - - gaussblur - Gaussian blur - vips_gaussblur() - - - gaussmat - Make a gaussian image - vips_gaussmat() - - - gaussnoise - Make a gaussnoise image - vips_gaussnoise() - - - getpoint - Read a point from an image - vips_getpoint() - - - gifload - Load gif with libnsgif - vips_gifload() - - - gifload_buffer - Load gif with libnsgif - vips_gifload_buffer() - - - gifload_source - Load gif from source - vips_gifload_source() - - - gifsave - Save as gif - vips_gifsave() - - - gifsave_buffer - Save as gif - vips_gifsave_buffer() - - - gifsave_target - Save as gif - vips_gifsave_target() - - - globalbalance - Global balance an image mosaic - vips_globalbalance() - - - gravity - Place an image within a larger image with a certain gravity - vips_gravity() - - - grey - Make a grey ramp image - vips_grey() - - - grid - Grid an image - vips_grid() - - - heifload - Load a heif image - vips_heifload() - - - heifload_buffer - Load a heif image - vips_heifload_buffer() - - - heifload_source - Load a heif image - vips_heifload_source() - - - heifsave - Save image in heif format - vips_heifsave() - - - heifsave_buffer - Save image in heif format - vips_heifsave_buffer() - - - heifsave_target - Save image in heif format - vips_heifsave_target() - - - hist_cum - Form cumulative histogram - vips_hist_cum() - - - hist_entropy - Estimate image entropy - vips_hist_entropy() - - - hist_equal - Histogram equalisation - vips_hist_equal() - - - hist_find - Find image histogram - vips_hist_find() - - - hist_find_indexed - Find indexed image histogram - vips_hist_find_indexed() - - - hist_find_ndim - Find n-dimensional image histogram - vips_hist_find_ndim() - - - hist_ismonotonic - Test for monotonicity - vips_hist_ismonotonic() - - - hist_local - Local histogram equalisation - vips_hist_local() - - - hist_match - Match two histograms - vips_hist_match() - - - hist_norm - Normalise histogram - vips_hist_norm() - - - hist_plot - Plot histogram - vips_hist_plot() - - - hough_circle - Find hough circle transform - vips_hough_circle() - - - hough_line - Find hough line transform - vips_hough_line() - - - icc_export - Output to device with icc profile - vips_icc_export() - - - icc_import - Import from device with icc profile - vips_icc_import() - - - icc_transform - Transform between devices with icc profiles - vips_icc_transform() - - - identity - Make a 1d image where pixel values are indexes - vips_identity() - - - ifthenelse - Ifthenelse an image - vips_ifthenelse() - - - insert - Insert image @sub into @main at @x, @y - vips_insert() - - - invert - Invert an image - vips_invert() - - - invertlut - Build an inverted look-up table - vips_invertlut() - - - invfft - Inverse fft - vips_invfft() - - - join - Join a pair of images - vips_join() - - - jp2kload - Load jpeg2000 image - vips_jp2kload() - - - jp2kload_buffer - Load jpeg2000 image - vips_jp2kload_buffer() - - - jp2kload_source - Load jpeg2000 image - vips_jp2kload_source() - - - jp2ksave - Save image in jpeg2000 format - vips_jp2ksave() - - - jp2ksave_buffer - Save image in jpeg2000 format - vips_jp2ksave_buffer() - - - jp2ksave_target - Save image in jpeg2000 format - vips_jp2ksave_target() - - - jpegload - Load jpeg from file - vips_jpegload() - - - jpegload_buffer - Load jpeg from buffer - vips_jpegload_buffer() - - - jpegload_source - Load image from jpeg source - vips_jpegload_source() - - - jpegsave - Save image to jpeg file - vips_jpegsave() - - - jpegsave_buffer - Save image to jpeg buffer - vips_jpegsave_buffer() - - - jpegsave_mime - Save image to jpeg mime - vips_jpegsave_mime() - - - jpegsave_target - Save image to jpeg target - vips_jpegsave_target() - - - jxlload - Load jpeg-xl image - vips_jxlload() - - - jxlload_buffer - Load jpeg-xl image - vips_jxlload_buffer() - - - jxlload_source - Load jpeg-xl image - vips_jxlload_source() - - - jxlsave - Save image in jpeg-xl format - vips_jxlsave() - - - jxlsave_buffer - Save image in jpeg-xl format - vips_jxlsave_buffer() - - - jxlsave_target - Save image in jpeg-xl format - vips_jxlsave_target() - - - labelregions - Label regions in an image - vips_labelregions() - - - linear - Calculate (a * in + b) - vips_linear(), vips_linear1() - - - linecache - Cache an image as a set of lines - vips_linecache() - - - logmat - Make a laplacian of gaussian image - vips_logmat() - - - magickload - Load file with imagemagick - vips_magickload() - - - magickload_buffer - Load buffer with imagemagick - vips_magickload_buffer() - - - magicksave - Save file with imagemagick - vips_magicksave() - - - magicksave_buffer - Save image to magick buffer - vips_magicksave_buffer() - - - mapim - Resample with a map image - vips_mapim() - - - maplut - Map an image though a lut - vips_maplut() - - - mask_butterworth - Make a butterworth filter - vips_mask_butterworth() - - - mask_butterworth_band - Make a butterworth_band filter - vips_mask_butterworth_band() - - - mask_butterworth_ring - Make a butterworth ring filter - vips_mask_butterworth_ring() - - - mask_fractal - Make fractal filter - vips_mask_fractal() - - - mask_gaussian - Make a gaussian filter - vips_mask_gaussian() - - - mask_gaussian_band - Make a gaussian filter - vips_mask_gaussian_band() - - - mask_gaussian_ring - Make a gaussian ring filter - vips_mask_gaussian_ring() - - - mask_ideal - Make an ideal filter - vips_mask_ideal() - - - mask_ideal_band - Make an ideal band filter - vips_mask_ideal_band() - - - mask_ideal_ring - Make an ideal ring filter - vips_mask_ideal_ring() - - - match - First-order match of two images - vips_match() - - - math - Apply a math operation to an image - vips_math(), vips_sin(), vips_cos(), vips_tan(), vips_asin(), vips_acos(), vips_atan(), vips_sinh(), vips_cosh(), vips_tanh(), vips_asinh(), vips_acosh(), vips_atanh(), vips_exp(), vips_exp10(), vips_log(), vips_log10() - - - math2 - Binary math operations - vips_math2(), vips_pow(), vips_wop(), vips_atan2() - - - math2_const - Binary math operations with a constant - vips_math2_const(), vips_andimage_const(), vips_orimage_const(), vips_eorimage_const(), vips_lshift_const(), vips_rshift_const(), vips_math2_const1(), vips_andimage_const1(), vips_orimage_const1(), vips_eorimage_const1(), vips_lshift_const1(), vips_rshift_const1() - - - matload - Load mat from file - vips_matload() - - - matrixinvert - Invert an matrix - vips_matrixinvert() - - - matrixload - Load matrix - vips_matrixload() - - - matrixload_source - Load matrix - vips_matrixload_source() - - - matrixprint - Print matrix - vips_matrixprint() - - - matrixsave - Save image to matrix - vips_matrixsave() - - - matrixsave_target - Save image to matrix - vips_matrixsave_target() - - - max - Find image maximum - vips_max() - - - maxpair - Maximum of a pair of images - vips_maxpair() - - - measure - Measure a set of patches on a color chart - vips_measure() - - - merge - Merge two images - vips_merge() - - - min - Find image minimum - vips_min() - - - minpair - Minimum of a pair of images - vips_minpair() - - - morph - Morphology operation - vips_morph() - - - mosaic - Mosaic two images - vips_mosaic() - - - mosaic1 - First-order mosaic of two images - vips_mosaic1() - - - msb - Pick most-significant byte from an image - vips_msb() - - - multiply - Multiply two images - vips_multiply() - - - niftiload - Load nifti volume - vips_niftiload() - - - niftiload_source - Load nifti volumes - vips_niftiload_source() - - - niftisave - Save image to nifti file - vips_niftisave() - - - openexrload - Load an openexr image - vips_openexrload() - - - openslideload - Load file with openslide - vips_openslideload() - - - openslideload_source - Load source with openslide - vips_openslideload_source() - - - pdfload - Load pdf from file - vips_pdfload() - - - pdfload_buffer - Load pdf from buffer - vips_pdfload_buffer() - - - pdfload_source - Load pdf from source - vips_pdfload_source() - - - percent - Find threshold for percent of pixels - vips_percent() - - - perlin - Make a perlin noise image - vips_perlin() - - - phasecor - Calculate phase correlation - vips_phasecor() - - - pngload - Load png from file - vips_pngload() - - - pngload_buffer - Load png from buffer - vips_pngload_buffer() - - - pngload_source - Load png from source - vips_pngload_source() - - - pngsave - Save image to file as png - vips_pngsave() - - - pngsave_buffer - Save image to buffer as png - vips_pngsave_buffer() - - - pngsave_target - Save image to target as png - vips_pngsave_target() - - - ppmload - Load ppm from file - vips_ppmload() - - - ppmload_source - Load ppm base class - vips_ppmload_source() - - - ppmsave - Save image to ppm file - vips_ppmsave() - - - ppmsave_target - Save to ppm - vips_ppmsave_target() - - - premultiply - Premultiply image alpha - vips_premultiply() - - - prewitt - Prewitt edge detector - vips_prewitt() - - - profile - Find image profiles - vips_profile() - - - profile_load - Load named icc profile - vips_profile_load() - - - project - Find image projections - vips_project() - - - quadratic - Resample an image with a quadratic transform - vips_quadratic() - - - rad2float - Unpack radiance coding to float rgb - vips_rad2float() - - - radload - Load a radiance image from a file - vips_radload() - - - radload_buffer - Load rad from buffer - vips_radload_buffer() - - - radload_source - Load rad from source - vips_radload_source() - - - radsave - Save image to radiance file - vips_radsave() - - - radsave_buffer - Save image to radiance buffer - vips_radsave_buffer() - - - radsave_target - Save image to radiance target - vips_radsave_target() - - - rank - Rank filter - vips_rank(), vips_median() - - - rawload - Load raw data from a file - vips_rawload() - - - rawsave - Save image to raw file - vips_rawsave() - - - rawsave_buffer - Write raw image to buffer - vips_rawsave_buffer() - - - rawsave_target - Write raw image to target - vips_rawsave_target() - - - recomb - Linear recombination with matrix - vips_recomb() - - - reduce - Reduce an image - vips_reduce() - - - reduceh - Shrink an image horizontally - vips_reduceh() - - - reducev - Shrink an image vertically - vips_reducev() - - - relational - Relational operation on two images - vips_relational(), vips_equal(), vips_notequal(), vips_less(), vips_lesseq(), vips_more(), vips_moreeq() - - - relational_const - Relational operations against a constant - vips_relational_const(), vips_equal_const(), vips_notequal_const(), vips_less_const(), vips_lesseq_const(), vips_more_const(), vips_moreeq_const(), vips_relational_const1(), vips_equal_const1(), vips_notequal_const1(), vips_less_const1(), vips_lesseq_const1(), vips_more_const1(), vips_moreeq_const1() - - - remainder - Remainder after integer division of two images - vips_remainder() - - - remainder_const - Remainder after integer division of an image and a constant - vips_remainder_const(), vips_remainder_const1() - - - replicate - Replicate an image - vips_replicate() - - - resize - Resize an image - vips_resize() - - - rot - Rotate an image - vips_rot() - - - rot45 - Rotate an image - vips_rot45() - - - rotate - Rotate an image by a number of degrees - vips_rotate() - - - round - Perform a round function on an image - vips_round(), vips_floor(), vips_ceil(), vips_rint() - - - sRGB2HSV - Transform srgb to hsv - vips_sRGB2HSV() - - - sRGB2scRGB - Convert an srgb image to scrgb - vips_sRGB2scRGB() - - - scRGB2BW - Convert scrgb to bw - vips_scRGB2BW() - - - scRGB2XYZ - Transform scrgb to xyz - vips_scRGB2XYZ() - - - scRGB2sRGB - Convert an scrgb image to srgb - vips_scRGB2sRGB() - - - scale - Scale an image to uchar - vips_scale() - - - scharr - Scharr edge detector - vips_scharr() - - - sdf - Create an sdf image - vips_sdf() - - - sequential - Check sequential access - vips_sequential() - - - sharpen - Unsharp masking for print - vips_sharpen() - - - shrink - Shrink an image - vips_shrink() - - - shrinkh - Shrink an image horizontally - vips_shrinkh() - - - shrinkv - Shrink an image vertically - vips_shrinkv() - - - sign - Unit vector of pixel - vips_sign() - - - similarity - Similarity transform of an image - vips_similarity() - - - sines - Make a 2d sine wave - vips_sines() - - - smartcrop - Extract an area from an image - vips_smartcrop() - - - sobel - Sobel edge detector - vips_sobel() - - - spcor - Spatial correlation - vips_spcor() - - - spectrum - Make displayable power spectrum - vips_spectrum() - - - stats - Find many image stats - vips_stats() - - - stdif - Statistical difference - vips_stdif() - - - subsample - Subsample an image - vips_subsample() - - - subtract - Subtract two images - vips_subtract() - - - sum - Sum an array of images - vips_sum() - - - svgload - Load svg with rsvg - vips_svgload() - - - svgload_buffer - Load svg with rsvg - vips_svgload_buffer() - - - svgload_source - Load svg from source - vips_svgload_source() - - - switch - Find the index of the first non-zero pixel in tests - vips_switch() - - - system - Run an external command - vips_system() - - - text - Make a text image - vips_text() - - - thumbnail - Generate thumbnail from file - vips_thumbnail() - - - thumbnail_buffer - Generate thumbnail from buffer - vips_thumbnail_buffer() - - - thumbnail_image - Generate thumbnail from image - vips_thumbnail_image() - - - thumbnail_source - Generate thumbnail from source - vips_thumbnail_source() - - - tiffload - Load tiff from file - vips_tiffload() - - - tiffload_buffer - Load tiff from buffer - vips_tiffload_buffer() - - - tiffload_source - Load tiff from source - vips_tiffload_source() - - - tiffsave - Save image to tiff file - vips_tiffsave() - - - tiffsave_buffer - Save image to tiff buffer - vips_tiffsave_buffer() - - - tiffsave_target - Save image to tiff target - vips_tiffsave_target() - - - tilecache - Cache an image as a set of tiles - vips_tilecache() - - - tonelut - Build a look-up table - vips_tonelut() - - - transpose3d - Transpose3d an image - vips_transpose3d() - - - unpremultiply - Unpremultiply image alpha - vips_unpremultiply() - - - vipsload - Load vips from file - vips_vipsload() - - - vipsload_source - Load vips from source - vips_vipsload_source() - - - vipssave - Save image to file in vips format - vips_vipssave() - - - vipssave_target - Save image to target in vips format - vips_vipssave_target() - - - webpload - Load webp from file - vips_webpload() - - - webpload_buffer - Load webp from buffer - vips_webpload_buffer() - - - webpload_source - Load webp from source - vips_webpload_source() - - - webpsave - Save as webp - vips_webpsave() - - - webpsave_buffer - Save as webp - vips_webpsave_buffer() - - - webpsave_mime - Save image to webp mime - vips_webpsave_mime() - - - webpsave_target - Save as webp - vips_webpsave_target() - - - worley - Make a worley noise image - vips_worley() - - - wrap - Wrap image origin - vips_wrap() - - - xyz - Make an image where pixel values are coordinates - vips_xyz() - - - zone - Make a zone plate - vips_zone() - - - zoom - Zoom an image - vips_zoom() - - - - -
-
- -
- -
diff --git a/doc/gen-function-list.py b/doc/gen-function-list.py index a7f2d38b41..d1d12cfd93 100755 --- a/doc/gen-function-list.py +++ b/doc/gen-function-list.py @@ -4,16 +4,13 @@ # for docs # this needs pyvips -# # pip install --user pyvips -# sample output: +# rebuild with: +# ./gen-function-list.py > function-list.md -# -# gamma -# Gamma an image -# vips_gamma() -# +# sample output: +# | `gamma` | Gamma an image | [method@Image.gamma] | from pyvips import Introspect, Operation, Error, \ ffi, type_map, type_from_name, nickname_find @@ -25,16 +22,27 @@ def gen_function(operation_name, overloads): intro = Introspect.get(operation_name) - c_operations = 'vips_{}()'.format(operation_name) + # Keep-in-sync with fixup-gir-for-doc.py + image_funcs = [ + 'arrayjoin', + 'bandjoin', + 'bandrank', + 'composite', + 'sum', + 'switch', + ] + + if operation_name in image_funcs: + c_operations = f'[func@Image.{operation_name}]' + else: + operation_type = 'ctor' if intro.member_x is None else 'method' + operation_class = 'Blob' if operation_name == 'profile_load' else 'Image' + c_operations = f'[{operation_type}@{operation_class}.{operation_name}]' if overloads: - c_operations += ', ' + (', '.join('vips_{}()'.format(n) for n in overloads)) + c_operations += ', ' + (', '.join(f'[method@Image.{n}]' for n in overloads)) - result = '\n' - result += ' {}\n'.format(operation_name) - result += ' {}\n'.format(intro.description.capitalize()) - result += ' {}\n'.format(c_operations) - result += '' + result = f"| `{operation_name}` | {intro.description.capitalize()} | {c_operations} |" return result @@ -70,8 +78,9 @@ def add_nickname(gtype, a, b): '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'], + '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'], @@ -82,7 +91,9 @@ def add_nickname(gtype, a, b): 'draw_rect': ['draw_rect1', 'draw_point', 'draw_point1'], 'extract_area': ['crop'], 'linear': ['linear1'], - 'math': ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'sinh', 'cosh', 'tanh', 'asinh', 'acosh', 'atanh', 'exp', 'exp10', 'log', 'log10'], + 'math': ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'sinh', + 'cosh', 'tanh', 'asinh', 'acosh', 'atanh', 'exp', 'exp10', + 'log', 'log10'], 'math2': ['pow', 'wop', 'atan2'], 'rank': ['median'], 'relational': ['equal', 'notequal', 'less', 'lesseq', 'more', 'moreeq'], @@ -90,19 +101,69 @@ def add_nickname(gtype, a, b): 'round': ['floor', 'ceil', 'rint'], } - overloads['boolean_const'] = [o + '_const' for o in overloads['boolean']] + ['boolean_const1'] + \ - [o + '_const1' for o in overloads['boolean']] + 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['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']] + overloads['relational_const'] = \ + [o + '_const' for o in overloads['relational']] \ + + ['relational_const1'] \ + + [o + '_const1' for o in overloads['relational']] for nickname in all_nicknames: - result = gen_function(nickname, overloads[nickname] if nickname in overloads else None) + result = gen_function(nickname, + overloads[nickname] if nickname in overloads else None) print(result) if __name__ == '__main__': + print("""Title: Operator index / Alphabetical + +libvips has a set of operators, each of which computes some useful image +processing operation. Each operator is implemented as a [class@GObject.Object] +class, for example `VipsGamma`. Classes are identified by their unique +[property@VipsObject:nickname], in this case `gamma`. + +From the command-line, C++ and most language bindings, you use the nickname +to call the operator. For example in C++: + +```c++ +vips::VImage fred = ...; +vips::VImage jim = fred.gamma(); +``` + +or Python: + +```python +fred = jim.gamma() +``` + +libvips has a set of C wrapper functions for calling operators, in this +case [method@Image.gamma]: + +```c +VipsImage *fred = ...; +VipsImage *jim; + +if (vips_gamma(fred, &jim, NULL)) + ...error; +``` + +Some operators have many C convenience functions. + +# All libvips operators + +This table lists all the libvips operators with their C convenience functions +and a short description. It's supposed to be useful for searching. See the +API docs each function links to for more details. + +| Operator | Description | C functions | +| -------- | ----------- | ----------- |""") + gen_function_list() diff --git a/doc/How-it-opens-files.md b/doc/how-it-opens-files.md similarity index 86% rename from doc/How-it-opens-files.md rename to doc/how-it-opens-files.md index 329a9fe6b3..33e3b6ea3c 100644 --- a/doc/How-it-opens-files.md +++ b/doc/how-it-opens-files.md @@ -1,13 +1,4 @@ - - Opening files - 3 - libvips - - - - Opening - How libvips opens files - +Title: Technical background > Opening files libvips has at least four different ways of opening image files, each best for different file types, file sizes and image use cases. libvips tries @@ -16,18 +7,18 @@ know what it is doing behind the scenes, except unfortunately when you do. 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. `vips_image_new_from_file()` has the official documentation. +be helpful. [ctor@Image.new_from_file] has the official documentation. -# Caching +## Caching libvips caches recent operations. This means that if a file changes between one load and the next, the second load will return the old image, even though the file has been replaced. You can force libvips to load a file and ignore any cached value by -setting the `revalidate` flag, see #VipsForeignLoad. +setting the `revalidate` flag, see [class@ForeignLoad]. -# Direct access +## Direct access This is the fastest and simplest one. The file is mapped directly into the process's address space and can be read with ordinary pointer access. Small @@ -39,14 +30,13 @@ system: your OS will use spare memory to cache recently used chunks of the file. 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, +array. libvips supports direct access for `.v`, 8-bit binary ppm/pbm/pnm, analyse and raw. libvips has a special direct write mode where pixels can be written directly -to the file image. This is used for the draw -operators. +to the file image. This is used for the [draw operations](libvips-draw.html). -# Random access via load library +## Random access via load library 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 @@ -64,7 +54,7 @@ same tile. libvips can load tiled tiff, tiled OpenEXR, FITS and OpenSlide images in this manner. -# Full decompression +## Full decompression 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 @@ -79,15 +69,14 @@ Note that on open libvips just reads the image header and is quick: the image decompress happens on the first pixel access. You can control this process with environment variables, command-line -flags and API calls as you choose, see -vips_image_new_from_file(). +flags and API calls as you choose, see [ctor@Image.new_from_file]. They let you set the threshold at which libvips switches between memory and disc and where on disc the temporary files are held. This is the slowest and most memory-hungry way to read files, but it's unavoidable for many file formats. Unless you can use the next one! -# Sequential access +## Sequential access This a fairly recent addition to libvips and is a hybrid of the previous two. @@ -105,7 +94,7 @@ bottom-to-top. Unfortunately libjpeg only supports top-to-bottom reading and writing, so libvips must convert `fred.jpg` to a random access format before it can run the flip operation. -However many useful operations do not require true random access.  For +However many useful operations do not require true random access. For example: ```bash @@ -127,4 +116,4 @@ small cache of the most recent 100 or so lines. This is done automatically in command-line operation. In programs, you need to set `access` to #VIPS_ACCESS_SEQUENTIAL in calls to functions like -vips_image_new_from_file(). +[ctor@Image.new_from_file]. diff --git a/doc/How-it-works.md b/doc/how-it-works.md similarity index 62% rename from doc/How-it-works.md rename to doc/how-it-works.md index a53082b377..757e0cb7bc 100644 --- a/doc/How-it-works.md +++ b/doc/how-it-works.md @@ -1,29 +1,20 @@ - - How libvips works - 3 - libvips - - - - Internals - A high-level technical overview of libvips's evaluation system - - -Compared to most image processing libraries, VIPS needs little RAM and runs -quickly, especially on machines with more than one CPU. VIPS achieves this +Title: Technical background > Evaluation + +Compared to most image processing libraries, libvips needs little RAM and runs +quickly, especially on machines with more than one CPU. libvips achieves this improvement by only keeping the pixels currently being processed in RAM and by having an efficient, threaded image IO system. This page explains how these features are implemented. -**Images** +## Images -VIPS images have three dimensions: width, height and bands. Bands usually +libvips images have three dimensions: width, height and bands. Bands usually (though not always) represent colour. These three dimensions can be any size up to 2 ** 31 elements. Every band element in an image has to have the same format. A format is an 8-, 16- or 32-bit int, signed or unsigned, 32- or 64-bit float, and 64- or 128-bit complex. -**Regions** +## Regions An image can be very large, much larger than the available memory, so you can't just access pixels with a pointer \*. @@ -58,20 +49,21 @@ VipsPel *pixel = VIPS_REGION_ADDR(region, x, y); g_object_unref(region); ``` -The action that `vips_region_prepare()` takes varies with the type of -image. If the image is a file on disc, for example, then VIPS will arrange +The action that [method@Region.prepare] takes varies with the type of +image. If the image is a file on disc, for example, then libvips will arrange for a section of the file to be read in. (\* there is an image access mode where you can just use a pointer, but it's rarely used) -**Partial images** +## Partial images -A partial image is one where, instead of storing a value for each pixel, VIPS -stores a function which can make any rectangular area of pixels on demand. +A partial image is one where, instead of storing a value for each pixel, +libvips stores a function which can make any rectangular area of pixels +on demand. -If you use `vips_region_prepare()` on a region created on a partial image, -VIPS will allocate enough memory to hold the pixels you asked for and use +If you use [method@Region.prepare] on a region created on a partial image, +libvips will allocate enough memory to hold the pixels you asked for and use the stored function to calculate values for just those pixels \*. The stored function comes in three parts: a start function, a generate @@ -82,47 +74,45 @@ function into three parts is good for SMP scaling: resource allocation and synchronisation mostly happens in start functions, so generate functions can run without having to talk to each other. -VIPS makes a set of guarantees about parallelism that make this simple to +libvips makes a set of guarantees about parallelism that make this simple to program. Start and stop functions are mutually exclusive and a state is never used by more than one generate. In other words, a start / generate / generate / stop sequence works like a thread. -![](Sequence.png) +![Sequence](Sequence.png) -(\* in fact VIPS keeps a cache of calculated pixel buffers and will return +(\* in fact libvips keeps a cache of calculated pixel buffers and will return a pointer to a previously-calculated buffer if it can) -**Operations** +# Operations -VIPS operations read input images and write output images, performing some +libvips operations read input images and write output images, performing some transformation on the pixels. When an operation writes to an image the action it takes depends upon the image type. For example, if the image is a -file on disc then VIPS will start a data sink to stream pixels to the file, +file on disc then libvips will start a data sink to stream pixels to the file, or if the image is a partial one then it will just attach start / generate / stop functions. -Like most threaded image processing systems, all VIPS operations have to +Like most threaded image processing systems, all libvips operations have to be free of side-effects. In other words, operations cannot modify images, they can only create new images. This could result in a lot of copying if -an operation is only making a small change to a large image so VIPS has a +an operation is only making a small change to a large image so libvips has a set of mechanisms to copy image areas by just adjusting pointers. Most of the time no actual copying is necessary and you can perform operations on large images at low cost. -**SIMD optimisations** +## SIMD optimisations -VIPS uses -Highway, a -C++ library, to optimise various operations with SIMD/vector -instructions. These optimised code paths are flexible and can adapt to -different instruction sets, including those with 'scalable' vectors -(size unknown at compile time). At runtime, dynamic dispatch selects -the best available implementation based on the processor's capabilities, -ensuring optimal performance. +libvips uses [Highway](https://github.com/google/highway), a C++ library, +to optimise various operations with SIMD/vector instructions. These optimised +code paths are flexible and can adapt to different instruction sets, including +those with 'scalable' vectors (size unknown at compile time). At runtime, +dynamic dispatch selects the best available implementation based on the +processor's capabilities, ensuring optimal performance. SIMD typically speeds operations up by a factor of three or four. -**Joining operations together** +## Joining operations together The region create / prepare / prepare / free calls you use to get pixels from an image are an exact parallel to the start / generate / generate / @@ -130,62 +120,62 @@ stop calls that images use to create pixels. In fact, they are the same: a region on a partial image holds the state created by that image for the generate function that will fill the region with pixels. -![](Combine.png) +![Combine](Combine.png) -VIPS joins image processing operations together by linking the output of one +libvips joins image processing operations together by linking the output of one operation (the start / generate / stop sequence) to the input of the next (the region it uses to get pixels for processing). This link is a single function call, and very fast. Additionally, because of the the split between allocation and processing, once a pipeline of operations has been set up, -VIPS is able to run without allocating and freeing memory. +libvips is able to run without allocating and freeing memory. -This graph (generated by `vipsprofile`, the vips profiler) shows memory use -over time for a vips pipeline running on a large image. The bottom trace +This graph (generated by `vipsprofile`, the libvips profiler) shows memory use +over time for a libvips pipeline running on a large image. The bottom trace shows total memory, the upper traces show threads calculating useful results (green), threads blocked on synchronisation (red) and memory allocations (white ticks). -![](Memtrace.png) +![Memtrace](Memtrace.png) Because the intermediate image is just a small region in memory, a pipeline of operations running together needs very little RAM. In fact, intermediates are small enough that they can fit in L2 cache on most machines, so an entire pipeline can run without touching main memory. And finally, because each thread runs a very cheap copy of just the writeable state of the -entire pipeline, threads can run with few locks. VIPS needs just four lock +entire pipeline, threads can run with few locks. libvips needs just four lock operations per output tile, regardless of the pipeline length or complexity. -**Data sources** +## Data sources -VIPS has data sources which can supply pixels for processing from a variety -of sources. VIPS can stream images from files in VIPS native format, from +libvips has data sources which can supply pixels for processing from a variety +of sources. libvips can stream images from files in libvips native format, from tiled TIFF files, from binary PPM/PGM/PBM/PFM, from Radiance (HDR) files, -from FITS images and from tiled OpenEXR images. VIPS will automatically +from FITS images and from tiled OpenEXR images. libvips will automatically unpack other formats to temporary disc files for you but this can obviously generate a lot of disc traffic. It also has a special sequential mode for streaming operations on non-random-access formats. Another -section in these docs explains how -libvips opens a file. One of the sources uses the ImageMagick (or optionally GraphicsMagick library, so VIPS -can read any image format that these libraries can read. +section in these docs explains [how libvips opens files]( +how-it-opens-files.html). One of the sources uses the [ImageMagick]( +https://imagemagick.org/) (or optionally [GraphicsMagick]( +http://graphicsmagick.org)) library, so libvips can read any image format +that these libraries can read. -VIPS images are held on disc as a 64-byte header containing basic image +libvips images are held on disc as a 64-byte header containing basic image information like width, height, bands and format, then the image data as a single large block of pixels, left-to-right and top-to-bottom, then an XML extension block holding all the image metadata, such as ICC profiles and EXIF blocks. -When reading from a large VIPS image (or any other format with the same -structure on disc, such as binary PPM), VIPS keeps a set of small rolling +When reading from a large libvips image (or any other format with the same +structure on disc, such as binary PPM), libvips keeps a set of small rolling windows into the file, some small number of scanlines in size. As pixels -are demanded by different threads VIPS will move these windows up and down -the file. As a result, VIPS can process images much larger than RAM, even +are demanded by different threads libvips will move these windows up and down +the file. As a result, libvips can process images much larger than RAM, even on 32-bit machines. -**Data sinks** +## Data sinks -In a demand-driven system, something has to do the demanding. VIPS has a +In a demand-driven system, something has to do the demanding. libvips has a variety of data sinks that you can use to pull image data though a pipeline in various situations. There are sinks that will build a complete image in memory, sinks to draw to a display, sinks to loop over an image (useful @@ -193,25 +183,25 @@ for statistical operations, for example) and sinks to stream an image to disc. The disc sink looks something like this: -![](Sink.png) +![Sink](Sink.png) The sink keeps two buffers\*, each as wide as the image. It starts threads as rapidly as it can up to the concurrency limit, filling each buffer with tiles\*\* of calculated pixels, each thread calculating one tile at once. A separate background thread watches each buffer and, as soon as the last tile in a buffer finishes, writes that complete set of scanlines to disc using -whatever image write library is appropriate. VIPS can write with libjpeg, +whatever image write library is appropriate. libvips can write with libjpeg, libtiff, libpng and others. It then wipes the buffer and repositions it further down the image, ready for the next set of tiles to stream in. These features in combination mean that, once a pipeline of image processing -operations has been built, VIPS can run almost lock-free. This is very +operations has been built, libvips can run almost lock-free. This is very important for SMP scaling: you don't want the synchronization overhead to scale with either the number of threads or the complexity of the pipeline -of operations being performed. As a result, VIPS scales almost linearly +of operations being performed. As a result, libvips scales almost linearly with increasing numbers of threads: -![](Vips-smp.png) +![SMP scaling](Vips-smp.png) Number of CPUs is on the horizontal axis, speedup is on the vertical axis. Taken from the [[Benchmarks]] page. @@ -219,48 +209,48 @@ axis. Taken from the [[Benchmarks]] page. (\* there can actually be more than one, it allocate enough buffers to ensure that there are at least two tiles for every thread) -(\*\* tiles can be any shape and size, VIPS has a tile hint system that +(\*\* tiles can be any shape and size, libvips has a tile hint system that operations use to tell sinks what tile geometry they prefer) -**Operation cache** +## Operation cache -Because VIPS operations are free of side-effects\*, you can cache them. Every -time you call an operation, VIPS searches the cache for a previous call to +Because libvips operations are free of side-effects\*, you can cache them. Every +time you call an operation, libvips searches the cache for a previous call to the same operation with the same arguments. If it finds a match, you get the previous result again. This can give a huge speedup. -By default, VIPS caches the last 100 operation calls. You can also control +By default, libvips caches the last 100 operation calls. You can also control the cache size by memory use or by files opened. -(\* Some vips operations DO have side effects, for example, -`vips_draw_circle()` will draw a circle on an image. These operations emit an +(\* Some libvips operations DO have side effects, for example, +[method@Image.draw_circle] will draw a circle on an image. These operations emit an "invalidate" signal on the image they are called on and this signal makes all downstream operations and caches drop their contents.) -**Operation database and APIs** +## Operation database and APIs -VIPS has around 300 image processing operations written in this style. Each +libvips has around 300 image processing operations written in this style. Each operation is a GObject class. You can use the standard GObject calls to walk the class hierarchy and discover operations, and libvips adds a small amount of extra introspection metadata to handle things like optional arguments. -The C API is a set of simple wrappers -which create class instances for you. The C++ -API is a little fancier and adds things like automatic object lifetime -management. The command-line interface -uses introspection to run any vips operation in the class hierarchy. +The [C API](using-from-c.md) is a set of simple wrappers +which create class instances for you. The [C++ API](using-from-cplusplus.md) +is a little fancier and adds things like automatic object lifetime +management. The [command-line interface](using-the-cli.md) +uses introspection to run any libvips operation in the class hierarchy. -There are bindings for many -other languages on many platforms. Most of these bindings use the -introspection system to generate the binding at run-time. +There are bindings for [many other languages](https://www.libvips.org/) on +many platforms. Most of these bindings use the introspection system to +generate the binding at run-time. -**Snip** +## Snip -The VIPS GUI, nip2, has its own scripting language called Snip. Snip is a +The libvips GUI, nip2, has its own scripting language called Snip. Snip is a lazy, higher-order, purely functional, object oriented language. Almost all of nip2's menus are implemented in it, and nip2 workspaces are Snip programs. -VIPS operations listed in the operation database appear as Snip functions. For +libvips operations listed in the operation database appear as Snip functions. For example, `abs` can be used from Snip as: ``` @@ -268,9 +258,9 @@ example, `abs` can be used from Snip as: a = vips_call "abs" [b] []; ``` -However, `abs` won't work on anything except the primitive vips image type. It -can't be used on any class, or list or number. Definitions in `_stdenv.dev` -wrap each VIPS operation as a higher level Snip operation. For example: +However, `abs` won't work on anything except the primitive `.v` image type. +It can't be used on any class, or list or number. Definitions in `_stdenv.dev` +wrap each libvips operation as a higher level Snip operation. For example: ``` abs x @@ -312,16 +302,15 @@ You can write Snip classes which present functions to the user as menu items. For example, `Math.def` has this: ``` -Math_arithmetic_item = class +Math_arithmetic_item = class Menupullright "_Arithmetic" "basic arithmetic for objects" { Absolute_value_item = class Menuaction "A_bsolute Value" "absolute value of x" { action x = map_unary abs x; } -} +} ``` Now the user can select an object and click `Math / Abs` to find the absolute value of that object. - diff --git a/doc/images/x.jpg b/doc/images/x.jpg deleted file mode 100644 index 4269c82167..0000000000 Binary files a/doc/images/x.jpg and /dev/null differ diff --git a/doc/libvips-arithmetic.md b/doc/libvips-arithmetic.md new file mode 100644 index 0000000000..35d8c4e612 --- /dev/null +++ b/doc/libvips-arithmetic.md @@ -0,0 +1,193 @@ +Title: Operator index > By section > Arithmetic + + + +These operations perform pixel arithmetic, that is, they perform an +arithmetic operation, such as addition, on every pixel in an image or a +pair of images. All (except in a few cases noted below) will work with +images of any type or any mixture of types, of any size and of any number +of bands. + +For binary operations, if the number of bands differs, one of the images +must have one band. In this case, an n-band image is formed from the +one-band image by joining n copies of the one-band image together, and then +the two n-band images are operated upon. + +In the same way, for operations that take an array constant, such as +[method@Image.remainder_const], you can mix single-element arrays or +single-band images freely. + +Arithmetic operations try to preserve precision by increasing the number of +bits in the output image when necessary. Generally, this follows the ANSI C +conventions for type promotion, so multiplying two +[enum@Vips.BandFormat.UCHAR] images together, for example, produces a +[enum@Vips.BandFormat.USHORT] image, and taking the [method@Image.cos] of a +[enum@Vips.BandFormat.USHORT] image produces [enum@Vips.BandFormat.FLOAT] +image. + +After processing, use [method@Image.cast] and friends to take then format +back down again.[method@Image.cast_uchar], for example, will cast any image +down to 8-bit unsigned. + +Images have an interpretation: a meaning for the pixel values. With +[enum@Vips.Interpretation.SRGB], for example, the first three bands will be +interpreted (for example, by a saver like [method@Image.jpegsave]) as R, G +and B, with values in 0 - 255, and any fourth band will be interpreted as an +alpha channel. + +After arithmetic, you may wish to change the interpretation (for example to +save as 16-bit PNG). Use [method@Image.copy] to change the interpretation +without changing pixels. + +For binary arithmetic operations, type promotion occurs in two stages. +First, the two input images are cast up to the smallest common format, +that is, the type with the smallest range that can represent the full +range of both inputs. This conversion can be represented as a table: + +## Smallest common format + +| **@in2/@in1** | **uchar** | **char** | **ushort** | **short** | **uint** | **int** | **float** | **double** | **complex** | **double complex** | +|----------------|----------------|----------------|----------------|----------------|----------------|----------------|----------------|----------------|----------------|--------------------| +| uchar | ushort | short | ushort | short | uint | int | float | double | complex | double complex | +| char | short | short | short | short | int | int | float | double | complex | double complex | +| ushort | ushort | short | ushort | short | uint | int | float | double | complex | double complex | +| short | short | short | short | short | int | int | float | double | complex | double complex | +| uint | uint | int | uint | int | uint | int | float | double | complex | double complex | +| int | int | int | int | int | int | int | float | double | complex | double complex | +| float | float | float | float | float | float | float | float | double | complex | double complex | +| double | double | double | double | double | double | double | double | double | double complex | double complex | +| complex | complex | complex | complex | complex | complex | complex | complex | double complex | complex | double complex | +| double complex | double complex | double complex | double complex | double complex | double complex | double complex | double complex | double complex | double complex | double complex | + +In the second stage, the operation is performed between the two identical +types to form the output. The details vary between operations, but +generally the principle is that the output type should be large enough to +represent the whole range of possible values, except that int never becomes +float. + +## Functions + +* [method@Image.add] +* [func@Image.sum] +* [method@Image.subtract] +* [method@Image.multiply] +* [method@Image.divide] +* [method@Image.linear] +* [method@Image.linear1] +* [method@Image.remainder] +* [method@Image.remainder_const] +* [method@Image.remainder_const1] +* [method@Image.invert] +* [method@Image.abs] +* [method@Image.sign] +* [method@Image.clamp] +* [method@Image.maxpair] +* [method@Image.minpair] +* [method@Image.round] +* [method@Image.floor] +* [method@Image.ceil] +* [method@Image.rint] +* [method@Image.math] +* [method@Image.sin] +* [method@Image.cos] +* [method@Image.tan] +* [method@Image.asin] +* [method@Image.acos] +* [method@Image.atan] +* [method@Image.exp] +* [method@Image.exp10] +* [method@Image.log] +* [method@Image.log10] +* [method@Image.sinh] +* [method@Image.cosh] +* [method@Image.tanh] +* [method@Image.asinh] +* [method@Image.acosh] +* [method@Image.atanh] +* [method@Image.complex] +* [method@Image.polar] +* [method@Image.rect] +* [method@Image.conj] +* [method@Image.complex2] +* [method@Image.cross_phase] +* [method@Image.complexget] +* [method@Image.real] +* [method@Image.imag] +* [method@Image.complexform] +* [method@Image.relational] +* [method@Image.equal] +* [method@Image.notequal] +* [method@Image.less] +* [method@Image.lesseq] +* [method@Image.more] +* [method@Image.moreeq] +* [method@Image.relational_const] +* [method@Image.equal_const] +* [method@Image.notequal_const] +* [method@Image.less_const] +* [method@Image.lesseq_const] +* [method@Image.more_const] +* [method@Image.moreeq_const] +* [method@Image.relational_const1] +* [method@Image.equal_const1] +* [method@Image.notequal_const1] +* [method@Image.less_const1] +* [method@Image.lesseq_const1] +* [method@Image.more_const1] +* [method@Image.moreeq_const1] +* [method@Image.boolean] +* [method@Image.andimage] +* [method@Image.orimage] +* [method@Image.eorimage] +* [method@Image.lshift] +* [method@Image.rshift] +* [method@Image.boolean_const] +* [method@Image.andimage_const] +* [method@Image.orimage_const] +* [method@Image.eorimage_const] +* [method@Image.lshift_const] +* [method@Image.rshift_const] +* [method@Image.boolean_const1] +* [method@Image.andimage_const1] +* [method@Image.orimage_const1] +* [method@Image.eorimage_const1] +* [method@Image.lshift_const1] +* [method@Image.rshift_const1] +* [method@Image.math2] +* [method@Image.pow] +* [method@Image.wop] +* [method@Image.atan2] +* [method@Image.math2_const] +* [method@Image.pow_const] +* [method@Image.wop_const] +* [method@Image.atan2_const] +* [method@Image.math2_const1] +* [method@Image.pow_const1] +* [method@Image.wop_const1] +* [method@Image.atan2_const1] +* [method@Image.avg] +* [method@Image.deviate] +* [method@Image.min] +* [method@Image.max] +* [method@Image.stats] +* [method@Image.measure] +* [method@Image.find_trim] +* [method@Image.getpoint] +* [method@Image.hist_find] +* [method@Image.hist_find_ndim] +* [method@Image.hist_find_indexed] +* [method@Image.hough_line] +* [method@Image.hough_circle] +* [method@Image.project] +* [method@Image.profile] + +## Enumerations + +* [enum@OperationMath] +* [enum@OperationMath2] +* [enum@OperationRound] +* [enum@OperationRelational] +* [enum@OperationBoolean] +* [enum@OperationComplex] +* [enum@OperationComplex2] +* [enum@OperationComplexget] diff --git a/doc/libvips-basic.md b/doc/libvips-basic.md new file mode 100644 index 0000000000..992dedbbcb --- /dev/null +++ b/doc/libvips-basic.md @@ -0,0 +1,80 @@ +Title: Operator index > By section > Basic + + + +A selection of basic aliases, [alias@GObject.Type] helpers and macro +definitions used by libvips. + +## Structs + +* [struct@Area] +* [struct@ArrayDouble] +* [struct@ArrayImage] +* [struct@ArrayInt] +* [struct@Blob] +* [struct@RefString] +* [struct@SaveString] + +## Aliases + +* [alias@Pel] + +## Callbacks + +* [callback@CallbackFn] +* [callback@SListMap2Fn] +* [callback@SListMap4Fn] +* [callback@SListFold2Fn] + +## Functions + +* [method@Area.copy] +* [func@Area.free_cb] +* [method@Area.unref] +* [ctor@Area.new] +* [ctor@Area.new_array] +* [ctor@Area.new_array_object] +* [method@Area.get_data] +* [ctor@RefString.new] +* [method@RefString.get] +* [ctor@Blob.new] +* [func@Blob.copy] +* [method@Blob.get] +* [method@Blob.set] +* [ctor@ArrayDouble.new] +* [ctor@ArrayDouble.newv] +* [method@ArrayDouble.get] +* [ctor@ArrayInt.new] +* [ctor@ArrayInt.newv] +* [method@ArrayInt.get] +* [ctor@ArrayImage.new] +* [ctor@ArrayImage.newv] +* [ctor@ArrayImage.empty] +* [method@ArrayImage.append] +* [method@ArrayImage.get] +* [func@value_set_area] +* [func@value_get_area] +* [func@value_get_save_string] +* [func@value_set_save_string] +* [func@value_set_save_stringf] +* [func@value_get_ref_string] +* [func@value_set_ref_string] +* [func@value_get_blob] +* [func@value_set_blob] +* [func@value_set_blob_free] +* [func@value_set_array] +* [func@value_get_array] +* [func@value_get_array_double] +* [func@value_set_array_double] +* [func@value_get_array_image] +* [func@value_set_array_image] +* [func@value_get_array_int] +* [func@value_set_array_int] +* [func@value_get_array_object] +* [func@value_set_array_object] + +## Function macros + +* [func@DEPRECATED_FOR] +* [func@DEPRECATED_MACRO_FOR] +* [func@ARRAY_ADDR] diff --git a/doc/libvips-colour.md b/doc/libvips-colour.md new file mode 100644 index 0000000000..b37fb4bf7e --- /dev/null +++ b/doc/libvips-colour.md @@ -0,0 +1,188 @@ +Title: Operator index > By section > Colour + + + +These operators let you transform coordinates and images between colour +spaces, calculate colour differences, and move to and from device spaces. + +All operations process colour from the first few bands and pass other bands +through unaltered. This means you can operate on images with alpha channels +safely. If you move to or from 16-bit RGB, any alpha channels are rescaled +for you. + +Radiance images have four 8-bits bands and store 8 bits of R, G and B and +another 8 bits of exponent, common to all channels. They are widely used in +the HDR imaging community. + +The colour functions can be divided into three main groups. First, +functions to transform images between the different colour spaces supported +by libvips: +[enum@Vips.Interpretation.SRGB], [enum@Vips.Interpretation.SCRGB], +[enum@Vips.Interpretation.B_W], [enum@Vips.Interpretation.XYZ], +[enum@Vips.Interpretation.YXY], [enum@Vips.Interpretation.LAB], +[enum@Vips.Interpretation.LCH], and [enum@Vips.Interpretation.CMC]. + +There are also a set of minor colourspaces which are one of the above in a +slightly different format: +[enum@Vips.Interpretation.LAB], [enum@Vips.Interpretation.LABQ], +[enum@Vips.Interpretation.LABS], [enum@Vips.Interpretation.LCH], +[enum@Vips.Interpretation.RGB16], and [enum@Vips.Interpretation.GREY16]. + +Use [method@Image.colourspace] to move an image to a target colourspace +using the best sequence of colour transform operations. + +Secondly, there are a set of operations for calculating colour difference +metrics. Finally, libvips wraps LittleCMS and uses it to provide a set of +operations for reading and writing images with ICC profiles. + +This figure shows how the libvips colour spaces interconvert: + +![Interconvert](interconvert.png) + +The colour spaces supported by libvips are: + +- [enum@Vips.Interpretation.LAB]: CIELAB '76 colourspace with a D65 white. + This uses three floats for each band, and bands have the obvious range.

+ There are two variants, [enum@Vips.Interpretation.LABQ] and + [enum@Vips.Interpretation.LABS], which use ints to store values. These are + less precise, but can be quicker to store and process.

+ [enum@Vips.Interpretation.LCH] is the same, but with a\*b\* as polar + coordinates. Hue is expressed in degrees. + +- [enum@Vips.Interpretation.XYZ]: CIE XYZ. This uses three floats. + See [const@D75_X0] and friends for values for the ranges under various + illuminants.

+ [enum@Vips.Interpretation.YXY] is the same, but with little x and y. + +- [enum@Vips.Interpretation.SCRGB]: a linear colourspace with the sRGB + primaries. This is useful if you need linear light and don't care + much what the primaries are.

+ Linearization is performed with the usual sRGB equations, see below. + +- [enum@Vips.Interpretation.SRGB]: the standard sRGB colourspace, see: + [wikipedia sRGB](http://en.wikipedia.org/wiki/SRGB).

+ This uses three 8-bit values for each of RGB.

+ [enum@Vips.Interpretation.RGB16] is the same, but using three 16-bit values + for RGB.

+ [enum@Vips.Interpretation.HSV] is sRGB, but in polar coordinates. + [enum@Vips.Interpretation.LCH] is much better, only use HSV if you have to. + +- [enum@Vips.Interpretation.B_W]: a monochrome image, roughly G from sRGB. + The grey value is calculated in linear [enum@Vips.Interpretation.SCRGB] + space with RGB ratios 0.2126, 0.7152, 0.0722 as defined by CIE 1931 linear + luminance.

+ [enum@Vips.Interpretation.GREY16] is the same, but using 16 bits. + +- [enum@Vips.Interpretation.CMC]: a colour space based on the CMC(1:1) + colour difference measurement. This is a highly uniform colour space, + and much better than CIELAB for expressing small differences.

+ The CMC colourspace is described in “Uniform Colour Space Based on the + CMC(l:c) Colour-difference Formula”, M R Luo and B Rigg, Journal of the + Society of Dyers and Colourists, vol 102, 1986. Distances in this + colourspace approximate, within 10% or so, differences in the CMC(l:c) + colour difference formula.

+ You can calculate metrics like CMC(2:1) by scaling the spaces before + finding differences. + +## Functions + +* [method@Image.colourspace_issupported] +* [method@Image.colourspace] +* [method@Image.LabQ2sRGB] +* [method@Image.rad2float] +* [method@Image.float2rad] +* [method@Image.LabS2LabQ] +* [method@Image.LabQ2LabS] +* [method@Image.LabQ2Lab] +* [method@Image.Lab2LabQ] +* [method@Image.LCh2Lab] +* [method@Image.Lab2LCh] +* [method@Image.Lab2XYZ] +* [method@Image.XYZ2Lab] +* [method@Image.XYZ2scRGB] +* [method@Image.scRGB2sRGB] +* [method@Image.scRGB2BW] +* [method@Image.sRGB2scRGB] +* [method@Image.scRGB2XYZ] +* [method@Image.HSV2sRGB] +* [method@Image.sRGB2HSV] +* [method@Image.LCh2CMC] +* [method@Image.CMC2LCh] +* [method@Image.XYZ2Yxy] +* [method@Image.Yxy2XYZ] +* [method@Image.LabS2Lab] +* [method@Image.Lab2LabS] +* [method@Image.CMYK2XYZ] +* [method@Image.XYZ2CMYK] +* [ctor@Blob.profile_load] +* [func@icc_present] +* [method@Image.icc_transform] +* [method@Image.icc_import] +* [method@Image.icc_export] +* [method@Image.icc_ac2rc] +* [func@icc_is_compatible_profile] +* [method@Image.dE76] +* [method@Image.dE00] +* [method@Image.dECMC] +* [func@col_Lab2XYZ] +* [func@col_XYZ2Lab] +* [func@col_ab2h] +* [func@col_ab2Ch] +* [func@col_Ch2ab] +* [func@col_L2Lcmc] +* [func@col_C2Ccmc] +* [func@col_Ch2hcmc] +* [func@col_make_tables_CMC] +* [func@col_Lcmc2L] +* [func@col_Ccmc2C] +* [func@col_Chcmc2h] +* [func@col_sRGB2scRGB_8] +* [func@col_sRGB2scRGB_16] +* [func@col_sRGB2scRGB_8_noclip] +* [func@col_sRGB2scRGB_16_noclip] +* [func@col_scRGB2XYZ] +* [func@col_XYZ2scRGB] +* [func@col_scRGB2sRGB_8] +* [func@col_scRGB2sRGB_16] +* [func@col_scRGB2BW_16] +* [func@col_scRGB2BW_8] +* [func@pythagoras] +* [func@col_dE00] + +## Constants + +* [const@D93_X0] +* [const@D93_Y0] +* [const@D93_Z0] +* [const@D75_X0] +* [const@D75_Y0] +* [const@D75_Z0] +* [const@D65_X0] +* [const@D65_Y0] +* [const@D65_Z0] +* [const@D55_X0] +* [const@D55_Y0] +* [const@D55_Z0] +* [const@D50_X0] +* [const@D50_Y0] +* [const@D50_Z0] +* [const@A_X0] +* [const@A_Y0] +* [const@A_Z0] +* [const@B_X0] +* [const@B_Y0] +* [const@B_Z0] +* [const@C_X0] +* [const@C_Y0] +* [const@C_Z0] +* [const@E_X0] +* [const@E_Y0] +* [const@E_Z0] +* [const@D3250_X0] +* [const@D3250_Y0] +* [const@D3250_Z0] + +## Enumerations + +* [enum@Intent] +* [enum@PCS] diff --git a/doc/libvips-conversion.md b/doc/libvips-conversion.md new file mode 100644 index 0000000000..198a12ad6f --- /dev/null +++ b/doc/libvips-conversion.md @@ -0,0 +1,93 @@ +Title: Operator index > By section > Conversion + + + +These operations convert an image in some way. They can be split into two +main groups. + +The first set of operations change an image's format in some way. You can +change the band format (for example, cast to 32-bit unsigned int), form +complex images from real images, convert images to matrices and back, change +header fields, and a few others. + +The second group move pixels about in some way. You can flip, rotate, +extract, insert and join pairs of images in various ways. + +## Functions + +* [method@Image.copy] +* [method@Image.tilecache] +* [method@Image.linecache] +* [method@Image.sequential] +* [method@Image.copy_file] +* [method@Image.embed] +* [method@Image.gravity] +* [method@Image.flip] +* [method@Image.insert] +* [method@Image.join] +* [func@Image.arrayjoin] +* [method@Image.extract_area] +* [method@Image.crop] +* [method@Image.smartcrop] +* [method@Image.extract_band] +* [method@Image.replicate] +* [method@Image.grid] +* [method@Image.transpose3d] +* [method@Image.wrap] +* [method@Image.rot] +* [method@Image.rot90] +* [method@Image.rot180] +* [method@Image.rot270] +* [method@Image.rot45] +* [method@Image.autorot_remove_angle] +* [method@Image.autorot] +* [method@Image.zoom] +* [method@Image.subsample] +* [method@Image.cast] +* [method@Image.cast_uchar] +* [method@Image.cast_char] +* [method@Image.cast_ushort] +* [method@Image.cast_short] +* [method@Image.cast_uint] +* [method@Image.cast_int] +* [method@Image.cast_float] +* [method@Image.cast_double] +* [method@Image.cast_complex] +* [method@Image.cast_dpcomplex] +* [method@Image.scale] +* [method@Image.msb] +* [method@Image.byteswap] +* [func@Image.bandjoin] +* [method@Image.bandjoin2] +* [method@Image.bandjoin_const] +* [method@Image.bandjoin_const1] +* [func@Image.bandrank] +* [method@Image.bandfold] +* [method@Image.bandunfold] +* [method@Image.bandbool] +* [method@Image.bandand] +* [method@Image.bandor] +* [method@Image.bandeor] +* [method@Image.bandmean] +* [method@Image.recomb] +* [method@Image.ifthenelse] +* [func@Image.switch] +* [method@Image.flatten] +* [method@Image.addalpha] +* [method@Image.premultiply] +* [method@Image.unpremultiply] +* [func@Image.composite] +* [method@Image.composite2] +* [method@Image.falsecolour] +* [method@Image.gamma] + +## Enumerations + +* [enum@Extend] +* [enum@CompassDirection] +* [enum@Direction] +* [enum@Align] +* [enum@Angle] +* [enum@Angle45] +* [enum@Interesting] +* [enum@BlendMode] diff --git a/doc/libvips-convolution.md b/doc/libvips-convolution.md new file mode 100644 index 0000000000..fb5a18cc83 --- /dev/null +++ b/doc/libvips-convolution.md @@ -0,0 +1,29 @@ +Title: Operator index > By section > Convolution + + + +These operations convolve an image in some way, or are operations based on +simple convolution, or are useful with convolution. + +## Functions + +* [method@Image.conv] +* [method@Image.convf] +* [method@Image.convi] +* [method@Image.conva] +* [method@Image.convsep] +* [method@Image.convasep] +* [method@Image.compass] +* [method@Image.gaussblur] +* [method@Image.sharpen] +* [method@Image.spcor] +* [method@Image.fastcor] +* [method@Image.sobel] +* [method@Image.scharr] +* [method@Image.prewitt] +* [method@Image.canny] + +## Enumerations + +* [enum@Combine] +* [enum@Precision] diff --git a/doc/libvips-create.md b/doc/libvips-create.md new file mode 100644 index 0000000000..65796c0e1d --- /dev/null +++ b/doc/libvips-create.md @@ -0,0 +1,42 @@ +Title: Operator index > By section > Create + + + +These functions generate various images. You can combine them with +the arithmetic and rotate functions to build more complicated images. + +## Functions + +* [ctor@Image.black] +* [ctor@Image.xyz] +* [ctor@Image.grey] +* [ctor@Image.gaussmat] +* [ctor@Image.logmat] +* [ctor@Image.text] +* [ctor@Image.gaussnoise] +* [ctor@Image.eye] +* [ctor@Image.sines] +* [ctor@Image.zone] +* [ctor@Image.sdf] +* [ctor@Image.identity] +* [method@Image.buildlut] +* [method@Image.invertlut] +* [ctor@Image.tonelut] +* [ctor@Image.mask_ideal] +* [ctor@Image.mask_ideal_ring] +* [ctor@Image.mask_ideal_band] +* [ctor@Image.mask_butterworth] +* [ctor@Image.mask_butterworth_ring] +* [ctor@Image.mask_butterworth_band] +* [ctor@Image.mask_gaussian] +* [ctor@Image.mask_gaussian_ring] +* [ctor@Image.mask_gaussian_band] +* [ctor@Image.mask_fractal] +* [ctor@Image.fractsurf] +* [ctor@Image.worley] +* [ctor@Image.perlin] + +## Enumerations + +* [enum@TextWrap] +* [enum@SdfShape] diff --git a/doc/libvips-docs.xml b/doc/libvips-docs.xml deleted file mode 100644 index 0f31388a25..0000000000 --- a/doc/libvips-docs.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - -]> - - - Codestin Search App - - For libvips &version;. The latest version of this documentation - can be found on the libvips - website. - - - - - Codestin Search App - - libvips is a free image processing system. It is good with large - images (images larger than the amount of RAM you have available), with - many CPUs (speed scales linearly to at least 32 threads), for working - with colour, for scientific analysis and for general research - and development. As well as JPEG, TIFF and PNG images, it also - supports scientific formats like FITS, Matlab, Analyze, PFM, - Radiance and OpenSlide. It works on many UNIX-like platforms, - as well as Windows and OS X. libvips is released under the GNU Library - General Public License (GNU LGPL). - - - - - - - - - - - - - - - - - - - - - Codestin Search App - - - - - - - - - - - - - - - - - - - - Codestin Search App - - - - - - - - - - - - - - - - - Codestin Search App - - - - - - - - Codestin Search App - - - - - Codestin Search App - - - - - - diff --git a/doc/libvips-draw.md b/doc/libvips-draw.md new file mode 100644 index 0000000000..39f09b064d --- /dev/null +++ b/doc/libvips-draw.md @@ -0,0 +1,48 @@ +Title: Operator index > By section > Draw + + + +These operations directly modify the image. They do not thread, on 32-bit +machines they will be limited to 2GB images, and a little care needs to be +taken if you use them as part of an image pipeline. They are mostly supposed +to be useful for paintbox-style programs. + +libvips operations are all functional: they take zero or more existing input +images and generate zero or more new output images. Images are never altered, +you always create new images. This means libvips can cache and thread very +aggressively. + +The downside is that creating entirely fresh images each time can be very +slow. libvips has a range of tricks to avoid these problems, but there are +still times when you really have to be able to modify an image. An example +might be drawing a curved line from a set of straight line segments: if you +need to draw 1,000 straight lines, a 1,000 operation-deep pipeline is going +to be a slow way to do it. This is where the draw operations come in. + +To use these operations, use [method@Image.copy_memory] to make a private +memory copy of the image you want to modify, 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. + +## Functions + +* [method@Image.draw_rect] +* [method@Image.draw_rect1] +* [method@Image.draw_point] +* [method@Image.draw_point1] +* [method@Image.draw_image] +* [method@Image.draw_mask] +* [method@Image.draw_mask1] +* [method@Image.draw_line] +* [method@Image.draw_line1] +* [method@Image.draw_circle] +* [method@Image.draw_circle1] +* [method@Image.draw_flood] +* [method@Image.draw_flood1] +* [method@Image.draw_smudge] + +## Enumerations + +* [enum@CombineMode] diff --git a/doc/libvips-error.md b/doc/libvips-error.md new file mode 100644 index 0000000000..a42c74ee54 --- /dev/null +++ b/doc/libvips-error.md @@ -0,0 +1,99 @@ +Title: Operator index > By section > Error + + + +libvips maintains an error buffer (a log of localised text messages), a set +of functions for adding messages, and a way to access and clear the buffer. + +The error buffer is global, that is, it is shared between all threads. You +can add to the buffer from any thread (there is a lock to prevent +corruption), but it's sensible to only read and clear the buffer from the +main thread of execution. + +The general principle is: if you detect an error, log a message for the +user. If a function you call detects an error, just propagate it and don't +add another message. + +```c +VipsImage *im; + +if (!(im = vips_image_new_from_file(filename, NULL))) + // vips_image_new_from_file() will set a message, we don't need to + return -1; + +if (vips_image_get_width(im) < 100) { + // we have detected an error, we must set a message + vips_error("myprogram", "%s", _("width too small")); + return -1; +} +``` + +The domain argument most of these functions take is not localised and is +supposed to indicate the component which failed. + +libvips uses [func@GLib.warning] and [func@GLib.info] to send warning and +information messages to the user. You can use the usual GLib mechanisms to +display or divert these messages. For example, info messages are hidden by +default, but you can see them with: + +```bash +$ G_MESSAGES_DEBUG=VIPS vipsthumbnail k2.jpg +VIPS-INFO: thumbnailing k2.jpg +VIPS-INFO: selected loader is VipsForeignLoadJpegFile +VIPS-INFO: input size is 1450 x 2048 +VIPS-INFO: loading jpeg with factor 8 pre-shrink +VIPS-INFO: converting to processing space srgb +VIPS-INFO: residual reducev by 0.5 +VIPS-INFO: 13 point mask +VIPS-INFO: using vector path +VIPS-INFO: residual reduceh by 0.5 +VIPS-INFO: 13 point mask +VIPS-INFO: thumbnailing k2.jpg as ./tn_k2.jpg +``` + +## Functions + +* [func@error_buffer] +* [func@error_buffer_copy] +* [func@error_clear] +* [func@error_freeze] +* [func@error_thaw] +* [func@error] +* [func@verror] +* [func@error_system] +* [func@verror_system] +* [func@error_g] +* [func@g_error] +* [func@error_exit] +* [func@check_uncoded] +* [func@check_coding] +* [func@check_coding_known] +* [func@check_coding_noneorlabq] +* [func@check_coding_same] +* [func@check_mono] +* [func@check_bands] +* [func@check_bands_1or3] +* [func@check_bands_atleast] +* [func@check_bands_1orn] +* [func@check_bands_1orn_unary] +* [func@check_bands_same] +* [func@check_bandno] +* [func@check_int] +* [func@check_uint] +* [func@check_uintorf] +* [func@check_noncomplex] +* [func@check_complex] +* [func@check_twocomponents] +* [func@check_format] +* [func@check_u8or16] +* [func@check_8or16] +* [func@check_u8or16orf] +* [func@check_format_same] +* [func@check_size_same] +* [func@check_oddsquare] +* [func@check_vector_length] +* [func@check_vector] +* [func@check_hist] +* [func@check_matrix] +* [func@check_separable] +* [func@check_precision_intfloat] diff --git a/doc/libvips-freqfilt.md b/doc/libvips-freqfilt.md new file mode 100644 index 0000000000..8589d5ba4a --- /dev/null +++ b/doc/libvips-freqfilt.md @@ -0,0 +1,14 @@ +Title: Operator index > By section > Fourier + + + +To and from Fourier space, filter in Fourier space, convert Fourier-space +images to a displayable form. + +## Functions + +* [method@Image.fwfft] +* [method@Image.invfft] +* [method@Image.freqmult] +* [method@Image.spectrum] +* [method@Image.phasecor] diff --git a/doc/libvips-from-C++.md b/doc/libvips-from-C++.md deleted file mode 100644 index b1f5063042..0000000000 --- a/doc/libvips-from-C++.md +++ /dev/null @@ -1,19 +0,0 @@ - - libvips from C++ - 3 - libvips - - - - C++ - Using libvips from C++ - - -libvips comes with a convenient C++ API. It is a very thin wrapper over the -C API and adds automatic reference counting, exceptions, operator -overloads, and automatic constant expansion. - -See the - -C++ API documentation -for more details. diff --git a/doc/libvips-from-C++.xml b/doc/libvips-from-C++.xml deleted file mode 100644 index a90293cea2..0000000000 --- a/doc/libvips-from-C++.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - libvips from C++ 3 libvips - - - C++ Using libvips from C++ - - - libvips comes with a convenient C++ API. It is a very thin wrapper over the C API and adds automatic reference counting, exceptions, operator overloads, and automatic constant expansion. - - - See the C++ API documentation for more details. - - - - diff --git a/doc/libvips-generate.md b/doc/libvips-generate.md new file mode 100644 index 0000000000..72d71a4667 --- /dev/null +++ b/doc/libvips-generate.md @@ -0,0 +1,30 @@ +Title: Operator index > By section > Generate + + + +These functions let you attach generate functions to images and ask for +regions of images to be calculated. + +## Callbacks + +* [callback@GenerateFn] +* [callback@RegionWrite] +* [callback@SinkNotify] +* [callback@StartFn] +* [callback@StopFn] + +## Functions + +* [method@Image.sink_disc] +* [method@Image.sink] +* [method@Image.sink_tile] +* [method@Image.sink_screen] +* [func@sink_memory] +* [func@start_one] +* [func@stop_one] +* [func@start_many] +* [func@stop_many] +* [func@allocate_input_array] +* [method@Image.generate] +* [func@Image.pipeline_array] +* [method@Image.pipelinev] diff --git a/doc/libvips-header.md b/doc/libvips-header.md new file mode 100644 index 0000000000..c8f200b965 --- /dev/null +++ b/doc/libvips-header.md @@ -0,0 +1,122 @@ +Title: Operator index > By section > Header + + + +libvips supports getting and setting image header data (including metadata) +in a uniform way. + +Use [method@Image.get_typeof] to test for the existence and +[alias@GObject.Type] of a header field. + +You can attach arbitrary metadata to images. Metadata is copied as images +are processed, so all images which used this image as input, directly or +indirectly, will have this same bit of metadata attached to them. Copying +is implemented with reference-counted pointers, so it is efficient, even for +large items of data. This does however mean that metadata items need to be +immutable. Metadata is handy for things like ICC profiles or EXIF data. + +Various convenience functions (e.g. [method@Image.set_int]) let you easily +attach simple types like numbers, strings and memory blocks to images. +Use [method@Image.map] to loop over an image's fields, including all metadata. + +Items of metadata are identified by strings. Some strings are reserved, for +example the ICC profile for an image is known by convention as +"icc-profile-data" (i.e. the [const@META_ICC_NAME] constant). + +If you save an image in `.v` format, all metadata (with a restriction, see +below) is automatically saved for you in a block of XML at the end of the +file. When you load a `.v` image, the metadata is restored. You can use the +`vipsedit` command-line tool to extract or replace this block of XML. + +`.v` metadata is based on [struct@GObject.Value]. See the docs for that +system if you want to do fancy stuff such as defining a new metadata type. +libvips defines a new [struct@GObject.Value] called [struct@SaveString], a +variety of string, see [func@value_set_save_string]. If your +[struct@GObject.Value] can be transformed to [struct@SaveString], it will +be saved and loaded to and from `.v` files for you. + +libvips provides a couple of base classes which implement reference-counted +areas of memory. If you base your metadata on one of these types, it can be +copied between images efficiently. + +## Callbacks + +* [callback@ImageMapFn] + +## Functions + +* [func@format_sizeof] +* [func@format_sizeof_unsafe] +* [func@Interpretation.max_alpha] +* [method@Image.get_width] +* [method@Image.get_height] +* [method@Image.get_bands] +* [method@Image.get_format] +* [func@Image.get_format_max] +* [method@Image.guess_format] +* [method@Image.get_coding] +* [method@Image.get_interpretation] +* [method@Image.guess_interpretation] +* [method@Image.get_xres] +* [method@Image.get_yres] +* [method@Image.get_xoffset] +* [method@Image.get_yoffset] +* [method@Image.get_filename] +* [method@Image.get_mode] +* [method@Image.get_scale] +* [method@Image.get_offset] +* [method@Image.get_page_height] +* [method@Image.get_n_pages] +* [method@Image.get_n_subifds] +* [method@Image.get_orientation] +* [method@Image.get_orientation_swap] +* [method@Image.get_concurrency] +* [method@Image.get_data] +* [method@Image.init_fields] +* [method@Image.set] +* [method@Image.get] +* [method@Image.get_as_string] +* [method@Image.get_typeof] +* [method@Image.remove] +* [method@Image.map] +* [method@Image.get_fields] +* [method@Image.set_area] +* [method@Image.get_area] +* [method@Image.set_blob] +* [method@Image.set_blob_copy] +* [method@Image.get_blob] +* [method@Image.get_int] +* [method@Image.set_int] +* [method@Image.get_double] +* [method@Image.set_double] +* [method@Image.get_string] +* [method@Image.set_string] +* [method@Image.print_field] +* [method@Image.get_image] +* [method@Image.set_image] +* [method@Image.set_array_int] +* [method@Image.get_array_int] +* [method@Image.get_array_double] +* [method@Image.set_array_double] +* [method@Image.history_printf] +* [method@Image.history_args] +* [method@Image.get_history] + +## Constants + +* [const@META_EXIF_NAME] +* [const@META_XMP_NAME] +* [const@META_IPTC_NAME] +* [const@META_PHOTOSHOP_NAME] +* [const@META_ICC_NAME] +* [const@META_IMAGEDESCRIPTION] +* [const@META_RESOLUTION_UNIT] +* [const@META_BITS_PER_SAMPLE] +* [const@META_PALETTE] +* [const@META_LOADER] +* [const@META_SEQUENTIAL] +* [const@META_ORIENTATION] +* [const@META_PAGE_HEIGHT] +* [const@META_N_PAGES] +* [const@META_N_SUBIFDS] +* [const@META_CONCURRENCY] diff --git a/doc/libvips-histogram.md b/doc/libvips-histogram.md new file mode 100644 index 0000000000..034726c430 --- /dev/null +++ b/doc/libvips-histogram.md @@ -0,0 +1,36 @@ +Title: Operator index > By section > Histogram + + + +Histograms and look-up tables are 1xn or nx1 images, where n is less than +256 or less than 65536, corresponding to 8- and 16-bit unsigned int images. +They are tagged with a [enum@Interpretation] of +[enum@Vips.Interpretation.HISTOGRAM] and usually displayed by user-interfaces +such as nip2 as plots rather than images. + +These functions can be broadly grouped as things to find or build +histograms ([method@Image.hist_find], [method@Image.hist_find_indexed], +[method@Image.hist_find_ndim], [method@Image.buildlut], +[ctor@Image.identity]), operations that manipulate histograms in some way +([method@Image.hist_cum], [method@Image.hist_norm]), +operations to apply histograms ([method@Image.maplut]), and a variety of +utility operations. + +A final group of operations build tone curves. These are useful in pre-press +work for adjusting the appearance of images. They are designed for +CIELAB images, but might be useful elsewhere. + +## Functions + +* [method@Image.maplut] +* [method@Image.percent] +* [method@Image.stdif] +* [method@Image.hist_cum] +* [method@Image.hist_norm] +* [method@Image.hist_equal] +* [method@Image.hist_plot] +* [method@Image.hist_match] +* [method@Image.hist_local] +* [method@Image.hist_ismonotonic] +* [method@Image.hist_entropy] +* [method@Image.case] diff --git a/doc/libvips-memory.md b/doc/libvips-memory.md new file mode 100644 index 0000000000..ad9443e7d4 --- /dev/null +++ b/doc/libvips-memory.md @@ -0,0 +1,41 @@ +Title: Operator index > By section > Memory + + + +These functions cover two main areas. + +First, some simple utility functions over the underlying [func@GLib.malloc] / +[func@GLib.free] functions. Memory that is allocated and freed using these +functions is interchangeable with any other GLib library. + +Second, a pair of functions, [func@tracked_malloc] and [func@tracked_free], +which are NOT compatible. If you [func@GLib.free] memory that has been +allocated with [func@tracked_malloc] you will see crashes. + +The tracked functions are only suitable for large allocations internal to the +library, for example pixel buffers. libvips watches the total amount of live +tracked memory and uses this information to decide when to trim caches. + +## Functions + +* [func@malloc] +* [func@strdup] +* [func@tracked_free] +* [func@tracked_aligned_free] +* [func@tracked_malloc] +* [func@tracked_aligned_alloc] +* [func@tracked_get_mem] +* [func@tracked_get_mem_highwater] +* [func@tracked_get_allocs] +* [func@tracked_open] +* [func@tracked_close] +* [func@tracked_get_files] + +## Function macros + +* [func@FREEF] +* [func@FREE] +* [func@SETSTR] +* [func@MALLOC] +* [func@NEW] +* [func@ARRAY] diff --git a/doc/libvips-morphology.md b/doc/libvips-morphology.md new file mode 100644 index 0000000000..6d73aa1134 --- /dev/null +++ b/doc/libvips-morphology.md @@ -0,0 +1,60 @@ +Title: Operator index > By section > Morphology + + + +The morphological functions search images for particular patterns of pixels, +specified with the mask argument, either adding or removing pixels when they +find a match. They are useful for cleaning up images --- for example, you +might threshold an image, and then use one of the morphological functions +to remove all single isolated pixels from the result. + +If you combine the morphological operators with the mask rotators +([method@Image.rot45], for example) and apply them repeatedly, you can +achieve very complicated effects: you can thin, prune, fill, open edges, +close gaps, and many others. For example, see “Fundamentals of Digital +Image Processing” by A. Jain, pp 384-388, Prentice-Hall, 1989 for more +ideas. + +Beware that libvips reverses the usual image processing convention, by +assuming white objects (non-zero pixels) on a black background (zero +pixels). + +The mask you give to the morphological functions should contain only the +values 0 (for background), 128 (for don't care) and 255 (for object). The +mask must have odd length sides --- the origin of the mask is taken to be +the centre value. For example, the mask: + +```c +VipsImage *mask = vips_image_new_matrixv(3, 3, + 128.0, 255.0, 128.0, + 255.0, 255.0, 255.0, + 128.0, 255.0, 128.0); +``` + +applied to an image with [method@Image.morph] +[enum@Vips.OperationMorphology.DILATE] will do a 4-connected dilation. + +Dilate sets pixels in the output if any part of the mask matches, whereas +erode sets pixels only if all the mask matches. + +See [method@Image.andimage], [method@Image.orimage] and +[method@Image.eorimage] for analogues of the usual set difference and set +union operations. + +Use [ctor@Image.new_matrixv] to create a mask in source, +[ctor@Image.matrixload] to load a mask from a simple text file, and +[ctor@Image.mask_ideal] and friends to create square, circular and ring +masks of specific sizes. + +## Functions + +* [method@Image.morph] +* [method@Image.rank] +* [method@Image.median] +* [method@Image.countlines] +* [method@Image.labelregions] +* [method@Image.fill_nearest] + +## Enumerations + +* [enum@OperationMorphology] diff --git a/doc/libvips-mosaicing.md b/doc/libvips-mosaicing.md new file mode 100644 index 0000000000..89a98632aa --- /dev/null +++ b/doc/libvips-mosaicing.md @@ -0,0 +1,39 @@ +Title: Operator index > By section > Mosaicing + + + +These functions are useful for joining many small images together to make one +large image. They can cope with unstable contrast and arbitrary sub-image +layout, but will not do any geometric correction. Geometric errors should be +removed before using these functions. + +The mosaicing functions can be grouped into layers: + +The lowest level operation is [method@Image.merge] which joins two images +together left-right or up-down with a smooth seam. + +Next, [method@Image.mosaic] uses search functions plus the two low-level merge +operations to join two images given just an approximate overlap as a start +point. + +[method@Image.mosaic1] is a first-order analogue of the basic mosaic +functions: it takes two approximate tie-points and uses them to rotate and +scale the right-hand or bottom image before starting to join. + +Finally, [method@Image.globalbalance] can be used to remove contrast +differences in a mosaic which has been assembled with these functions. It +takes the mosaic apart, measures image contrast differences along the seams, +finds a set of correction factors which will minimise these differences, and +reassembles the mosaic. [method@Image.remosaic] uses the same techniques, but +will reassemble the image from a different set of source images. + +## Functions + +* [method@Image.merge] +* [method@Image.mosaic] +* [method@Image.mosaic1] +* [method@Image.match] +* [method@Image.globalbalance] +* [method@Image.remosaic] +* [method@Image.matrixinvert] +* [method@Image.matrixmultiply] diff --git a/doc/libvips-resample.md b/doc/libvips-resample.md new file mode 100644 index 0000000000..d3cd480ab6 --- /dev/null +++ b/doc/libvips-resample.md @@ -0,0 +1,80 @@ +Title: Operator index > By section > Resample + + + +These operations build on each other in a set of layers. + +First, [method@Image.affine] applies an affine transform to an image. This +is any sort of 2D transform which preserves straight lines; so any combination +of stretch, sheer, rotate and translate. You supply an interpolator for it to +use to generate pixels, see [ctor@Interpolate.new]. It will not produce good +results for very large shrinks: you'll see aliasing. + +[method@Image.reduce] is like [method@Image.affine], but it can only shrink +images, it can't enlarge, rotate, or skew. It's very fast and uses an adaptive +kernel for interpolation. + +[method@Image.shrink] is a fast block shrinker. It can quickly reduce images +by large integer factors. It will give poor results for small size reductions: +again, you'll see aliasing. + +Next, [method@Image.resize] specialises in the common task of image reduce and +enlarge. It strings together combinations of [method@Image.shrink], +[method@Image.reduce], [method@Image.affine] and others to implement a general, +high-quality image resizer. + +Finally, [ctor@Image.thumbnail] combines load and resize in one operation, and +adds colour management and correct handling of alpha transparency. Because +load and resize happen together, it can exploit tricks like JPEG and TIFF +shrink-on-load, giving a (potentially) huge speedup. +[method@Image.thumbnail_image] is only there for emergencies, don't use it +unless you really have to. + +As a separate thing, [method@Image.mapim] can apply arbitrary 2D image +transforms to an image. + +## Classes + +* [class@Interpolate] + +## Callbacks + +* [callback@InterpolateMethod] + +## Functions + +* [method@Image.shrink] +* [method@Image.shrinkh] +* [method@Image.shrinkv] +* [method@Image.reduce] +* [method@Image.reduceh] +* [method@Image.reducev] +* [ctor@Image.thumbnail] +* [ctor@Image.thumbnail_buffer] +* [method@Image.thumbnail_image] +* [ctor@Image.thumbnail_source] +* [method@Image.similarity] +* [method@Image.rotate] +* [method@Image.affine] +* [method@Image.resize] +* [method@Image.mapim] +* [method@Image.quadratic] +* [func@interpolate] +* [ctor@Interpolate.new] +* [func@Interpolate.bilinear_static] +* [func@Interpolate.nearest_static] +* [method@Interpolate.get_method] +* [method@Interpolate.get_window_offset] +* [method@Interpolate.get_window_size] + +## Constants + +* [const@INTERPOLATE_SCALE] +* [const@INTERPOLATE_SHIFT] +* [const@TRANSFORM_SCALE] +* [const@TRANSFORM_SHIFT] + +## Enumerations + +* [enum@Kernel] +* [enum@Size] diff --git a/doc/libvips-vips.md b/doc/libvips-vips.md new file mode 100644 index 0000000000..0cf9901a68 --- /dev/null +++ b/doc/libvips-vips.md @@ -0,0 +1,44 @@ +Title: Operator index > By section > Initialisation + + + +These functions handle the initialization, finalization, version retrieval, +and relocation for libvips. + +libvips is a relocatable package, meaning you can move the directory tree you +compiled it to at runtime and it will still be able to find all data files. +This is required for macOS and Windows, but slightly unusual in the Unix +world. See [func@init] and [func@guess_prefix]. + +## Functions + +* [func@max_coord_get] +* [func@init] +* [func@get_argv0] +* [func@get_prgname] +* [func@shutdown] +* [func@thread_shutdown] +* [func@add_option_entries] +* [func@leak_set] +* [func@block_untrusted_set] +* [func@version_string] +* [func@version] +* [func@guess_prefix] +* [func@guess_libdir] + +## Function macros + +* [func@INIT] + +## Constants + +* [const@DEFAULT_MAX_COORD] +* [const@ENABLE_DEPRECATED] +* [const@LIBRARY_AGE] +* [const@LIBRARY_CURRENT] +* [const@LIBRARY_REVISION] +* [const@MAJOR_VERSION] +* [const@MICRO_VERSION] +* [const@MINOR_VERSION] +* [const@VERSION] +* [const@VERSION_STRING] diff --git a/doc/Making-image-pyramids.md b/doc/making-image-pyramids.md similarity index 68% rename from doc/Making-image-pyramids.md rename to doc/making-image-pyramids.md index 5e423fdff6..7a0d5fc0c4 100644 --- a/doc/Making-image-pyramids.md +++ b/doc/making-image-pyramids.md @@ -1,39 +1,30 @@ - - Image pyramids - 3 - libvips - - - - Pyramids - How to use libvips to make image pyramids - - -libvips includes `vips_dzsave()`, an operation -that can build image pyramids compatible with DeepZoom, Zoomify -and Google Maps -image viewers. It's fast and can generate pyramids for large images using -only a small amount of memory. - -The TIFF writer, `vips_tiffsave()` can also build tiled pyramidal TIFF images, -but that's very simple to use. This page concentrates on the DeepZoom builder. +Title: Using > Building image pyramids + +libvips includes [method@Image.dzsave], an operation that can build image +pyramids compatible with [DeepZoom](http://en.wikipedia.org/wiki/Deep_Zoom), +Zoomify and [Google Maps](https://developers.google.com/maps) image viewers. +It's fast and can generate pyramids for large images using only a small amount +of memory. + +The TIFF writer, [method@Image.tiffsave] can also build tiled pyramidal TIFF +images, but that's very simple to use. This page concentrates on the DeepZoom +builder. Run dzsave with no arguments to see a summary: -``` +```bash $ vips dzsave save image to deepzoom file usage: - dzsave in filename + dzsave in filename [--option-name option-value ...] where: in - Image to save, input VipsImage filename - Filename to save to, input gchararray optional arguments: - basename - Base name to save to, input gchararray + imagename - Image name, input gchararray layout - Directory layout, input VipsForeignDzLayout - default: dz - allowed: dz, zoomify, google, iiif, iiif3 + default enum: dz + allowed enums: dz, zoomify, google, iiif, iiif3 suffix - Filename suffix for tiles, input gchararray overlap - Tile overlap in pixels, input gint default: 1 @@ -44,30 +35,38 @@ optional arguments: centre - Center image in tile, input gboolean default: false depth - Pyramid depth, input VipsForeignDzDepth - default: onepixel - allowed: onepixel, onetile, one + default enum: onepixel + allowed enums: onepixel, onetile, one angle - Rotate image during save, input VipsAngle - default: d0 - allowed: d0, d90, d180, d270 + default enum: d0 + allowed enums: d0, d90, d180, d270 container - Pyramid container type, input VipsForeignDzContainer - default: fs - allowed: fs, zip - properties - Write a properties file to the output directory, input -gboolean - default: false + default enum: fs + allowed enums: fs, zip, szi compression - ZIP deflate compression level, input gint default: 0 min: -1, max: 9 - strip - Strip all metadata from image, input gboolean - default: false + region-shrink - Method to shrink regions, input VipsRegionShrink + default enum: mean + allowed enums: mean, median, mode, max, min, nearest + skip-blanks - Skip tiles which are nearly equal to the background, input gint + default: -1 + min: -1, max: 65535 + id - Resource ID, input gchararray + Q - Q factor, input gint + default: 75 + min: 1, max: 100 + keep - Which metadata to retain, input VipsForeignKeep + default flags: exif:xmp:iptc:icc:other:all + allowed flags: none, exif, xmp, iptc, icc, other, all background - Background value, input VipsArrayDouble -operation flags: sequential nocache +operation flags: sequential nocache ``` -You can also call `vips_dzsave()` from any language with a libvips binding, or -by using `.dz` or `.szi` as an output file suffix. +You can also call [method@Image.dzsave] from any language with a libvips +binding, or by using `.dz` or `.szi` as an output file suffix. -# Writing DeepZoom pyramids +## Writing DeepZoom pyramids The `--layout` option sets the basic mode of operation. With no `--layout`, dzsave writes DeepZoom pyramids. For example: @@ -78,7 +77,7 @@ $ vips dzsave huge.tif mydz This will create a directory called `mydz_files` containing the image tiles, and write a file called `mydz.dzi` containing the image -metadata.  +metadata. You can use the `--suffix` option to control how tiles are written. For example: @@ -88,10 +87,10 @@ $ vips dzsave huge.tif mydz --suffix .jpg[Q=90] ``` will write JPEG tiles with the quality factor set to 90. You can set any -format write options you like, see the API docs for `vips_jpegsave()` +format write options you like, see the API docs for [method@Image.jpegsave] for details. -# Writing Zoomify pyramids +## Writing Zoomify pyramids Use `--layout zoomify` to put dzsave into zoomify mode. For example: @@ -105,11 +104,10 @@ directories called `TileGroupn`, each containing 256 image tiles. As with DeepZoom, you can use `--suffix` to set jpeg quality. -# Writing Google Maps pyramids +## Writing Google Maps pyramids Use `--layout google` to write Google maps-style pyramids. These are -compatible with Leaflet. For -example: +compatible with [Leaflet](http://leafletjs.com). For example: ```bash $ vips dzsave wtc.tif gmapdir --layout google @@ -136,7 +134,7 @@ For example: $ vips dzsave wtc.tif gmapdir --layout google --background 0 --centre ``` -# Other options +## Other options You can use `--tile-size` and `--overlap` to control how large the tiles are and how they overlap (obviously). They default to the correct values @@ -164,11 +162,11 @@ $ vips dzsave wtc.tif mypyr.zip to write a zipfile containing the tiles. You can use `.szi` as a suffix to enable zip output as well. -# Preprocessing images +## Preprocessing images You can use `.dz` as a filename suffix, meaning send the image to -`vips_dzsave()`. This means you can write the output of any vips operation to a -pyramid. For example: +[method@Image.dzsave]. This means you can write the output of any libvips +operation to a pyramid. For example: ```bash $ vips extract_area huge.svs mypy.dz[layout=google] 100 100 10000 10000 @@ -189,10 +187,8 @@ $ vips dzsave CMU-1.mrxs[level=1] x Will pull out level 1 (the half-resolution level of an MRXS slide) and make a pyramid from that. -# Troubleshooting +## Troubleshooting -If you are building vips from source you do need to check the summary at +If you are building libvips from source you do need to check the summary at the end of configure carefully. You must have the `libarchive-dev` package -for `vips_dzsave()` to work. - - +for [method@Image.dzsave] to work. diff --git a/doc/meson.build b/doc/meson.build index dc963813ad..98ee454e63 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -1,158 +1,112 @@ -private_libvips_headers = [ - 'arithmetic/binary.h', - 'arithmetic/hough.h', - 'arithmetic/nary.h', - 'arithmetic/parithmetic.h', - 'arithmetic/statistic.h', - 'arithmetic/unaryconst.h', - 'arithmetic/unary.h', - 'colour/pcolour.h', - 'colour/profiles.h', - 'conversion/bandary.h', - 'conversion/pconversion.h', - 'convolution/correlation.h', - 'convolution/pconvolution.h', - 'create/pcreate.h', - 'create/pmask.h', - 'create/point.h', - 'draw/drawink.h', - 'draw/pdraw.h', - 'foreign/dbh.h', - 'foreign/jpeg.h', - 'foreign/libnsgif/lzw.h', - 'foreign/libnsgif/nsgif.h', - 'foreign/libnsgif/test/cli.h', - 'foreign/magick.h', - 'foreign/pforeign.h', - 'foreign/quantise.h', - 'foreign/tiff.h', - 'freqfilt/pfreqfilt.h', - 'histogram/hist_unary.h', - 'histogram/phistogram.h', - 'include/vips/almostdeprecated.h', - 'include/vips/deprecated.h', - 'include/vips/dispatch.h', - 'include/vips/format.h', - 'include/vips/internal.h', - 'include/vips/intl.h', - 'include/vips/mask.h', - 'include/vips/private.h', - 'include/vips/thread.h', - 'include/vips/video.h', - 'include/vips/vips7compat.h', - 'iofuncs/sink.h', - 'morphology/pmorphology.h', - 'mosaicing/global_balance.h', - 'mosaicing/pmosaicing.h', - 'resample/presample.h', - 'resample/templates.h', -] +gidocgen = find_program('gi-docgen') -private_headers = [] -foreach private_libvips_header : private_libvips_headers - private_headers += [project_source_root / 'libvips' / private_libvips_header] -endforeach +if not enable_introspection + error('API reference requires introspection.') +endif + +docs_dir = get_option('prefix') / get_option('datadir') / 'doc' -markdown_content_files = files( - 'binding.md', - 'Cite.md', - 'Developer-checklist.md', - 'Examples.md', - 'How-it-opens-files.md', - 'How-it-works.md', - 'libvips-from-C++.md', - 'Making-image-pyramids.md', - 'Using-vipsthumbnail.md', +vips_content_files = files( + 'binding.md', + 'cite.md', + 'developer-checklist.md', + 'examples.md', + 'extending.md', + 'file-format.md', + 'function-list.md', + 'how-it-opens-files.md', + 'how-it-works.md', + 'making-image-pyramids.md', + 'multipage-and-animated-images.md', + 'using-from-c.md', + 'using-from-cplusplus.md', + 'using-the-cli.md', + 'using-threads.md', + 'using-vipsthumbnail.md', ) -pandoc = find_program('pandoc', required: false) +vips_section_files = files( + 'libvips-arithmetic.md', + 'libvips-basic.md', + 'libvips-colour.md', + 'libvips-conversion.md', + 'libvips-convolution.md', + 'libvips-create.md', + 'libvips-draw.md', + 'libvips-error.md', + 'libvips-freqfilt.md', + 'libvips-generate.md', + 'libvips-header.md', + 'libvips-histogram.md', + 'libvips-memory.md', + 'libvips-morphology.md', + 'libvips-mosaicing.md', + 'libvips-resample.md', + 'libvips-vips.md', +) -if pandoc.found() - # we have some files in markdown ... convert to docbook for gtk-doc - gen = generator(pandoc, - output: '@BASENAME@.xml', - arguments: [ - '@INPUT@', - '--template=@0@'.format(meson.current_source_dir() / 'pandoc-docbook-template.docbook'), - '--wrap=none', - '-V', 'title=@BASENAME@', - '-f', 'markdown+smart', - '-t', 'docbook', - '-o', '@OUTPUT@', - ] - ) +vips_include_dir = meson.current_build_dir() / 'libvips' / 'include' +doc_conf = configuration_data() +doc_conf.set('VIPS_VERSION', '@0@.@1@'.format(version_major, version_minor)) - markdown_content_files_generated = gen.process(markdown_content_files) +vips_toml = configure_file( + input: 'vips.toml.in', + output: 'vips.toml', + configuration: doc_conf, + install: true, + install_dir: docs_dir / 'vips', +) - # pandoc makes section headers, we want refsect3 for gtk-doc - markdown_content_files_docbook = custom_target('gen-docs', - output: 'generated', - input: markdown_content_files_generated, - command: [ 'sed', '-i', '-e', 's| Multipage and animated images + +libvips represents animated and multipage images as tall, thin strips of +frames, like a strip of movie film (or a roll of toilet paper). Special image +metadata items are used to hold the page height, the number of frames, and any +frame delay or loop settings. + +At least the JXL, GIF and WebP loaders and savers support animation, +and the TIFF, PDF, HEIC, AVIF and VIPS loaders and savers support multipage. + +## Reading multipage images + +For example, at the command-line, try: + +```bash +$ vipsheader -a silver-gear-cogs-animation-5.gif[n=-1] +silver-gear-cogs-animation-5.gif: 281x2560 uchar, 4 bands, srgb, gifload +width: 281 +height: 2560 +bands: 4 +format: uchar +coding: none +interpretation: srgb +xoffset: 0 +yoffset: 0 +xres: 1 +yres: 1 +filename: silver-gear-cogs-animation-5.gif +vips-loader: gifload +page-height: 320 +n-pages: 8 +loop: 0 +delay: 100 100 100 100 100 100 100 100 +background: 0 0 0 +gif-palette: -12500671 -11447983 -723724 -3289651 -11974327 -11711155 -5395027 -13027015 -9276814 -9408400 -16777216 -14079703 -197380 -12237499 -5723992 -526345 -15592942 -12763843 -5921371 -13750738 -13553359 -10592674 -6908266 -7829368 -7960954 -8158333 -809254 +bits-per-sample: 7 +palette: 1 +``` + +Points to note: + +- By default, libvips will just read the first page from an animated or + multipage image. You pass `[n=-1]` to the loader to get all pages (or + frames) in the animation. You can pick out a single page or range of + pages with perhaps `[page=4]` and `[page=2,n=2]`. + +- `page-height` is the vertical size of each frame within the overall image + (2560 pixels high in this case). + +- `n-pages` is the number of pages (or frames) in this animation. Obviously + `n-pages * frame-height == height`, or in this case 320 * 8 == 2560. + +- `loop` is the number of times the animation should loop before stopping. + Zero means "never stop looping". + +- `delay` is an optional array with a time in milliseconds which each frame + should display for. + +You'll see a similar set of metadata for a multipage image, such as a PDF: + +```bash +$ vipsheader -a nipguide.pdf[n=-1] +nipguide.pdf: 595x48836 uchar, 4 bands, srgb, pdfload +width: 595 +height: 48836 +bands: 4 +format: uchar +coding: none +interpretation: srgb +xoffset: 0 +yoffset: 0 +xres: 2.83465 +yres: 2.83465 +filename: nipguide.pdf +vips-loader: pdfload +page-height: 842 +pdf-n_pages: 58 +n-pages: 58 +pdf-creator: TeX +pdf-producer: pdfTeX-1.40.16 +``` + +Now there's no `loop` or `delay` since this is not animated, but `n-pages` and +`page-height` are set. In just the same way, you can load all pages, a single +page or a range of pages. + +This all assumes that every page (or frame) has the same dimensions. If +they don't (this can commonly happen with PDF and TIFF), you have to read +pages one by one. + +## Writing multipage images + +As long as these various pieces of metadata are set, you can write animated +and multipage images in the obvious way. For example: + +```bash +$ vips copy nipguide.pdf[n=-1] x.gif +``` + +This will take the 58-page PDF and render a 58-frame animation. This only +works because this specific PDF has pages which are all the same size -- +PDFs with (for example) a mix of portrait and landscape pages can't be +handled like this. + +More usefully, you could convert a GIF to WebP with: + +```bash +$ vips copy silver-gear-cogs-animation-5.gif[n=-1] silver.webp +``` + +To write an animated or multipage image programmatically, you need to +construct the tall, thin image and set the metadata. For example: + +```bash +$ vips arrayjoin "k2.jpg k4a.png" x.tif[page-height=2048] --across=1 +``` + +Provided that the images are both 2048 pixels high, this will write a +two-page TIFF. + +In Python you could write something like: + +```python +#!/usr/bin/env python3 + +import sys +import pyvips + +# the input images -- assume these are all the same size +images = [pyvips.Image.new_from_file(filename, access="sequential") + for filename in sys.argv[2:]] + +# frame delays are in milliseconds +delay_array = [300] * len(images) + +animation = pyvips.Image.arrayjoin(images, across=1).copy() +animation.set_type(pyvips.GValue.gint_type, "loop", 10) +animation.set_type(pyvips.GValue.gint_type, "n-pages", len(images)) +animation.set_type(pyvips.GValue.gint_type, "page-height", images[0].height) +animation.set_type(pyvips.GValue.array_int_type, "delay", delay_array) +print(f"writing {sys.argv[1]} ...") +animation.write_to_file(sys.argv[1]) +``` + +It's a little more fiddly in C: + +```c +/* compile with + * + * gcc -g -Wall assemble-animated.c `pkg-config vips --cflags --libs` + */ + +#include +#include + +/* for libvips before 8.16, add this line: + * G_DEFINE_AUTOPTR_CLEANUP_FUNC(VipsImage, g_object_unref) + */ + +int +main(int argc, char *argv[]) +{ + if (VIPS_INIT(argv[0])) + vips_error_exit(NULL); + if (argc < 3) + vips_error_exit("usage: %s outfile infile1 infile2 ...", argv[0]); + + /* Load a set of input files. + */ + g_autoptr(GPtrArray) frames = g_ptr_array_new_full(argc, g_object_unref); + for (int i = 2; i < argc; i++) { + VipsImage *frame; + if (!(frame = vips_image_new_from_file(argv[i], + "access", VIPS_ACCESS_SEQUENTIAL, + NULL))) + vips_error_exit(NULL); + + g_ptr_array_add(frames, frame); + } + + /* Combine to form a vertical strip. + */ + g_autoptr(VipsImage) strip; + if (vips_arrayjoin((VipsImage **) frames->pdata, &strip, frames->len, + "across", 1, + NULL)) + vips_error_exit(NULL); + + /* Set the animation metadata. Delay times are in milliseconds. + */ + VipsImage *frame0 = VIPS_IMAGE(frames->pdata[0]); + vips_image_set_int(strip, "page-height", frame0->Ysize); + vips_image_set_int(strip, "loop", 10); + int delays[] = { 300, 300, 300 }; + vips_image_set_array_int(strip, "delay", delays, VIPS_NUMBER(delays)); + + if (vips_image_write_to_file(strip, argv[1], NULL)) + vips_error_exit(NULL); + + return 0; +} +``` diff --git a/doc/pandoc-docbook-template.docbook b/doc/pandoc-docbook-template.docbook deleted file mode 100644 index ef420a8d72..0000000000 --- a/doc/pandoc-docbook-template.docbook +++ /dev/null @@ -1,21 +0,0 @@ - -$if(mathml)$ - -$else$ - -$endif$ - - -$for(include-before)$ -$include-before$ -$endfor$ - -$body$ - -$for(include-after)$ -$include-after$ -$endfor$ - - diff --git a/doc/rename.sed b/doc/rename.sed new file mode 100644 index 0000000000..662542b523 --- /dev/null +++ b/doc/rename.sed @@ -0,0 +1,538 @@ +s/vips_\(amiMSBfirst\)/apple_\1_apple/g +s/vips_\(error_freeze\)/apple_\1_apple/g +s/vips_\(error_thaw\)/apple_\1_apple/g +s/vips_\(error_buffer\)/apple_\1_apple/g +s/vips_\(error_clear\)/apple_\1_apple/g +s/vips_\(_make_blend_luts\)/apple_\1_apple/g +s/vips_\(clinear\)/apple_\1_apple/g +s/vips_\(image_new\)/apple_\1_apple/g +s/vips_\(target_new_to_memory\)/apple_\1_apple/g +s/vips_\(vector_isenabled\)/apple_\1_apple/g +s/vips_\(vector_set_enabled\)/apple_\1_apple/g +s/vips_\(.*\)_get_type/apple_\1_get_type_apple/g + +s/See also: \([^.]\)/::: seealso\n * \1/g + +s/#VipsImage::\(width\)/[property@Image:\1]/g +s/#VipsImage::\(height\)/[property@Image:\1]/g +s/#VipsImage::\(format\)/[property@Image:\1]/g +s/#VipsImage::\(interpretation\)/[property@Image:\1]/g + +s/#VipsImage::\([^ ,.]*\)/[signal@Image::\1]/g +s/#VipsObject::\([^ ,.]*\)/[signal@Object::\1]/g + +s/vips_foreign_\([^(]*\)()/[func@Foreign.\1]/g + +s/VIPS_INIT()/[func@INIT]/g +s/VIPS_IMAGE_\([^(]*\)()/[func@IMAGE_\1]/g +s/VIPS_REGION\([^(]*\)()/[func@REGION\1]/g +s/VIPS_MATRIX\([^(]*\)()/[func@MATRIX]/g +s/VIPS_BUF_\([^(]*\)()/[func@BUF_\1]/g +s/VIPS_SBUF_\([^(]*\)()/[func@SBUF_\1]/g + +s/vips_image_\(pipeline_array\)()/[func@Image.\1]/g + +s/vips_operation_\([^(]*\)()/[method@Operation.\1]/g +s/vips_connnection_\([^(]*\)()/[method@Connection.\1]/g +s/vips_source_custom\([^(]*\)()/[method@SourceCustom.\1]/g +s/vips_source_\([^(]*\)()/[method@Source.\1]/g +s/vips_target_custom_\([^(]*\)()/[method@TargetCustom.\1]/g +s/vips_target_\([^(]*\)()/[method@Target.\1]/g +s/vips_object_\([^(]*\)()/[method@Object.\1]/g +s/vips_\([^_]*\)_new()/[ctor@\u\1.new]/g +s/vips_image_\(new_[^(]*\)()/[ctor@Image.\1]/g +s/vips_image_\(generate\)()/[method@Image.generate]/g +s/vips_image_\([^(]*\)()/[method@Image.\1]/g +s/vips_region_\([^(]*\)()/[method@Region.\1]/g +s/vips_buf_\([^(]*\)()/[method@Buf.\1]/g +s/vips_sbuf_\([^(]*\)()/[method@Sbuf.\1]/g +s/vips_dbuf_\([^(]*\)()/[method@Dbuf.\1]/g +s/vips_\(reorder_[^(]*\)()/[method@Image.\1]/g + +s/vips_area_\(new\)()/[ctor@Area.\1]/g +s/vips_area_\(new_[^(]*\)()/[ctor@Area.\1]/g +s/vips_area_\([^(]*\)()/[method@Area.\1]/g + +s/vips_array_double_\(new[^(]*\)()/[ctor@ArrayDouble.\1]/g +s/vips_array_double_\([^(]*\)()/[method@ArrayDouble.\1]/g + +s/vips_array_int_\(new[^(]*\)()/[ctor@ArrayInt.\1]/g +s/vips_array_int_\([^(]*\)()/[method@ArrayInt.\1]/g + +s/vips_array_image_\(new[^(]*\)()/[ctor@ArrayImage.\1]/g +s/vips_array_image_empty()/[ctor@ArrayImage.empty]/g +s/vips_array_image_\([^(]*\)()/[method@ArrayImage.\1]/g + +s/vips_\(abs\)()/[method@Image.\1]/g +s/vips_\(acosh\)()/[method@Image.\1]/g +s/vips_\(acos\)()/[method@Image.\1]/g +s/vips_\(addalpha\)()/[method@Image.\1]/g +s/vips_\(add\)()/[method@Image.\1]/g +s/vips_\(affine\)()/[method@Image.\1]/g +s/vips_\(andimage_const1\)()/[method@Image.\1]/g +s/vips_\(andimage_const\)()/[method@Image.\1]/g +s/vips_\(andimage\)()/[method@Image.\1]/g +s/vips_\(asinh\)()/[method@Image.\1]/g +s/vips_\(asin\)()/[method@Image.\1]/g +s/vips_\(atan2\)()/[method@Image.\1]/g +s/vips_\(atanh\)()/[method@Image.\1]/g +s/vips_\(atan\)()/[method@Image.\1]/g +s/vips_\(autorot\)()/[method@Image.\1]/g +s/vips_\(avg\)()/[method@Image.\1]/g +s/vips_\(bandand\)()/[method@Image.\1]/g +s/vips_\(bandbool\)()/[method@Image.\1]/g +s/vips_\(bandeor\)()/[method@Image.\1]/g +s/vips_\(bandfold\)()/[method@Image.\1]/g +s/vips_\(bandjoin2\)()/[method@Image.\1]/g +s/vips_\(bandjoin_const1\)()/[method@Image.\1]/g +s/vips_\(bandjoin_const\)()/[method@Image.\1]/g +s/vips_\(bandjoin\)()/[func@Image.\1]/g +s/vips_\(bandmean\)()/[method@Image.\1]/g +s/vips_\(bandor\)()/[method@Image.\1]/g +s/vips_\(bandunfold\)()/[method@Image.\1]/g +s/vips_\(black\)()/[ctor@Image.\1]/g +s/vips_\(boolean_const1\)()/[method@Image.\1]/g +s/vips_\(boolean_const\)()/[method@Image.\1]/g +s/vips_\(boolean\)()/[method@Image.\1]/g +s/vips_\(buildlut\)()/[method@Image.\1]/g +s/vips_\(byteswap\)()/[method@Image.\1]/g +s/vips_\(cache\)()/[method@Image.\1]/g +s/vips_\(canny\)()/[method@Image.\1]/g +s/vips_\(case\)()/[method@Image.\1]/g +s/vips_\(cast_char\)()/[method@Image.\1]/g +s/vips_\(cast_complex\)()/[method@Image.\1]/g +s/vips_\(cast_double\)()/[method@Image.\1]/g +s/vips_\(cast_dpcomplex\)()/[method@Image.\1]/g +s/vips_\(cast_float\)()/[method@Image.\1]/g +s/vips_\(cast_int\)()/[method@Image.\1]/g +s/vips_\(cast\)()/[method@Image.\1]/g +s/vips_\(cast_short\)()/[method@Image.\1]/g +s/vips_\(cast_uchar\)()/[method@Image.\1]/g +s/vips_\(cast_uint\)()/[method@Image.\1]/g +s/vips_\(cast_ushort\)()/[method@Image.\1]/g +s/vips_\(ceil\)()/[method@Image.\1]/g +s/vips_\(clamp\)()/[method@Image.\1]/g +s/vips_\(CMC2LCh\)()/[method@Image.\1]/g +s/vips_\(CMYK2XYZ\)()/[method@Image.\1]/g +s/vips_\(colourspace_issupported\)()/[method@Image.\1]/g +s/vips_\(colourspace\)()/[method@Image.\1]/g +s/vips_\(compass\)()/[method@Image.\1]/g +s/vips_\(complex2\)()/[method@Image.\1]/g +s/vips_\(complexform\)()/[method@Image.\1]/g +s/vips_\(complexget\)()/[method@Image.\1]/g +s/vips_\(complex\)()/[method@Image.\1]/g +s/vips_\(composite2\)()/[method@Image.\1]/g +s/vips_\(conj\)()/[method@Image.\1]/g +s/vips_\(conva\)()/[method@Image.\1]/g +s/vips_\(convasep\)()/[method@Image.\1]/g +s/vips_\(conversion\)()/[func@Image.\1]/g +s/vips_\(convf\)()/[method@Image.\1]/g +s/vips_\(convi\)()/[method@Image.\1]/g +s/vips_\(conv\)()/[method@Image.\1]/g +s/vips_\(convsep\)()/[method@Image.\1]/g +s/vips_\(copy\)()/[method@Image.\1]/g +s/vips_\(cosh\)()/[method@Image.\1]/g +s/vips_\(cos\)()/[method@Image.\1]/g +s/vips_\(countlines\)()/[method@Image.\1]/g +s/vips_\(crop\)()/[method@Image.\1]/g +s/vips_\(cross_phase\)()/[method@Image.\1]/g +s/vips_\(csvsave\)()/[method@Image.\1]/g +s/vips_\(csvsave_target\)()/[method@Image.\1]/g +s/vips_\(dE00\)()/[method@Image.\1]/g +s/vips_\(dE76\)()/[method@Image.\1]/g +s/vips_\(dECMC\)()/[method@Image.\1]/g +s/vips_\(deviate\)()/[method@Image.\1]/g +s/vips_\(divide\)()/[method@Image.\1]/g +s/vips_\(draw_circle1\)()/[method@Image.\1]/g +s/vips_\(draw_circle\)()/[method@Image.\1]/g +s/vips_\(draw_flood1\)()/[method@Image.\1]/g +s/vips_\(draw_flood\)()/[method@Image.\1]/g +s/vips_\(draw_image\)()/[method@Image.\1]/g +s/vips_\(draw_line1\)()/[method@Image.\1]/g +s/vips_\(draw_line\)()/[method@Image.\1]/g +s/vips_\(draw_mask1\)()/[method@Image.\1]/g +s/vips_\(draw_mask\)()/[method@Image.\1]/g +s/vips_\(draw_point1\)()/[method@Image.\1]/g +s/vips_\(draw_point\)()/[method@Image.\1]/g +s/vips_\(draw_rect1\)()/[method@Image.\1]/g +s/vips_\(draw_rect\)()/[method@Image.\1]/g +s/vips_\(draw_smudge\)()/[method@Image.\1]/g +s/vips_\(dzsave_buffer\)()/[method@Image.\1]/g +s/vips_\(dzsave\)()/[method@Image.\1]/g +s/vips_\(dzsave_target\)()/[method@Image.\1]/g +s/vips_\(embed\)()/[method@Image.\1]/g +s/vips_\(eorimage_const1\)()/[method@Image.\1]/g +s/vips_\(eorimage_const\)()/[method@Image.\1]/g +s/vips_\(eorimage\)()/[method@Image.\1]/g +s/vips_\(equal_const1\)()/[method@Image.\1]/g +s/vips_\(equal_const\)()/[method@Image.\1]/g +s/vips_\(equal\)()/[method@Image.\1]/g +s/vips_\(exp10\)()/[method@Image.\1]/g +s/vips_\(exp\)()/[method@Image.\1]/g +s/vips_\(extract_area\)()/[method@Image.\1]/g +s/vips_\(extract_band\)()/[method@Image.\1]/g +s/vips_\(eye\)()/[ctor@Image.\1]/g +s/vips_\(falsecolour\)()/[method@Image.\1]/g +s/vips_\(fastcor\)()/[method@Image.\1]/g +s/vips_\(fill_nearest\)()/[method@Image.\1]/g +s/vips_\(find_trim\)()/[method@Image.\1]/g +s/vips_\(vipsload\)()/[ctor@Image.\1]/g +s/vips_\(radload\)()/[ctor@Image.\1]/g +s/vips_\(fitsload\)()/[ctor@Image.\1]/g +s/vips_\(fitsload_source\)()/[ctor@Image.\1]/g +s/vips_\(fitssave\)()/[method@Image.\1]/g +s/vips_\(flatten\)()/[method@Image.\1]/g +s/vips_\(flip\)()/[method@Image.\1]/g +s/vips_\(float2rad\)()/[method@Image.\1]/g +s/vips_\(floor\)()/[method@Image.\1]/g +s/vips_\(fractsurf\)()/[ctor@Image.\1]/g +s/vips_\(freqmult\)()/[method@Image.\1]/g +s/vips_\(fwfft\)()/[method@Image.\1]/g +s/vips_\(gamma\)()/[method@Image.\1]/g +s/vips_\(gaussblur\)()/[method@Image.\1]/g +s/vips_\(gaussmat\)()/[ctor@Image.\1]/g +s/vips_\(gaussnoise\)()/[ctor@Image.\1]/g +s/vips_\(getpoint\)()/[method@Image.\1]/g +s/vips_\(get_tile_size\)()/[method@Image.\1]/g +s/vips_\(gifsave_buffer\)()/[method@Image.\1]/g +s/vips_\(gifsave\)()/[method@Image.\1]/g +s/vips_\(gifsave_target\)()/[method@Image.\1]/g +s/vips_\(globalbalance\)()/[method@Image.\1]/g +s/vips_\(gravity\)()/[method@Image.\1]/g +s/vips_\(grey\)()/[ctor@Image.\1]/g +s/vips_\(grid\)()/[method@Image.\1]/g +s/vips_\(heifsave_buffer\)()/[method@Image.\1]/g +s/vips_\(heifsave\)()/[method@Image.\1]/g +s/vips_\(heifsave_target\)()/[method@Image.\1]/g +s/vips_\(hist_cum\)()/[method@Image.\1]/g +s/vips_\(hist_entropy\)()/[method@Image.\1]/g +s/vips_\(hist_equal\)()/[method@Image.\1]/g +s/vips_\(hist_find_indexed\)()/[method@Image.\1]/g +s/vips_\(hist_find\)()/[method@Image.\1]/g +s/vips_\(hist_find_ndim\)()/[method@Image.\1]/g +s/vips_\(hist_ismonotonic\)()/[method@Image.\1]/g +s/vips_\(hist_local\)()/[method@Image.\1]/g +s/vips_\(hist_match\)()/[method@Image.\1]/g +s/vips_\(hist_norm\)()/[method@Image.\1]/g +s/vips_\(hist_plot\)()/[method@Image.\1]/g +s/vips_\(hough_circle\)()/[method@Image.\1]/g +s/vips_\(hough_line\)()/[method@Image.\1]/g +s/vips_\(HSV2sRGB\)()/[method@Image.\1]/g +s/vips_\(icc_export\)()/[method@Image.\1]/g +s/vips_\(icc_import\)()/[method@Image.\1]/g +s/vips_\(icc_transform\)()/[method@Image.\1]/g +s/vips_\(identity\)()/[ctor@Image.\1]/g +s/vips_\(ifthenelse\)()/[method@Image.\1]/g +s/vips_image_\(get_typeof\)()/[method@Image.\1]/g +s/vips_\(imag\)()/[method@Image.\1]/g +s/vips_\(insert\)()/[method@Image.\1]/g +s/vips_\(invertlut\)()/[method@Image.\1]/g +s/vips_\(invert\)()/[method@Image.\1]/g +s/vips_\(invfft\)()/[method@Image.\1]/g +s/vips_\(join\)()/[method@Image.\1]/g +s/vips_\(jp2ksave_buffer\)()/[method@Image.\1]/g +s/vips_\(jp2ksave\)()/[method@Image.\1]/g +s/vips_\(jp2ksave_target\)()/[method@Image.\1]/g +s/vips_\(jpegsave_buffer\)()/[method@Image.\1]/g +s/vips_\(jpegsave\)()/[method@Image.\1]/g +s/vips_\(jpegsave_mime\)()/[method@Image.\1]/g +s/vips_\(jpegsave_target\)()/[method@Image.\1]/g +s/vips_\(jxlload\)()/[ctor@Image.\1]/g +s/vips_\(jxlsave_buffer\)()/[method@Image.\1]/g +s/vips_\(jxlsave\)()/[method@Image.\1]/g +s/vips_\(jxlsave_target\)()/[method@Image.\1]/g +s/vips_\(Lab2LabQ\)()/[method@Image.\1]/g +s/vips_\(Lab2LabS\)()/[method@Image.\1]/g +s/vips_\(Lab2LCh\)()/[method@Image.\1]/g +s/vips_\(Lab2XYZ\)()/[method@Image.\1]/g +s/vips_\(labelregions\)()/[method@Image.\1]/g +s/vips_\(LabQ2Lab\)()/[method@Image.\1]/g +s/vips_\(LabQ2LabS\)()/[method@Image.\1]/g +s/vips_\(LabQ2sRGB\)()/[method@Image.\1]/g +s/vips_\(LabS2Lab\)()/[method@Image.\1]/g +s/vips_\(LabS2LabQ\)()/[method@Image.\1]/g +s/vips_\(LCh2CMC\)()/[method@Image.\1]/g +s/vips_\(LCh2Lab\)()/[method@Image.\1]/g +s/vips_\(less_const1\)()/[method@Image.\1]/g +s/vips_\(less_const\)()/[method@Image.\1]/g +s/vips_\(lesseq_const1\)()/[method@Image.\1]/g +s/vips_\(lesseq_const\)()/[method@Image.\1]/g +s/vips_\(lesseq\)()/[method@Image.\1]/g +s/vips_\(less\)()/[method@Image.\1]/g +s/vips_\(linear1\)()/[method@Image.\1]/g +s/vips_\(linear\)()/[method@Image.\1]/g +s/vips_\(linecache\)()/[method@Image.\1]/g +s/vips_\(log10\)()/[method@Image.\1]/g +s/vips_\(logmat\)()/[ctor@Image.\1]/g +s/vips_\(log\)()/[method@Image.\1]/g +s/vips_\(lshift_const1\)()/[method@Image.\1]/g +s/vips_\(lshift_const\)()/[method@Image.\1]/g +s/vips_\(lshift\)()/[method@Image.\1]/g +s/vips_\(pngload\)()/[ctor@Image.\1]/g +s/vips_\(ppmload\)()/[ctor@Image.\1]/g +s/vips_\(openslideload\)()/[ctor@Image.\1]/g +s/vips_\(tiffload\)()/[ctor@Image.\1]/g +s/vips_\(gifload\)()/[ctor@Image.\1]/g +s/vips_\(niftiload\)()/[ctor@Image.\1]/g +s/vips_\(matrixload\)()/[ctor@Image.\1]/g +s/vips_\(svgload\)()/[ctor@Image.\1]/g +s/vips_\(magickload\)()/[ctor@Image.\1]/g +s/vips_\(magicksave_buffer\)()/[method@Image.\1]/g +s/vips_\(magicksave\)()/[method@Image.\1]/g +s/vips_\(mapim\)()/[method@Image.\1]/g +s/vips_\(maplut\)()/[method@Image.\1]/g +s/vips_\(mask_butterworth_band\)()/[ctor@Image.\1]/g +s/vips_\(mask_butterworth\)()/[ctor@Image.\1]/g +s/vips_\(mask_butterworth_ring\)()/[ctor@Image.\1]/g +s/vips_\(mask_fractal\)()/[ctor@Image.\1]/g +s/vips_\(mask_gaussian_band\)()/[ctor@Image.\1]/g +s/vips_\(mask_gaussian\)()/[ctor@Image.\1]/g +s/vips_\(mask_gaussian_ring\)()/[ctor@Image.\1]/g +s/vips_\(mask_ideal_band\)()/[ctor@Image.\1]/g +s/vips_\(mask_ideal\)()/[ctor@Image.\1]/g +s/vips_\(mask_ideal_ring\)()/[ctor@Image.\1]/g +s/vips_\(match\)()/[method@Image.\1]/g +s/vips_\(math2_const1\)()/[method@Image.\1]/g +s/vips_\(math2_const\)()/[method@Image.\1]/g +s/vips_\(math2\)()/[method@Image.\1]/g +s/vips_\(math\)()/[method@Image.\1]/g +s/vips_\(matrixinvert\)()/[method@Image.\1]/g +s/vips_\(matrixmultiply\)()/[method@Image.\1]/g +s/vips_\(matrixprint\)()/[method@Image.\1]/g +s/vips_\(matrixsave\)()/[method@Image.\1]/g +s/vips_\(matrixsave_target\)()/[method@Image.\1]/g +s/vips_\(max\)()/[method@Image.\1]/g +s/vips_\(maxpair\)()/[method@Image.\1]/g +s/vips_\(measure\)()/[method@Image.\1]/g +s/vips_\(median\)()/[method@Image.\1]/g +s/vips_\(merge\)()/[method@Image.\1]/g +s/vips_\(min\)()/[method@Image.\1]/g +s/vips_\(minpair\)()/[method@Image.\1]/g +s/vips_\(more_const1\)()/[method@Image.\1]/g +s/vips_\(more_const\)()/[method@Image.\1]/g +s/vips_\(moreeq_const1\)()/[method@Image.\1]/g +s/vips_\(moreeq_const\)()/[method@Image.\1]/g +s/vips_\(moreeq\)()/[method@Image.\1]/g +s/vips_\(more\)()/[method@Image.\1]/g +s/vips_\(morph\)()/[method@Image.\1]/g +s/vips_\(mosaic1\)()/[method@Image.\1]/g +s/vips_\(mosaic\)()/[method@Image.\1]/g +s/vips_\(msb\)()/[method@Image.\1]/g +s/vips_\(multiply\)()/[method@Image.\1]/g +s/vips_\(niftisave\)()/[method@Image.\1]/g +s/vips_\(notequal_const1\)()/[method@Image.\1]/g +s/vips_\(notequal_const\)()/[method@Image.\1]/g +s/vips_\(notequal\)()/[method@Image.\1]/g +s/vips_\(orimage_const1\)()/[method@Image.\1]/g +s/vips_\(orimage_const\)()/[method@Image.\1]/g +s/vips_\(orimage\)()/[method@Image.\1]/g +s/vips_\(percent\)()/[method@Image.\1]/g +s/vips_\(perlin\)()/[ctor@Image.\1]/g +s/vips_\(phasecor\)()/[method@Image.\1]/g +s/vips_\(pngsave_buffer\)()/[method@Image.\1]/g +s/vips_\(pngsave\)()/[method@Image.\1]/g +s/vips_\(pngsave_target\)()/[method@Image.\1]/g +s/vips_\(polar\)()/[method@Image.\1]/g +s/vips_\(pow\)()/[method@Image.\1]/g +s/vips_\(ppmsave\)()/[method@Image.\1]/g +s/vips_\(ppmsave_target\)()/[method@Image.\1]/g +s/vips_\(premultiply\)()/[method@Image.\1]/g +s/vips_\(prewitt\)()/[method@Image.\1]/g +s/vips_\(profile\)()/[method@Image.\1]/g +s/vips_\(project\)()/[method@Image.\1]/g +s/vips_\(quadratic\)()/[method@Image.\1]/g +s/vips_\(rad2float\)()/[method@Image.\1]/g +s/vips_\(radsave_buffer\)()/[method@Image.\1]/g +s/vips_\(radsave\)()/[method@Image.\1]/g +s/vips_\(radsave_target\)()/[method@Image.\1]/g +s/vips_\(rank\)()/[method@Image.\1]/g +s/vips_\(rawsave_buffer\)()/[method@Image.\1]/g +s/vips_\(rawsave_fd\)()/[method@Image.\1]/g +s/vips_\(rawsave\)()/[method@Image.\1]/g +s/vips_\(rawsave\)()/[method@Image.\1]/g +s/vips_\(rawsave_target\)()/[method@Image.\1]/g +s/vips_\(real\)()/[method@Image.\1]/g +s/vips_\(recomb\)()/[method@Image.\1]/g +s/vips_\(rect\)()/[method@Image.\1]/g +s/vips_\(reduceh\)()/[method@Image.\1]/g +s/vips_\(reduce\)()/[method@Image.\1]/g +s/vips_\(reducev\)()/[method@Image.\1]/g +s/vips_\(relational_const1\)()/[method@Image.\1]/g +s/vips_\(relational_const\)()/[method@Image.\1]/g +s/vips_\(relational\)()/[method@Image.\1]/g +s/vips_\(remainder_const1\)()/[method@Image.\1]/g +s/vips_\(remainder_const\)()/[method@Image.\1]/g +s/vips_\(remainder\)()/[method@Image.\1]/g +s/vips_\(replicate\)()/[method@Image.\1]/g +s/vips_\(resize\)()/[method@Image.\1]/g +s/vips_\(rint\)()/[method@Image.\1]/g +s/vips_\(rot45\)()/[method@Image.\1]/g +s/vips_\(rotate\)()/[method@Image.\1]/g +s/vips_\(rot\)()/[method@Image.\1]/g +s/vips_\(round\)()/[method@Image.\1]/g +s/vips_\(rshift_const1\)()/[method@Image.\1]/g +s/vips_\(rshift_const\)()/[method@Image.\1]/g +s/vips_\(rshift\)()/[method@Image.\1]/g +s/vips_\(scale\)()/[method@Image.\1]/g +s/vips_\(scharr\)()/[method@Image.\1]/g +s/vips_\(scRGB2BW\)()/[method@Image.\1]/g +s/vips_\(scRGB2sRGB\)()/[method@Image.\1]/g +s/vips_\(scRGB2XYZ\)()/[method@Image.\1]/g +s/vips_\(sdf\)()/[ctor@Image.\1]/g +s/vips_\(sequential\)()/[method@Image.\1]/g +s/vips_\(sharpen\)()/[method@Image.\1]/g +s/vips_\(shrinkh\)()/[method@Image.\1]/g +s/vips_\(shrink\)()/[method@Image.\1]/g +s/vips_\(shrinkv\)()/[method@Image.\1]/g +s/vips_\(sign\)()/[method@Image.\1]/g +s/vips_\(similarity\)()/[method@Image.\1]/g +s/vips_\(sinh\)()/[method@Image.\1]/g +s/vips_\(sink_disc\)()/[method@Image.\1]/g +s/vips_\(sink\)()/[method@Image.\1]/g +s/vips_\(sink_screen\)()/[method@Image.\1]/g +s/vips_\(sin\)()/[method@Image.\1]/g +s/vips_\(smartcrop\)()/[method@Image.\1]/g +s/vips_\(sobel\)()/[method@Image.\1]/g +s/vips_\(spcor\)()/[method@Image.\1]/g +s/vips_\(spectrum\)()/[method@Image.\1]/g +s/vips_\(sRGB2HSV\)()/[method@Image.\1]/g +s/vips_\(sRGB2scRGB\)()/[method@Image.\1]/g +s/vips_\(stats\)()/[method@Image.\1]/g +s/vips_\(stdif\)()/[method@Image.\1]/g +s/vips_\(subsample\)()/[method@Image.\1]/g +s/vips_\(subtract\)()/[method@Image.\1]/g +s/vips_\(switch\)()/[func@Image.\1]/g +s/vips_\(tanh\)()/[method@Image.\1]/g +s/vips_\(tan\)()/[method@Image.\1]/g +s/vips_\(text\)()/[ctor@Image.\1]/g +s/vips_\(thumbnail_image\)()/[method@Image.\1]/g +s/vips_\(thumbnail_buffer\)()/[ctor@Image.\1]/g +s/vips_\(thumbnail_source\)()/[ctor@Image.\1]/g +s/vips_\(thumbnail\)()/[ctor@Image.\1]/g +s/vips_\(tiffsave_buffer\)()/[method@Image.\1]/g +s/vips_\(tiffsave\)()/[method@Image.\1]/g +s/vips_\(tiffsave_target\)()/[method@Image.\1]/g +s/vips_\(tilecache\)()/[method@Image.\1]/g +s/vips_\(tonelut\)()/[ctor@Image.\1]/g +s/vips_\(transpose3d\)()/[method@Image.\1]/g +s/vips_\(unpremultiply\)()/[method@Image.\1]/g +s/vips_\(vipssave\)()/[method@Image.\1]/g +s/vips_\(vipssave_target\)()/[method@Image.\1]/g +s/vips_\(jpegload\)()/[ctor@Image.\1]/g +s/vips_\(jpegload_buffer\)()/[ctor@Image.\1]/g +s/vips_\(heifload\)()/[ctor@Image.\1]/g +s/vips_\(csvload\)()/[ctor@Image.\1]/g +s/vips_\(webpload\)()/[ctor@Image.\1]/g +s/vips_\(webpsave_buffer\)()/[method@Image.\1]/g +s/vips_\(webpsave\)()/[method@Image.\1]/g +s/vips_\(webpsave_mime\)()/[method@Image.\1]/g +s/vips_\(webpsave_target\)()/[method@Image.\1]/g +s/vips_\(wop\)()/[method@Image.\1]/g +s/vips_\(worley\)()/[ctor@Image.\1]/g +s/vips_\(wrap\)()/[method@Image.\1]/g +s/vips_\(XYZ2CMYK\)()/[method@Image.\1]/g +s/vips_\(XYZ2Lab\)()/[method@Image.\1]/g +s/vips_\(XYZ2scRGB\)()/[method@Image.\1]/g +s/vips_\(XYZ2Yxy\)()/[method@Image.\1]/g +s/vips_\(xyz\)()/[ctor@Image.\1]/g +s/vips_\(Yxy2XYZ\)()/[method@Image.\1]/g +s/vips_\(zone\)()/[ctor@Image.\1]/g +s/vips_\(zoom\)()/[method@Image.\1]/g + +s/vips_\([^(]*\)()/[func@\1]/g + +s/#Vips\(Kernel\)/[enum@\1]/g +s/#Vips\(SdfShape\)/[enum@\1]/g +s/#Vips\(CombineMode\)/[enum@\1]/g +s/#Vips\(Access\)/[enum@\1]/g +s/#Vips\(RegionShrink\)/[enum@\1]/g +s/#Vips\(BandFormat\)/[enum@\1]/g +s/#Vips\(Interpretation\)/[enum@\1]/g +s/#Vips\(Coding\)/[enum@\1]/g +s/#Vips\(DemandStyle\)/[enum@\1]/g +s/#Vips\(Precision\)/[enum@\1]/g +s/#Vips\(ArgumentFlags\)/[flags@\1]/g +s/#Vips\(ForeignPngFilter\)/[flags@\1]/g +s/#Vips\(ForeignPpmFormat\)/[enum@\1]/g +s/#Vips\(ForeignTiffCompression\)/[enum@\1]/g +s/#Vips\(ForeignTiffPredictor\)/[enum@\1]/g +s/#Vips\(ForeignTiffResUnit\)/[enum@\1]/g +s/#Vips\(ForeignDzDepth\)/[enum@\1]/g +s/#Vips\(ForeignWebpPreset\)/[enum@\1]/g + +s/#Vips\(Rect\)/[struct@\1]/g +s/#Vips\(Progress\)/[struct@\1]/g + +s/#Vips\(Image\)/[class@\1]/g +s/#Vips\(Foreign\)/[class@\1]/g +s/#Vips\(Region\)/[class@\1]/g +s/#Vips\(Object\)/[class@\1]/g +s/#Vips\(Operation\)/[class@\1]/g +s/#Vips\(ForeignLoad\)/[class@\1]/g +s/#Vips\(Connection\)/[class@\1]/g +s/#Vips\(SourceCustom\)/[class@\1]/g +s/#Vips\(Source\)/[class@\1]/g +s/#Vips\(TargetCustom\)/[class@\1]/g +s/#Vips\(Target\)/[class@\1]/g +s/#Vips\(ThreadState\)/[class@\1]/g +s/#Vips\(Buf\)/[class@\1]/g +s/#Vips\(Sbuf\)/[class@\1]/g +s/#Vips\(Dbuf\)/[class@\1]/g +s/#Vips\(Blob\)/[struct@\1]/g +s/#Vips\(Area\)/[struct@\1]/g +s/#Vips\(ArrayInt\)/[struct@\1]/g +s/#Vips\(ArrayDouble\)/[struct@\1]/g +s/#Vips\(ArrayImage\)/[struct@\1]/g +s/#Vips\(RefString\)/[struct@\1]/g +s/#Vips\(ThreadpoolAllocateFn\)/[callback@\1]/g +s/#Vips\(ThreadpoolWorkFn\)/[callback@\1]/g +s/#Vips\(ThreadpoolProgressFn\)/[callback@\1]/g + +s/#VIPS_COMBINE_MODE_\([^ ,.]*\)/[enum@Vips.CombineMode.\1]/g +s/#VIPS_SDF_SHAPE_\([^ ,.]*\)/[enum@Vips.SdfShape.\1]/g +s/#VIPS_KERNEL_\([^ ,.]*\)/[enum@Vips.Kernel.\1]/g +s/#VIPS_OPERATION_MATH_\([^ ,.]*\)/[enum@Vips.OperationMath.\1]/g +s/#VIPS_OPERATION_MATH2_\([^ ,.]*\)/[enum@Vips.OperationMath2.\1]/g +s/#VIPS_OPERATION_RELATIONAL_\([^ ,.]*\)/[enum@Vips.OperationRelational.\1]/g +s/#VIPS_OPERATION_BOOLEAN_\([^ ,.]*\)/[enum@Vips.OperationBoolean.\1]/g +s/#VIPS_OPERATION_ROUND_\([^ ,.]*\)/[enum@Vips.OperationRound.\1]/g +s/#VIPS_OPERATION_COMPLEX_\([^ ,.]*\)/[enum@Vips.OperationComplex.\1]/g +s/#VIPS_OPERATION_COMPLEX2_\([^ ,.]*\)/[enum@Vips.OperationComplex2.\1]/g +s/#VIPS_OPERATION_COMPLEXGET_\([^ ,.]*\)/[enum@Vips.OperationComplexget.\1]/g +s/#VIPS_OPERATION_MORPHOLOGY_\([^ ,.]*\)/[enum@Vips.OperationMorphology.\1]/g +s/#VIPS_OPERATION_\([^ ,.]*\)/[flags@Vips.OperationFlags.\1]/g +s/#VIPS_FORMAT_\([^ ,.]*\)/[enum@Vips.BandFormat.\1]/g +s/#VIPS_PRECISION_\([^ ,.]*\)/[enum@Vips.Precision.\1]/g +s/#VIPS_DEMAND_STYLE_\([^ ,.]*\)/[enum@Vips.DemandStyle.\1]/g +s/#VIPS_INTERPRETATION_\([^ ,.]*\)/[enum@Vips.Interpretation.\1]/g +s/#VIPS_ACCESS_\([^ ,.]*\)/[enum@Vips.Access.\1]/g +s/#VIPS_CODING_\([^ ,.]*\)/[enum@Vips.Coding.\1]/g + +s/apple_\(.*\)_apple/vips_\1/g + +s/g_\(assert_not_reached\)/banana_\1_banana/g + +s/g_thread_\([^(]*new\)()/[ctor@GLib.Thread.\1]/g +s/g_object_\(new\)()/[ctor@GObject.Object.\1]/g +s/g_object_\([^(]*\)()/[method@GObject.Object.\1]/g +s/%GValue/[struct@GObject.Value]/g +s/%GObject/[class@GObject.Object]/g +s/%GThread/[struct@GLib.Thread]/g +s/%GType/[alias@GObject.Type]/g +s/%NULL/`NULL`/g +s/%TRUE/`TRUE`/g +s/%FALSE/`FALSE`/g +s/%gint64/`gint64`/g +s/%guint64/`guint64`/g +s/%gint/`gint`/g +s/%gboolean/`gboolean`/g +s/%gdouble/`gdouble`/g +s/%gchararray/`gchararray`/g +s/%gpointer/`gpointer`/g +s/%GInputStream/[class@Gio.InputStream]/g +s/%GInput/[class@Gio.Input]/g +s/%GSList/[struct@GLib.SList]/g + +s/g_\([^(]*\)()/[func@GLib.\1]/g + +s/banana_\(.*\)_banana/g_\1/g diff --git a/doc/rename.sh b/doc/rename.sh new file mode 100755 index 0000000000..01013c9adc --- /dev/null +++ b/doc/rename.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +for filename in "$@"; do + sed -i -f rename.sed $filename +done diff --git a/doc/urlmap.js b/doc/urlmap.js new file mode 100644 index 0000000000..69c33a9199 --- /dev/null +++ b/doc/urlmap.js @@ -0,0 +1,7 @@ +// A map between namespaces and base URLs for their online documentation +baseURLs = [ + ['GLib', 'https://docs.gtk.org/glib/'], + ['Gio', 'https://docs.gtk.org/gio/'], + ['GObject', 'https://docs.gtk.org/gobject/'], + ['GModule', 'https://docs.gtk.org/gmodule/'], +] diff --git a/doc/using-C.xml b/doc/using-C.xml deleted file mode 100644 index 773ddcdaaf..0000000000 --- a/doc/using-C.xml +++ /dev/null @@ -1,371 +0,0 @@ - - - - - - VIPS from C - 3 - VIPS Library - - - - Using VIPS - How to use the VIPS library from C - - - - Codestin Search App - - VIPS comes with a convenient, high-level C API. You should read the API - docs for full details, but this section will try to give a brief - overview. - - - - - Codestin Search App - - When your program starts, use VIPS_INIT() - to start up the VIPS library. You should pass it the name - of your program, usually argv[0]. If you call - vips_shutdown() just before you exit, libvips will attempt to free all - resources. This can help leak checking, but is not required. - - - - VIPS_INIT() is a macro to let it check - that the libvips library you have linked to matches the libvips headers - you included. - - - - You can add the VIPS flags to your %GObject command-line processing - with vips_add_option_entries(). - - - - - Codestin Search App - - The basic data object is the #VipsImage. You can create an - image from a file on disc or from an area of memory, either - as a C-style array, or as a formatted object, like JPEG. See - vips_image_new_from_file() and friends. Loading an - image is fast: VIPS read just enough of the image to be able to get - the various properties, such as width, but no decoding occurs until - pixel values are really needed. - - - - Once you have an image, you can get properties from it in the usual way. - You can use projection functions, like vips_image_get_width() or - g_object_get(), to get %GObject properties. All VIPS objects are - immutable, meaning you can only get properties, you can't set them. - See VIPS Header to read about - image properties. - - - - - Codestin Search App - - VIPS is based on the %GObject library and is therefore reference counted. - vips_image_new_from_file() returns an object with a count of 1. - When you are done with an image, use g_object_unref() to dispose of it. - If you pass an image to an operation and that operation needs to keep a - copy of the image, it will ref it. So you can unref an image as soon as - you no longer need it, you don't need to hang on to it in case anyone - else is still using it. - - - - See #VipsOperation for more detail on VIPS - reference counting conventions. See the Reference pools - section below for a way to automate reference counting in C. - - - - - - Codestin Search App - - Use things like vips_embed() to manipulate your images. You use it from - C like this: - - -const char *filename; -VipsImage *in = vips_image_new_from_file(filename, NULL); -const int x = 10; -const int y = 10; -const int width = 1000; -const int height = 1000; -VipsImage *out; - -if (vips_embed(in, &out, x, y, width, height, NULL)) - error_handling(); - - - Now out will hold a reference to a 1000 by 1000 pixel - image, with in pasted 10 right and 10 down from the top - left-hand corner. The remainder of the image will be black. If - in is too large, it will be clipped at the image edges. - - - - Operations can take optional arguments. You give these as a set of - NULL-terminated name-value pairs at the end of the call. For example, - you can write: - - -if (vips_embed(in, &out, x, y, width, height, - "extend", VIPS_EXTEND_COPY, - NULL)) - error_handling(); - - - And now the new edge pixels, which were black, will be filled with a copy - of the edge pixels of in. Operation options are listed - at the top of each operation's entry in the docs. Alternatively, - the vips program is handy for getting a - summary of an operation's parameters. For example: - - -$ vips embed -embed an image in a larger image -usage: - embed in out x y width height -where: - in - Input image, input VipsImage - out - Output image, output VipsImage - x - Left edge of input in output, input gint - default: 0 - min: -1000000000, max: 1000000000 - y - Top edge of input in output, input gint - default: 0 - min: -1000000000, max: 1000000000 - width - Image width in pixels, input gint - default: 1 - min: 1, max: 1000000000 - height - Image height in pixels, input gint - default: 1 - min: 1, max: 1000000000 -optional arguments: - extend - How to generate the extra pixels, input VipsExtend - default: black - allowed: black, copy, repeat, mirror, white, background - background - Colour for background pixels, input VipsArrayDouble -operation flags: sequential-unbuffered - - - See #VipsOperation for more information on running operations on images. - - - - The API docs have a handy table of all vips - operations, if you want to find out how to do something, try - searching that. - - - - When you are done, you can write - the final image to a disc file, to a formatted memory buffer, or to - C-style memory array. See vips_image_write_to_file() and friends. - - - - - Codestin Search App - - Use #VipsRegion to read pixels out of images. You can use - VIPS_IMAGE_ADDR() as well, but this can need a large amount of - memory to work. See extending - for an introduction to writing your own operations. - - - - - Codestin Search App - - - VIPS keeps a log of error message, see VIPS Error to find out how to get and - clear the error log. - - - - - - Codestin Search App - - - On *nix systems, you can compile the example code with something like: - - -$ gcc -g -Wall myprog.c `pkg-config vips --cflags --libs` - - - On Windows, you'll need to set the compiler flags by hand, perhaps: - - -x86_64-w64-mingw32-gcc-win32 -mms-bitfields \ - -Ic:/vips-8.6/include \ - -Ic:/vips-8.6/include/glib-2.0 \ - -Ic:/vips-8.6/lib/glib-2.0/include \ - myprog.c \ - -Lc:/vips-8.6/lib \ - -lvips -lz -ljpeg -lstdc++ -lxml2 -lfftw3 -lm -lMagickWand -llcms2 \ - -lopenslide -lcfitsio -lpangoft2-1.0 -ltiff -lpng14 -lexif \ - -lMagickCore -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 \ - -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl \ - -o myprog.exe - - - - - -Codestin Search App - -#include <stdio.h> -#include <vips/vips.h> - -int -main(int argc, char **argv) -{ - VipsImage *in; - double mean; - VipsImage *out; - - if (VIPS_INIT(argv[0])) - vips_error_exit(NULL); - - if (argc != 3) - vips_error_exit("usage: %s infile outfile", argv[0]); - - if (!(in = vips_image_new_from_file(argv[1], NULL))) - vips_error_exit(NULL); - - printf("image width = %d\n", vips_image_get_width(in)); - - if (vips_avg(in, &mean, NULL)) - vips_error_exit(NULL); - - printf("mean pixel value = %g\n", mean); - - if (vips_invert(in, &out, NULL)) - vips_error_exit(NULL); - - g_object_unref(in); - - if (vips_image_write_to_file(out, argv[2], NULL)) - vips_error_exit(NULL); - - g_object_unref(out); - - return 0; -} - - - - - - - Codestin Search App - - libvips has a simple system to automate at least some reference counting - issues. Reference pools are arrays of object pointers which will be - released automatically when some other object is finalized. - - - - The code below crops a many-page image (perhaps a GIF or PDF). It - splits the image into separate pages, crops each page, reassembles the - cropped areas, and saves again. It creates a context - object representing the state of processing, and - crop_animation allocates two reference pools off that using - vips_object_local_array, one to hold the cropped frames, - and one to assemble and copy the result. - - - - All unreffing is handled by main, and it doesn't need to - know anything about crop_animation. - - - -Codestin Search App - -#include <vips/vips.h> - -static int -crop_animation(VipsObject *context, VipsImage *image, VipsImage **out, - int left, int top, int width, int height) -{ - int page_height = vips_image_get_page_height(image); - int n_pages = image->Ysize / page_height; - VipsImage **page = (VipsImage **) vips_object_local_array(context, n_pages); - VipsImage **copy = (VipsImage **) vips_object_local_array(context, 1); - - int i; - - /* Split the image into cropped frames. - */ - for (i = 0; i < n_pages; i++) - if (vips_crop(image, &page[i], - left, page_height * i + top, width, height, NULL)) - return -1; - - /* Reassemble the frames and set the page height. You must copy before - * modifying metadata. - */ - if (vips_arrayjoin(page, &copy[0], n_pages, "across", 1, NULL) || - vips_copy(copy[0], out, NULL)) - return -1; - vips_image_set_int(*out, "page-height", height); - - return 0; -} - -int -main(int argc, char **argv) -{ - VipsImage *image; - VipsObject *context; - VipsImage *x; - - if (VIPS_INIT(NULL)) - vips_error_exit(NULL); - - if (!(image = vips_image_new_from_file(argv[1], - "access", VIPS_ACCESS_SEQUENTIAL, - NULL))) - vips_error_exit(NULL); - - context = VIPS_OBJECT(vips_image_new()); - if (crop_animation(context, image, &x, 10, 10, 500, 500)) { - g_object_unref(image); - g_object_unref(context); - vips_error_exit(NULL); - } - g_object_unref(image); - g_object_unref(context); - image = x; - - if (vips_image_write_to_file(image, argv[2], NULL)) { - g_object_unref(image); - vips_error_exit(NULL); - } - - g_object_unref(image); - - return 0; -} - - - - - - diff --git a/doc/using-command-line.xml b/doc/using-command-line.xml deleted file mode 100644 index d0681de076..0000000000 --- a/doc/using-command-line.xml +++ /dev/null @@ -1,236 +0,0 @@ - - - - - - VIPS from the command-line - 1 - VIPS Library - - - - Using VIPS - How to use the VIPS library from the command-line - - - - Codestin Search App - - Use the vips command to execute VIPS operations from - the command-line. For example: - - -$ vips rot k2.jpg x.jpg d90 - - - Will rotate the image k2.jpg by 90 degrees - anticlockwise and write the result to the file x.jpg. - If you don't give any arguments to an operation, - vips will give a short description, for example: - - -$ vips rot -rotate an image -usage: - rot in out angle -where: - in - Input image, input VipsImage - out - Output image, output VipsImage - angle - Angle to rotate image, input VipsAngle - default: d90 - allowed: d0, d90, d180, d270 - - - There's a straightforward relationship with the C API: compare this to - the API docs for vips_rot(). - - - - - Codestin Search App - - You can list all classes with: - - -$ vips -l -... -VipsOperation (operation), operations - VipsSystem (system), run an external command - VipsArithmetic (arithmetic), arithmetic operations - VipsBinary (binary), binary operations - VipsAdd (add), add two images - ... etc. - - - Each line shows the canonical name of the class (for example - VipsAdd), the class nickname - (add in this case), and a short description. - Some subclasses of operation will show more: for example, subclasses of - VipsForeign will show some of the extra flags - supported by the file load/save operations. - - - - The API docs have a handy table of all vips - operations, if you want to find out how to do something, try - searching that. - - - - - Codestin Search App - - Many operations take optional arguments. You can supply these as - command-line options. For example: - - -$ vips gamma -gamma an image -usage: - gamma in out -where: - in - Input image, input VipsImage - out - Output image, output VipsImage -optional arguments: - exponent - Gamma factor, input gdouble - default: 2.4 - min: 1e-06, max: 1000 -operation flags: sequential-unbuffered - - - vips_gamma() applies a gamma factor to an image. By - default, it uses 2.4, the sRGB gamma factor, but you can specify any - gamma with the exponent option. - - - - Use it from the command-line like this: - - -$ vips gamma k2.jpg x.jpg --exponent 0.42 - - - This will read file k2.jpg, un-gamma it, and - write the result to file x.jpg. - - - - - Codestin Search App - - Some operations take arrays of values as arguments. For example, - vips_affine() needs an array of four numbers for the - 2x2 transform matrix. You pass arrays as space-separated lists: - - -$ vips affine k2.jpg x.jpg "2 0 0 1" - - - You may need the quotes to stop your shell breaking the argument at - the spaces. vips_bandjoin() needs an array of input images to - join, run it like this: - - -$ vips bandjoin "k2.jpg k4.jpg" x.tif - - - - - - Codestin Search App - - vips will automatically convert between image file - formats for you. Input images are detected by sniffing their first few - bytes; output formats are set from the filename suffix. You can see a - list of all the supported file formats with something like: - - -$ vips -l foreign - - - Then get a list of the options a format supports with: - - -$ vips jpegsave - - - - - You can pass options to the implicit load and save operations enclosed - in square brackets after the filename: - - -vips affine k2.jpg x.jpg[Q=90,strip] "2 0 0 1" - - - Will write x.jpg at quality level 90 and will - strip all metadata from the image. - - - - - Codestin Search App - - - Because each operation runs in a separate process, you can't use - libvips's chaining system to join operations together, you have to use - intermediate files. The command-line interface is therefore quite a bit - slower than Python or C. - - - - The best alternative is to use vips files for intermediates. - Something like: - - -vips invert input.jpg t1.v -vips affine t1.v output.jpg "2 0 0 1" -rm t1.v - - - - - - - Codestin Search App - - - Finally, vips has a couple of useful extra options. - - - - - Use to get - vips to display a simple progress indicator. - - - - - - Use and vips will - leak-test on exit, and also display an estimate of peak memory use. - - - - - - Set G_MESSAGES_DEBUG=VIPS and GLib will display - informational and debug messages from libvips. - - - - - - - - VIPS comes with a couple of other useful programs. - vipsheader is a command which can print image header - fields. vipsedit can change fields in vips format - images. vipsthumbnail can make image thumbnails - quickly. - - - - diff --git a/doc/using-from-c.md b/doc/using-from-c.md new file mode 100644 index 0000000000..f1cc106154 --- /dev/null +++ b/doc/using-from-c.md @@ -0,0 +1,286 @@ +Title: Using > C + +libvips comes with a convenient, high-level C API. You should read the API +docs for full details, but this section will try to give a brief overview. + +## Library startup + +When your program starts, use [func@INIT] to start up libvips. You +should pass it the name of your program, usually `argv[0]`. If +you call [func@shutdown] just before you exit, libvips will attempt to free +all resources. This can help leak checking, but is not required. + +[func@INIT] is a macro to let it check that the libvips shared library you +have linked to matches the libvips headers you included. + +You can add the libvips flags to your [class@GObject.Object] command-line +processing with [func@add_option_entries]. + +## The [class@Image] class + +The basic data object is the [class@Image]. You can create an image from a +file on disc or from an area of memory, either as a C-style array, or as a +formatted object, like JPEG. See [ctor@Image.new_from_file] and friends. +Loading an image is fast: libvips read just enough of the image to be able +to get the various properties, such as width, but no decoding occurs until +pixel values are really needed. + +Once you have an image, you can get properties from it in the usual +way. You can use projection functions, like [method@Image.get_width] or +[method@GObject.Object.get], to get [class@GObject.Object] properties. All +libvips objects are immutable, meaning you can only get properties, you +can't set them. See [libvips Header](file-format.html) to read about image +properties. + +## Reference counting + +libvips is based on the [class@GObject.Object] library and is therefore +reference counted. [ctor@Image.new_from_file] returns an object with a count +of 1. When you are done with an image, use [method@GObject.Object.unref] to +dispose of it. If you pass an image to an operation and that operation needs +to keep a copy of the image, it will ref it. So you can unref an image as soon +as you no longer need it, you don't need to hang on to it in case anyone else +is still using it. + +See [class@Operation] for more details on libvips' reference counting +conventions. See the [Reference pools](#reference-pools) section below +for a way to automate reference counting in C. + +## libvips operations + +Use things like [method@Image.embed] to manipulate your images. You use it +from C like this: + +```c +const char *filename; +VipsImage *in = vips_image_new_from_file(filename, NULL); +const int x = 10; +const int y = 10; +const int width = 1000; +const int height = 1000; +VipsImage *out; + +if (vips_embed(in, &out, x, y, width, height, NULL)) + error_handling(); +``` + +Now `out` will hold a reference to a 1000 by 1000 pixel image, with `in` +pasted 10 right and 10 down from the top left-hand corner. The remainder +of the image will be black. If `in` is too large, it will be clipped at +the image edges. + +Operations can take optional arguments. You give these as a set of +NULL-terminated name-value pairs at the end of the call. For example, +you can write: + +```c +if (vips_embed(in, &out, x, y, width, height, + "extend", VIPS_EXTEND_COPY, + NULL)) + error_handling(); +``` + +And now the new edge pixels, which were black, will be filled with a copy +of the edge pixels of `in`. Operation options are listed at the top of each +operation's entry in the docs. Alternatively, the `vips` program is handy +for getting a summary of an operation's parameters. For example: + +```bash +$ vips embed +embed an image in a larger image +usage: + embed in out x y width height [--option-name option-value ...] +where: + in - Input image, input VipsImage + out - Output image, output VipsImage + x - Left edge of input in output, input gint + default: 0 + min: -1000000000, max: 1000000000 + y - Top edge of input in output, input gint + default: 0 + min: -1000000000, max: 1000000000 + width - Image width in pixels, input gint + default: 1 + min: 1, max: 1000000000 + height - Image height in pixels, input gint + default: 1 + min: 1, max: 1000000000 +optional arguments: + extend - How to generate the extra pixels, input VipsExtend + default enum: black + allowed enums: black, copy, repeat, mirror, white, background + background - Colour for background pixels, input VipsArrayDouble +``` + +See [class@Operation] for more information on running operations on images. + +The API docs have a [handy table of all libvips operations]( +function-list.html), if you want to find out how to do something, try +searching that. + +When you are done, you can write the final image to a disc file, +to a formatted memory buffer, or to C-style memory array. See +[method@Image.write_to_file] and friends. + +## Getting pixels + +Use [class@Region] to read pixels out of images. You can use [func@IMAGE_ADDR] +as well, but this can need a large amount of memory to work. See [extending]( +extending.html) for an introduction to writing your own operations. + +## Error handling + +libvips keeps a log of error message, see [func@error_buffer] and +[func@error_clear] to find out how to get and clear the error log. + +## Example + +On Unix systems, you can compile the [example code](#libvips-from-c-example) +with something like: + +```bash +$ gcc -g -Wall myprog.c `pkg-config vips --cflags --libs` +``` + +On Windows, you'll need to set the compiler flags by hand, perhaps: + +```bash +x86_64-w64-mingw32-gcc-win32 -mms-bitfields \ + -Ic:/vips-8.6/include \ + -Ic:/vips-8.6/include/glib-2.0 \ + -Ic:/vips-8.6/lib/glib-2.0/include \ + myprog.c \ + -Lc:/vips-8.6/lib \ + -lvips -lz -ljpeg -lstdc++ -lxml2 -lfftw3 -lm -lMagickWand -llcms2 \ + -lopenslide -lcfitsio -lpangoft2-1.0 -ltiff -lpng14 -lexif \ + -lMagickCore -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 \ + -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl \ + -o myprog.exe +``` + +## libvips from C example + +```c +#include +#include + +int +main(int argc, char **argv) +{ + VipsImage *in; + double mean; + VipsImage *out; + + if (VIPS_INIT(argv[0])) + vips_error_exit(NULL); + + if (argc != 3) + vips_error_exit("usage: %s infile outfile", argv[0]); + + if (!(in = vips_image_new_from_file(argv[1], NULL))) + vips_error_exit(NULL); + + printf("image width = %d\n", vips_image_get_width(in)); + + if (vips_avg(in, &mean, NULL)) + vips_error_exit(NULL); + + printf("mean pixel value = %g\n", mean); + + if (vips_invert(in, &out, NULL)) + vips_error_exit(NULL); + + g_object_unref(in); + + if (vips_image_write_to_file(out, argv[2], NULL)) + vips_error_exit(NULL); + + g_object_unref(out); + + return 0; +} +``` + +## Reference pools + +libvips has a simple system to automate at least some reference counting +issues. Reference pools are arrays of object pointers which will be released +automatically when some other object is finalized. + +The code below crops a many-page image (perhaps a GIF or PDF). It splits the +image into separate pages, crops each page, reassembles the cropped areas, +and saves again. It creates a `context` object representing the state of +processing, and `crop_animation` allocates two reference pools off that +using [method@Object.local_array], one to hold the cropped frames, and one +to assemble and copy the result. + +All unreffing is handled by `main`, and it doesn't need to know anything +about `crop_animation`. + +```c +#include + +static int +crop_animation(VipsObject *context, VipsImage *image, VipsImage **out, + int left, int top, int width, int height) +{ + int page_height = vips_image_get_page_height(image); + int n_pages = image->Ysize / page_height; + VipsImage **page = (VipsImage **) vips_object_local_array(context, n_pages); + VipsImage **copy = (VipsImage **) vips_object_local_array(context, 1); + + int i; + + /* Split the image into cropped frames. + */ + for (i = 0; i < n_pages; i++) + if (vips_crop(image, &page[i], + left, page_height * i + top, width, height, NULL)) + return -1; + + /* Reassemble the frames and set the page height. You must copy before + * modifying metadata. + */ + if (vips_arrayjoin(page, ©[0], n_pages, "across", 1, NULL) || + vips_copy(copy[0], out, NULL)) + return -1; + vips_image_set_int(*out, "page-height", height); + + return 0; +} + +int +main(int argc, char **argv) +{ + VipsImage *image; + VipsObject *context; + VipsImage *x; + + if (VIPS_INIT(NULL)) + vips_error_exit(NULL); + + if (!(image = vips_image_new_from_file(argv[1], + "access", VIPS_ACCESS_SEQUENTIAL, + NULL))) + vips_error_exit(NULL); + + context = VIPS_OBJECT(vips_image_new()); + if (crop_animation(context, image, &x, 10, 10, 500, 500)) { + g_object_unref(image); + g_object_unref(context); + vips_error_exit(NULL); + } + g_object_unref(image); + g_object_unref(context); + image = x; + + if (vips_image_write_to_file(image, argv[2], NULL)) { + g_object_unref(image); + vips_error_exit(NULL); + } + + g_object_unref(image); + + return 0; +} +``` diff --git a/doc/using-from-cplusplus.md b/doc/using-from-cplusplus.md new file mode 100644 index 0000000000..431cdb3780 --- /dev/null +++ b/doc/using-from-cplusplus.md @@ -0,0 +1,8 @@ +Title: Using > C++ + +libvips comes with a convenient C++ API. It is a very thin wrapper over the +C API and adds automatic reference counting, exceptions, operator +overloads, and automatic constant expansion. + +See the [C++ API documentation](https://www.libvips.org/API/current/cpp/) +for more details. diff --git a/doc/using-the-cli.md b/doc/using-the-cli.md new file mode 100644 index 0000000000..cddacc6226 --- /dev/null +++ b/doc/using-the-cli.md @@ -0,0 +1,162 @@ +Title: Using > At the command-line + +Use the `vips` command to execute libvips operations from the command-line. +For example: + +```bash +$ vips rot k2.jpg x.jpg d90 +``` + +Will rotate the image `k2.jpg` by 90 degrees anticlockwise and write the +result to the file `x.jpg`. If you don't give any arguments to an operation, +`vips` will give a short description, for example: + +```bash +$ vips rot +rotate an image +usage: + rot in out angle +where: + in - Input image, input VipsImage + out - Output image, output VipsImage + angle - Angle to rotate image, input VipsAngle + default: d90 + allowed: d0, d90, d180, d270 +``` + +There's a straightforward relationship with the C API: compare this to the +API docs for [method@Image.rot]. + +## Listing all operations + +You can list all classes with: + +```bash +$ vips -l +... +VipsOperation (operation), operations + VipsSystem (system), run an external command + VipsArithmetic (arithmetic), arithmetic operations + VipsBinary (binary), binary operations + VipsAdd (add), add two images + ... etc. +``` + +Each line shows the canonical name of the class (for example `VipsAdd`), the +class nickname (`add` in this case), and a short description. Some subclasses +of operation will show more: for example, subclasses of `VipsForeign` +will show some of the extra flags supported by the file load/save operations. + +The API docs have a [handy table of all libvips operations]( +function-list.html), if you want to find out how to do something, try +searching that. + +## Optional arguments + +Many operations take optional arguments. You can supply these as command-line +options. For example: + +```bash +$ vips gamma +gamma an image +usage: + gamma in out [--option-name option-value ...] +where: + in - Input image, input VipsImage + out - Output image, output VipsImage +optional arguments: + exponent - Gamma factor, input gdouble + default: 0.416667 + min: 1e-06, max: 1000 +operation flags: sequential +``` + +[method@Image.gamma] applies a gamma factor to an image. By +default, it uses 2.4, the sRGB gamma factor, but you can specify any +gamma with the `exponent` option. + +Use it from the command-line like this: + +```bash +$ vips gamma k2.jpg x.jpg --exponent 0.42 +``` + +This will read file `k2.jpg`, un-gamma it, and +write the result to file `x.jpg`. + +## Array arguments + +Some operations take arrays of values as arguments. For example, +[method@Image.affine] needs an array of four numbers for the +2x2 transform matrix. You pass arrays as space-separated lists: + +```bash +$ vips affine k2.jpg x.jpg "2 0 0 1" +``` + +You may need the quotes to stop your shell breaking the argument at +the spaces. [func@Image.bandjoin] needs an array of input images to +join, run it like this: + +```bash +$ vips bandjoin "k2.jpg k4.jpg" x.tif +``` + +## Implicit file format conversion + +`vips` will automatically convert between image file +formats for you. Input images are detected by sniffing their first few +bytes; output formats are set from the filename suffix. You can see a +list of all the supported file formats with something like: + +```bash +$ vips -l foreign +``` + +Then get a list of the options a format supports with: + +```bash +$ vips jpegsave +``` + +You can pass options to the implicit load and save operations enclosed +in square brackets after the filename: + +```bash +$ vips affine k2.jpg x.jpg[Q=90,strip] "2 0 0 1" +``` + +Will write `x.jpg` at quality level 90 and will +strip all metadata from the image. + +## Chaining operations + +Because each operation runs in a separate process, you can't use +libvips's chaining system to join operations together, you have to use +intermediate files. The command-line interface is therefore quite a bit +slower than Python or C. + +The best alternative is to use libvips files for intermediates. +Something like: + +```bash +$ vips invert input.jpg t1.v +$ vips affine t1.v output.jpg "2 0 0 1" +$ rm t1.v +``` + +## Other features + +Finally, `vips` has a couple of useful extra options. + +- Use `--vips-progress` to get `vips` to display a simple progress indicator. + +- Use `--vips-leak` and `vips` will leak-test + on exit, and also display an estimate of peak memory use. + +- Set `G_MESSAGES_DEBUG=VIPS` and GLib will display informational + and debug messages from libvips. + +libvips comes with a couple of other useful programs. `vipsheader` is a +command which can print image header fields. `vipsedit` can change fields +in `.v` format images. `vipsthumbnail` can make image thumbnails quickly. diff --git a/doc/using-threads.md b/doc/using-threads.md new file mode 100644 index 0000000000..014d76fbf3 --- /dev/null +++ b/doc/using-threads.md @@ -0,0 +1,178 @@ +Title: Using > Threads + +This section tries to summarise the rules for threaded programs using +libvips. Generally, libvips is threaded and thread-safe, with a few +exceptions. + +## Images + +On startup, you need to call [func@INIT] single-threaded. After that, +you can freely create images in any thread and read them in any other +thread. See the example at the end of this chapter. +Note that results can also be shared between threads for you by the +libvips operation cache. + +The exception is the drawing operators, such as [method@Image.draw_circle]. +These operations modify their image argument so you can't call them on +the same image from more than one thread. Reading from an image while +another thread is writing to it with one of the draw operations will +obviously also fail. + +When libvips calculates an image, by default it will use as many +threads as you have CPU cores. Use [func@concurrency_set] to change this. + +## Error handling + +libvips has a single error code (-1 or %NULL) returned by all functions +on error. Error messages are not returned, instead they are logged +in a single global error buffer shared by all threads, see +[func@error_buffer]. + +This makes error handling very simple but the obvious downside is that +because error returns and error messages are separate, when you +detect an error return you can't be +sure that what's in the error buffer is the message that matches your +error. + +The simplest way to handle this is to present the whole error log to +the user on the next interaction and leave it to them to decide what +action caused the failure. + +## Using [class@Region] between threads + +[class@Image] objects are immutable and can be shared between +threads very simply. However the lower-level [class@Region] object +used to implement [class@Image] (see [extending libvips](extending.html)) is +mutable and you can only use a [class@Region] from one thread at once. + +In fact it's worse than that: to reduce locking, [class@Region] keeps a +lot of state in per-thread storage. If you want to create a region in +one thread and use it in another, you have to first tag the region as +unowned from the creating thread with `vips__region_no_ownership()`, then +in the receiving thread take ownership with +`vips__region_take_ownership()`. See the source for operations like +[method@Image.tilecache] if you're curious how this works. + +libvips includes a set of sanity checks for region ownership and will +fail if you don't pass ownership correctly. + +## Example + +This example runs many [method@Image.resize] in parallel from many threads. + +```c +/* Read from many threads. + * + * Compile with: + * + * gcc -g -Wall soak.c `pkg-config vips --cflags --libs` + * + * Run with: + * + * rm -rf x + * mkdir x + * for i in {0..10}; do ./a.out ~/pics/k2.jpg; done + * + */ + +#include +#include + +#include + +/* How many pings we run at once. + */ +#define NUM_IN_PARALLEL (50) + +/* Number of tests we do in total. + */ +#define TOTAL_TESTS (NUM_IN_PARALLEL * 20) + +/* Workers queue up on this. + */ +GMutex allocation_lock; + +/* Our set of threads. + */ +GThread *workers[NUM_IN_PARALLEL]; + +/* Number of calls so far. + */ +int n_calls = 0; + +/* Our test function. This is called by NUM_IN_PARALLEL threads a total of + * TOTAL_TESTS times. + */ +static int +test(const char *filename) +{ + VipsImage *im, *x; + char output_file[256]; + + snprintf(output_file, 256, "x/tmp-%p.jpg", g_thread_self()); + + if (!(im = vips_image_new_from_file(filename, + "access", VIPS_ACCESS_SEQUENTIAL, + NULL))) + return -1; + + if (vips_resize(im, &x, 0.1, NULL)) { + g_object_unref(im); + return -1; + } + g_object_unref(im); + im = x; + + if (vips_image_write_to_file(im, output_file, NULL)) { + g_object_unref(im); + return -1; + } + g_object_unref(im); + + return 0; +} + +/* What we run as a thread. + */ +static void * +worker(void *data) +{ + const char *filename = (const char *) data; + + for (;;) { + gboolean done; + + done = FALSE; + g_mutex_lock(&allocation_lock); + n_calls += 1; + if (n_calls > TOTAL_TESTS) + done = TRUE; + g_mutex_unlock(&allocation_lock); + + if (done) + break; + + if (test(filename)) + vips_error_exit(NULL); + } + + return NULL; +} + +int +main(int argc, char **argv) +{ + int i; + + if (VIPS_INIT(argv[0])) + vips_error_exit(NULL); + + for (i = 0; i < NUM_IN_PARALLEL; i++) + workers[i] = g_thread_new(NULL, (GThreadFunc) worker, argv[1]); + + for (i = 0; i < NUM_IN_PARALLEL; i++) + g_thread_join(workers[i]); + + return 0; +} +``` diff --git a/doc/using-threads.xml b/doc/using-threads.xml deleted file mode 100644 index 9d55875909..0000000000 --- a/doc/using-threads.xml +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - VIPS and threads - 3 - VIPS Library - - - - Using VIPS - VIPS and threading - - - - Codestin Search App - - This section tries to summarise the rules for threaded programs using - libvips. Generally, libvips is threaded and thread-safe, with a few - exceptions. - - - - - Codestin Search App - - On startup, you need to call VIPS_INIT() single-threaded. After that, - you can freely create images in any thread and read them in any other - thread. See the example at the end of this chapter. - Note that results can also be shared between threads for you by the vips - operation cache. - - - - The exception is the drawing operators, such as vips_draw_circle(). - These operations modify their image argument so you can't call them on - the same image from more than one thread. Reading from an image while - another thread is writing to it with one of the draw operations will - obviously also fail. - - - - When libvips calculates an image, by default it will use as many - threads as you have CPU cores. Use vips_concurrency_set() to change this. - - - - - - Codestin Search App - - libvips has a single error code (-1 or %NULL) returned by all functions - on error. Error messages are not returned, instead they are logged - in a single global error buffer shared by all threads, see - vips_error_buffer(). - - - - This makes error handling very simple but the obvious downside is that - because error returns and error messages are separate, when you - detect an error return you can't be - sure that what's in the error buffer is the message that matches your - error. - - - - The simplest way to handle this is to present the whole error log to - the user on the next interaction and leave it to them to decide what - action caused the failure. - - - - - - Codestin Search App - - #VipsImage objects are immutable and can be shared between - threads very simply. - However the lower-level #VipsRegion object used to implement #VipsImage - (see Extending VIPS) is mutable and you - can only use a #VipsRegion from one thread at once. - - - - In fact it's worse than that: to reduce locking, #VipsRegion keeps a - lot of state in per-thread storage. If you want to create a region in - one thread and use it in another, you have to first tag the region as - unowned from the creating thread with vips__region_no_ownership(), then - in the receiving thread take ownership with - vips__region_take_ownership(). See the source for operations like - vips_tilecache() if you're curious how this works. - - - - libvips includes a set of sanity checks for region ownership and will - fail if you don't pass ownership correctly. - - - - - - Codestin Search App - - This example runs many vips_resize() in parallel from many threads. - - - -Codestin Search App - -/* Read from many threads. - * - * Compile with: - * - * gcc -g -Wall soak.c `pkg-config vips --cflags --libs` - * - * Run with: - * - * rm -rf x - * mkdir x - * for i in {0..10}; do ./a.out ~/pics/k2.jpg; done - * - */ - -#include <stdio.h> -#include <glib.h> - -#include <vips/vips.h> - -/* How many pings we run at once. - */ -#define NUM_IN_PARALLEL (50) - -/* Number of tests we do in total. - */ -#define TOTAL_TESTS (NUM_IN_PARALLEL * 20) - -/* Workers queue up on this. - */ -GMutex allocation_lock; - -/* Our set of threads. - */ -GThread *workers[NUM_IN_PARALLEL]; - -/* Number of calls so far. - */ -int n_calls = 0; - -/* Our test function. This is called by NUM_IN_PARALLEL threads a total of - * TOTAL_TESTS times. - */ -static int -test(const char *filename) -{ - VipsImage *im, *x; - char output_file[256]; - - snprintf(output_file, 256, "x/tmp-%p.jpg", g_thread_self()); - - if (!(im = vips_image_new_from_file(filename, - "access", VIPS_ACCESS_SEQUENTIAL, - NULL))) - return -1; - - if (vips_resize(im, &x, 0.1, NULL)) { - g_object_unref(im); - return -1; - } - g_object_unref(im); - im = x; - - if (vips_image_write_to_file(im, output_file, NULL)) { - g_object_unref(im); - return -1; - } - g_object_unref(im); - - return 0; -} - -/* What we run as a thread. - */ -static void * -worker(void *data) -{ - const char *filename = (const char *) data; - - for (;;) { - gboolean done; - - done = FALSE; - g_mutex_lock(&allocation_lock); - n_calls += 1; - if (n_calls > TOTAL_TESTS) - done = TRUE; - g_mutex_unlock(&allocation_lock); - - if (done) - break; - - if (test(filename)) - vips_error_exit(NULL); - } - - return NULL; -} - -int -main(int argc, char **argv) -{ - int i; - - if (VIPS_INIT(argv[0])) - vips_error_exit(NULL); - - g_mutex_init(&allocation_lock); - - for (i = 0; i < NUM_IN_PARALLEL; i++) - workers[i] = g_thread_new(NULL, (GThreadFunc) worker, argv[1]); - - for (i = 0; i < NUM_IN_PARALLEL; i++) - g_thread_join(workers[i]); - - return 0; -} - - - - - - diff --git a/doc/Using-vipsthumbnail.md b/doc/using-vipsthumbnail.md similarity index 89% rename from doc/Using-vipsthumbnail.md rename to doc/using-vipsthumbnail.md index e18481c22e..d5e111e6b8 100644 --- a/doc/Using-vipsthumbnail.md +++ b/doc/using-vipsthumbnail.md @@ -1,23 +1,14 @@ - - Using `vipsthumbnail` - 3 - libvips - - - - `vipsthumbnail` - Introduction to `vipsthumbnail`, with examples - +Title: Using > vipsthumbnail libvips ships with a handy command-line image thumbnailer, `vipsthumbnail`. This page introduces it, with some examples. -The thumbnailing functionality is implemented by `vips_thumbnail()` and -`vips_thumbnail_buffer()` (which thumbnails an image held as a string), +The thumbnailing functionality is implemented by [ctor@Image.thumbnail] and +[ctor@Image.thumbnail_buffer] (which thumbnails an image held as a string), see the docs for details. You can use these functions from any language with a libvips binding. For example, from PHP you could write: -```php?start_inline=1 +```php $filename = "image.jpg"; $image = Vips\Image::thumbnail($filename, 200, ["height" => 200]); $image->writeToFile("my-thumbnail.jpg"); @@ -31,9 +22,9 @@ $ cat k2.jpg | \ cat > x.jpg ``` -# libvips options +## libvips options -`vipsthumbnail` supports the usual range of vips command-line options. A +`vipsthumbnail` supports the usual range of `vips` command-line options. A few of them are useful: `--vips-cache-trace` shows each operation as libvips starts it. It can be @@ -48,7 +39,7 @@ useful to see where libvips is looping and how often. `--vips-info` shows a higher level view of the operations that `vipsthumbnail` is running. -# Looping +## Looping `vipsthumbnail` can process many images in one command. For example: @@ -68,7 +59,7 @@ much load you want to put on your system. For example: $ parallel vipsthumbnail ::: *.jpg ``` -# Thumbnail size +## Thumbnail size You can set the bounding box of the generated thumbnail with the `--size` option. For example: @@ -93,7 +84,7 @@ than the target. You can append `!` to force a resize to the exact target size, breaking the aspect ratio. -# Cropping +## Cropping `vipsthumbnail` normally shrinks images to fit within the box set by `--size`. You can use the `--smartcrop` option to crop to fill the box instead. Excess @@ -105,18 +96,18 @@ $ vipsthumbnail owl.jpg --smartcrop attention -s 128 Where `owl.jpg` is an off-centre composition: -![](owl.jpg) +![Owl](owl.jpg) Gives this result: -![](tn_owl.jpg) +![Smartcrop](tn_owl.jpg) First it shrinks the image to get the vertical axis to 128 pixels, then crops down to 128 pixels across using the `attention` strategy. This one searches -the image for features which might catch a human eye, see `vips_smartcrop()` -for details. +the image for features which might catch a human eye, see +[method@Image.smartcrop] for details. -# Linear light +## Linear light Shrinking images involves combining many pixels into one. Arithmetic averaging really ought to be in terms of the number of photons, but (for @@ -148,7 +139,7 @@ user 0m4.640s sys 0m0.016s ``` -# Output directory +## Output directory You set the thumbnail write parameters with the `-o` option. This is a pattern which the input filename is pasted into to @@ -184,7 +175,7 @@ $ vipsthumbnail fred.jpg ../jim.tif -o mythumbs/tn_%s.jpg Now both input files will have thumbnails written to a subdirectory of their current directory. -# Output format and options +## Output format and options You can use `-o` to specify the thumbnail image format too. For example: @@ -206,11 +197,11 @@ optimizer. Check the image write operations to see all the possible options. For example: -``` +```bash $ vips jpegsave save image to jpeg file usage: - jpegsave in filename + jpegsave in filename [--option-name option-value ...] where: in - Image to save, input VipsImage filename - Filename to save to, input gchararray @@ -218,7 +209,6 @@ optional arguments: Q - Q factor, input gint default: 75 min: 1, max: 100 - profile - Filename of ICC profile to embed, input gchararray optimize-coding - Compute optimal Huffman coding tables, input gboolean default: false interlace - Generate an interlaced (progressive) jpeg, input gboolean @@ -242,6 +232,7 @@ optional arguments: default flags: exif:xmp:iptc:icc:other:all allowed flags: none, exif, xmp, iptc, icc, other, all background - Background value, input VipsArrayDouble + profile - Filename of ICC profile to embed, input gchararray ``` The `keep` option is especially useful. Many image have very large IPTC, @@ -250,7 +241,7 @@ large saving. For example: -``` +```bash $ vipsthumbnail 42-32157534.jpg $ ls -l tn_42-32157534.jpg -rw-r–r– 1 john john 6682 Nov 12 21:27 tn_42-32157534.jpg @@ -258,13 +249,13 @@ $ ls -l tn_42-32157534.jpg `keep=none` almost halves the size of the thumbnail: -``` +```bash $ vipsthumbnail 42-32157534.jpg -o x.jpg[optimize_coding,keep=none] $ ls -l x.jpg -rw-r–r– 1 john john 3600 Nov 12 21:27 x.jpg ``` -# Colour management +## Colour management `vipsthumbnail` will optionally put images through LittleCMS for you. You can use this to move all thumbnails to the same colour space. All web browsers @@ -274,7 +265,7 @@ This can save several kb per thumbnail. For example: -``` +```bash $ vipsthumbnail shark.jpg $ ls -l tn_shark.jpg -rw-r–r– 1 john john 7295 Nov  9 14:33 tn_shark.jpg @@ -283,8 +274,8 @@ $ ls -l tn_shark.jpg Now transform to sRGB and don't attach a profile (you can also use `keep=none`, though that will remove *all* metadata from the image): -``` -$ vipsthumbnail shark.jpg --export-profile srgb -o tn_shark.jpg[profile=none] +```bash +$ vipsthumbnail shark.jpg --output-profile srgb -o tn_shark.jpg[profile=none] $ ls -l tn_shark.jpg -rw-r–r– 1 john john 4229 Nov  9 14:33 tn_shark.jpg ``` @@ -300,16 +291,16 @@ space, even though it has no embedded profile. ```bash -$ vipsthumbnail kgdev.jpg --import-profile /my/profiles/a98.icm +$ vipsthumbnail kgdev.jpg --input-profile /my/profiles/a98.icm ``` -# Final suggestion +## Final suggestion Putting all this together, I suggest this as a sensible set of options: ```bash $ vipsthumbnail fred.jpg \ --size 128 \ - --export-profile srgb \ + --output-profile srgb \ -o tn_%s.jpg[optimize_coding,keep=none] ``` diff --git a/doc/version.xml.in b/doc/version.xml.in deleted file mode 100644 index 5c53e2937e..0000000000 --- a/doc/version.xml.in +++ /dev/null @@ -1 +0,0 @@ -@VIPS_VERSION@ \ No newline at end of file diff --git a/doc/vips.toml.in b/doc/vips.toml.in new file mode 100644 index 0000000000..51ee4123eb --- /dev/null +++ b/doc/vips.toml.in @@ -0,0 +1,98 @@ +[library] +name = "Vips" +version = "@VIPS_VERSION@" +browse_url = "https://github.com/libvips/libvips" +repository_url = "https://github.com/libvips/libvips.git" +website_url = "https://www.libvips.org" +docs_url = "https://www.libvips.org/API/@VIPS_VERSION@/" +authors = "libvips team and contributors" +license = "LGPL-2.1-or-later" +description = "The libvips image processing library" +search_index = true + +# List the dependencies using their GIR namespace +dependencies = ["GObject-2.0"] + + [dependencies."GObject-2.0"] + name = "GObject" + description = "The base type system library" + docs_url = "https://docs.gtk.org/gobject/" + +related = ["GObject-2.0"] + + [related."GObject-2.0"] + name = "GObject" + description = "The base type system library" + docs_url = "https://docs.gtk.org/gobject/" + +[theme] +name = "basic" +show_class_hierarchy = true +show_index_summary = true + +[source-location] +# The base URL for accessing a file in the repository +base_url = "https://github.com/libvips/libvips/blob/master/" + +[extra] +# The same order will be used when generating the index +content_files = [ + "using-the-cli.md", + "using-from-c.md", + "using-from-cplusplus.md", + "making-image-pyramids.md", + "multipage-and-animated-images.md", + "using-vipsthumbnail.md", + "using-threads.md", + "developer-checklist.md", + "examples.md", + + "function-list.md", + "libvips-basic.md", + "libvips-memory.md", + "libvips-error.md", + "libvips-vips.md", + "libvips-arithmetic.md", + "libvips-colour.md", + "libvips-conversion.md", + "libvips-convolution.md", + "libvips-create.md", + "libvips-draw.md", + "libvips-freqfilt.md", + "libvips-generate.md", + "libvips-header.md", + "libvips-histogram.md", + "libvips-morphology.md", + "libvips-mosaicing.md", + "libvips-resample.md", + + "how-it-works.md", + "how-it-opens-files.md", + "file-format.md", + + "extending.md", + "binding.md", + + "cite.md", + +] +content_images = [ + "images/Combine.png", + "images/interconvert.png", + "images/Memtrace.png", + "images/owl.jpg", + "images/Sequence.png", + "images/Sink.png", + "images/tn_owl.jpg", + "images/Vips-smp.png", +] +content_base_url = "https://github.com/libvips/libvips/blob/master/doc/" +urlmap_file = "urlmap.js" + +[check] +ignore_deprecated = true + +# Hide the following types from the docs +[[object]] +name = "Token" +hidden = true diff --git a/examples/assemble-animated.c b/examples/assemble-animated.c new file mode 100644 index 0000000000..31ac691271 --- /dev/null +++ b/examples/assemble-animated.c @@ -0,0 +1,54 @@ +/* compile with + * + * gcc -g -Wall assemble-animated.c `pkg-config vips --cflags --libs` + */ + +#include +#include + +/* for libvips before 8.16, add this line: + * G_DEFINE_AUTOPTR_CLEANUP_FUNC(VipsImage, g_object_unref) + */ + +int +main(int argc, char *argv[]) +{ + if (VIPS_INIT(argv[0])) + vips_error_exit(NULL); + if (argc < 3) + vips_error_exit("usage: %s outfile infile1 infile2 ...", argv[0]); + + /* Load a set of input files. + */ + g_autoptr(GPtrArray) frames = g_ptr_array_new_full(argc, g_object_unref); + for (int i = 2; i < argc; i++) { + VipsImage *frame; + if (!(frame = vips_image_new_from_file(argv[i], + "access", VIPS_ACCESS_SEQUENTIAL, + NULL))) + vips_error_exit(NULL); + + g_ptr_array_add(frames, frame); + } + + /* Combine to form a vertical strip. + */ + g_autoptr(VipsImage) strip; + if (vips_arrayjoin((VipsImage **) frames->pdata, &strip, frames->len, + "across", 1, + NULL)) + vips_error_exit(NULL); + + /* Set the animation metadata. Delay times are in milliseconds. + */ + VipsImage *frame0 = VIPS_IMAGE(frames->pdata[0]); + vips_image_set_int(strip, "page-height", frame0->Ysize); + vips_image_set_int(strip, "loop", 10); + int delays[] = { 300, 300, 300 }; + vips_image_set_array_int(strip, "delay", delays, VIPS_NUMBER(delays)); + + if (vips_image_write_to_file(strip, argv[1], NULL)) + vips_error_exit(NULL); + + return 0; +} diff --git a/fuzz/oss_fuzz_build.sh b/fuzz/oss_fuzz_build.sh index 091ef1252c..63f6b8f94e 100755 --- a/fuzz/oss_fuzz_build.sh +++ b/fuzz/oss_fuzz_build.sh @@ -43,7 +43,7 @@ popd # lcms pushd $SRC/lcms meson setup build --prefix=$WORK --libdir=lib --default-library=static --buildtype=debugoptimized \ - -Djpeg=disabled -Dtiff=disabled + -Dtests=disabled -Djpeg=disabled -Dtiff=disabled meson install -C build --tag devel popd @@ -103,7 +103,7 @@ popd # libspng pushd $SRC/libspng meson setup build --prefix=$WORK --libdir=lib --default-library=static --buildtype=debugoptimized \ - -Dstatic_zlib=true + -Dstatic_zlib=true -Dbuild_examples=false meson install -C build --tag devel popd @@ -148,7 +148,8 @@ popd # cgif pushd $SRC/cgif -meson setup build --prefix=$WORK --libdir=lib --default-library=static --buildtype=debugoptimized +meson setup build --prefix=$WORK --libdir=lib --default-library=static --buildtype=debugoptimized \ + -Dexamples=false -Dtests=false meson install -C build --tag devel popd @@ -187,11 +188,14 @@ cmake \ cmake --build . --target install popd +# FIXME: Workaround for https://github.com/mesonbuild/meson/issues/14533 +export LDFLAGS+=" $CFLAGS" + # libvips # Disable building man pages, gettext po files, tools, and tests sed -i "/subdir('man')/{N;N;N;d;}" meson.build meson setup build --prefix=$WORK --libdir=lib --prefer-static --default-library=static --buildtype=debugoptimized \ - -Dbackend_max_links=4 -Ddeprecated=false -Dexamples=false -Dcplusplus=false -Dmodules=disabled \ + -Ddeprecated=false -Dexamples=false -Dcplusplus=false -Dmodules=disabled \ -Dfuzzing_engine=oss-fuzz -Dfuzzer_ldflags="$LIB_FUZZING_ENGINE" \ -Dcpp_link_args="$LDFLAGS -Wl,-rpath=\$ORIGIN/lib" meson install -C build --tag devel diff --git a/libvips/arithmetic/abs.c b/libvips/arithmetic/abs.c index 72db08f390..90f52faa8e 100644 --- a/libvips/arithmetic/abs.c +++ b/libvips/arithmetic/abs.c @@ -116,7 +116,7 @@ vips_abs_build(VipsObject *object) int x; \ \ for (x = 0; x < sz; x++) \ - q[x] = VIPS_FABS(p[x]); \ + q[x] = fabs(p[x]); \ } /* Complex abs operation: calculate modulus. @@ -212,17 +212,18 @@ vips_abs_init(VipsAbs *abs) /** * vips_abs: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * * This operation finds the absolute value of an image. It does a copy for * unsigned integer types, negate for negative values in - * signed integer types, fabs(3) for + * signed integer types, [`fabs()`](man:fabs(3)) for * float types, and calculates modulus for complex * types. * - * See also: vips_sign(). + * ::: seealso + * [method@Image.sign]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/add.c b/libvips/arithmetic/add.c index 64b2a4b250..351dcc6420 100644 --- a/libvips/arithmetic/add.c +++ b/libvips/arithmetic/add.c @@ -188,11 +188,11 @@ vips_add_init(VipsAdd *add) } /** - * vips_add: + * vips_add: (method) * @left: input image * @right: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates @in1 + @in2 and writes the result to @out. * @@ -206,67 +206,29 @@ vips_add_init(VipsAdd *add) * * The two input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic), then the + * [arithmetic](libvips-arithmetic.html)), then the * following table is used to determine the output type: * - * - * Codestin Search App - * - * - * - * input type - * output type - * - * - * - * - * uchar - * ushort - * - * - * char - * short - * - * - * ushort - * uint - * - * - * short - * int - * - * - * uint - * uint - * - * - * int - * int - * - * - * float - * float - * - * - * double - * double - * - * - * complex - * complex - * - * - * double complex - * double complex - * - * - * - *
+ * ## [method@Image.add] type promotion + * + * | input type | output type | + * |----------------|----------------| + * | uchar | ushort | + * | char | short | + * | ushort | uint | + * | short | int | + * | uint | uint | + * | int | int | + * | float | float | + * | double | double | + * | complex | complex | + * | double complex | double complex | * * In other words, the output type is just large enough to hold the whole * range of possible values. * - * See also: vips_subtract(), vips_linear(). + * ::: seealso + * [method@Image.subtract], [method@Image.linear]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index c51c90583c..814397d048 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -55,213 +55,6 @@ #include "parithmetic.h" -/** - * SECTION: arithmetic - * @short_description: pixel arithmetic, trig, log, statistics - * @stability: Stable - * @include: vips/vips.h - * - * These operations perform pixel arithmetic, that is, they perform an - * arithmetic operation, such as addition, on every pixel in an image or a - * pair of images. All (except in a few cases noted below) will work with - * images of any type or any mixture of types, of any size and of any number - * of bands. - * - * For binary operations, if the number of bands differs, one of the images - * must have one band. In this case, an n-band image is formed from the - * one-band image by joining n copies of the one-band image together, and then - * the two n-band images are operated upon. - * - * In the same way, for operations that take an array constant, such as - * vips_remainder_const(), you can mix single-element arrays or single-band - * images freely. - * - * Arithmetic operations try to preserve precision by increasing the number of - * bits in the output image when necessary. Generally, this follows the ANSI C - * conventions for type promotion, so multiplying two - * #VIPS_FORMAT_UCHAR images together, for example, produces a - * #VIPS_FORMAT_USHORT image, and taking the vips_cos() of a - * #VIPS_FORMAT_USHORT image produces #VIPS_FORMAT_FLOAT image. - * - * After processing, use vips_cast() and friends to take then format back down - * again. vips_cast_uchar(), for example, will cast any image down to 8-bit - * unsigned. - * - * Images have an *interpretation*: a meaning for the pixel values. With - * #VIPS_INTERPRETATION_sRGB, for example, the first three bands will be - * interpreted (for example, by a saver like vips_jpegsave()) as R, G and B, - * with values in 0 - 255, and any fourth band will be interpreted as an - * alpha channel. - * - * After arithmetic, you may wish to change the interpretation (for example to - * save as 16-bit PNG). Use vips_copy() to change the interpretation without - * changing pixels. - * - * For binary arithmetic operations, type promotion occurs in two stages. - * First, the two input images are cast up to the smallest common format, - * that is, the type with the smallest range that can represent the full - * range of both inputs. This conversion can be represented as a table: - * - * - * Codestin Search App - * - * - * - * @in2/@in1 - * uchar - * char - * ushort - * short - * uint - * int - * float - * double - * complex - * double complex - * - * - * - * - * uchar - * ushort - * short - * ushort - * short - * uint - * int - * float - * double - * complex - * double complex - * - * - * char - * short - * short - * short - * short - * int - * int - * float - * double - * complex - * double complex - * - * - * ushort - * ushort - * short - * ushort - * short - * uint - * int - * float - * double - * complex - * double complex - * - * - * short - * short - * short - * short - * short - * int - * int - * float - * double - * complex - * double complex - * - * - * uint - * uint - * int - * uint - * int - * uint - * int - * float - * double - * complex - * double complex - * - * - * int - * int - * int - * int - * int - * int - * int - * float - * double - * complex - * double complex - * - * - * float - * float - * float - * float - * float - * float - * float - * float - * double - * complex - * double complex - * - * - * double - * double - * double - * double - * double - * double - * double - * double - * double - * double complex - * double complex - * - * - * complex - * complex - * complex - * complex - * complex - * complex - * complex - * complex - * double complex - * complex - * double complex - * - * - * double complex - * double complex - * double complex - * double complex - * double complex - * double complex - * double complex - * double complex - * double complex - * double complex - * double complex - * - * - * - *
- * - * In the second stage, the operation is performed between the two identical - * types to form the output. The details vary between operations, but - * generally the principle is that the output type should be large enough to - * represent the whole range of possible values, except that int never becomes - * float. - */ - G_DEFINE_ABSTRACT_TYPE(VipsArithmetic, vips_arithmetic, VIPS_TYPE_OPERATION); /* Save a bit of typing. diff --git a/libvips/arithmetic/avg.c b/libvips/arithmetic/avg.c index 49c1dad9fc..45e8117cb6 100644 --- a/libvips/arithmetic/avg.c +++ b/libvips/arithmetic/avg.c @@ -246,15 +246,16 @@ vips_avg_init(VipsAvg *avg) /** * vips_avg: (method) - * @in: input #VipsImage + * @in: input [class@Image] * @out: (out): output pixel average - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation finds the average value in an image. It operates on all - * bands of the input image: use vips_stats() if you need to calculate an + * bands of the input image: use [method@Image.stats] if you need to calculate an * average for each band. For complex images, return the average modulus. * - * See also: vips_stats(), vips_bandmean(), vips_deviate(), vips_rank() + * ::: seealso + * [method@Image.stats], [method@Image.bandmean], [method@Image.deviate], [method@Image.rank] * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/boolean.c b/libvips/arithmetic/boolean.c index 71315dc09f..6a679b04c7 100644 --- a/libvips/arithmetic/boolean.c +++ b/libvips/arithmetic/boolean.c @@ -1,4 +1,4 @@ -/* boolean.c --- various bit operations +/* boolean.c -- various bit operations * * Modified: * 15/12/94 JC @@ -295,12 +295,12 @@ vips_booleanv(VipsImage *left, VipsImage *right, VipsImage **out, } /** - * vips_boolean: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage + * vips_boolean: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] * @boolean: boolean operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various boolean operations on pairs of images. * @@ -318,9 +318,10 @@ vips_booleanv(VipsImage *left, VipsImage *right, VipsImage **out, * * The two input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). * - * See also: vips_boolean_const(). + * ::: seealso + * [method@Image.boolean_const]. * * Returns: 0 on success, -1 on error */ @@ -339,14 +340,14 @@ vips_boolean(VipsImage *left, VipsImage *right, VipsImage **out, } /** - * vips_andimage: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_andimage: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_AND on a pair of images. See - * vips_boolean(). + * Perform [enum@Vips.OperationBoolean.AND] on a pair of images. See + * [method@Image.boolean]. * * Returns: 0 on success, -1 on error */ @@ -365,14 +366,14 @@ vips_andimage(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_orimage: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_orimage: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_OR on a pair of images. See - * vips_boolean(). + * Perform [enum@Vips.OperationBoolean.OR] on a pair of images. See + * [method@Image.boolean]. * * Returns: 0 on success, -1 on error */ @@ -391,14 +392,14 @@ vips_orimage(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_eorimage: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_eorimage: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_EOR on a pair of images. See - * vips_boolean(). + * Perform [enum@Vips.OperationBoolean.EOR] on a pair of images. See + * [method@Image.boolean]. * * Returns: 0 on success, -1 on error */ @@ -417,14 +418,14 @@ vips_eorimage(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_lshift: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_lshift: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_LSHIFT on a pair of images. See - * vips_boolean(). + * Perform [enum@Vips.OperationBoolean.LSHIFT] on a pair of images. See + * [method@Image.boolean]. * * Returns: 0 on success, -1 on error */ @@ -443,14 +444,14 @@ vips_lshift(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_rshift: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_rshift: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_RSHIFT on a pair of images. See - * vips_boolean(). + * Perform [enum@Vips.OperationBoolean.RSHIFT] on a pair of images. See + * [method@Image.boolean]. * * Returns: 0 on success, -1 on error */ @@ -616,7 +617,7 @@ vips_boolean_constv(VipsImage *in, VipsImage **out, * @boolean: boolean operation to perform * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various boolean operations on an image against an array of * constants. @@ -630,7 +631,8 @@ vips_boolean_constv(VipsImage *in, VipsImage **out, * element and the image only has a single band, the result is a many-band * image where each band corresponds to one array element. * - * See also: vips_boolean(), vips_boolean_const1(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const1]. * * Returns: 0 on success, -1 on error */ @@ -654,12 +656,13 @@ vips_boolean_const(VipsImage *in, VipsImage **out, * @out: (out): output image * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_AND on an image and an array of constants. - * See vips_boolean_const(). + * Perform [enum@Vips.OperationBoolean.AND] on an image and an array of constants. + * See [method@Image.boolean_const]. * - * See also: vips_boolean(), vips_boolean_const1(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const1]. * * Returns: 0 on success, -1 on error */ @@ -684,12 +687,13 @@ vips_andimage_const(VipsImage *in, VipsImage **out, * @out: (out): output image * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_OR on an image and an array of constants. - * See vips_boolean_const(). + * Perform [enum@Vips.OperationBoolean.OR] on an image and an array of constants. + * See [method@Image.boolean_const]. * - * See also: vips_boolean(), vips_boolean_const1(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const1]. * * Returns: 0 on success, -1 on error */ @@ -714,12 +718,13 @@ vips_orimage_const(VipsImage *in, VipsImage **out, * @out: (out): output image * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_EOR on an image and an array of constants. - * See vips_boolean_const(). + * Perform [enum@Vips.OperationBoolean.EOR] on an image and an array of constants. + * See [method@Image.boolean_const]. * - * See also: vips_boolean(), vips_boolean_const1(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const1]. * * Returns: 0 on success, -1 on error */ @@ -744,12 +749,13 @@ vips_eorimage_const(VipsImage *in, VipsImage **out, * @out: (out): output image * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_LSHIFT on an image and an array of constants. - * See vips_boolean_const(). + * Perform [enum@Vips.OperationBoolean.LSHIFT] on an image and an array of constants. + * See [method@Image.boolean_const]. * - * See also: vips_boolean(), vips_boolean_const1(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const1]. * * Returns: 0 on success, -1 on error */ @@ -773,12 +779,13 @@ vips_lshift_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) * @out: (out): output image * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_LSHIFT on an image and an array of constants. - * See vips_boolean_const(). + * Perform [enum@Vips.OperationBoolean.LSHIFT] on an image and an array of constants. + * See [method@Image.boolean_const]. * - * See also: vips_boolean(), vips_boolean_const1(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const1]. * * Returns: 0 on success, -1 on error */ @@ -802,12 +809,13 @@ vips_rshift_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) * @out: (out): output image * @boolean: boolean operation to perform * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various boolean operations on an image with a single constant. See - * vips_boolean_const(). + * [method@Image.boolean_const]. * - * See also: vips_boolean(), vips_boolean_const(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const]. * * Returns: 0 on success, -1 on error */ @@ -830,12 +838,13 @@ vips_boolean_const1(VipsImage *in, VipsImage **out, * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_AND on an image and a constant. - * See vips_boolean_const1(). + * Perform [enum@Vips.OperationBoolean.AND] on an image and a constant. + * See [method@Image.boolean_const1]. * - * See also: vips_boolean(), vips_boolean_const(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const]. * * Returns: 0 on success, -1 on error */ @@ -858,12 +867,13 @@ vips_andimage_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_OR on an image and a constant. - * See vips_boolean_const1(). + * Perform [enum@Vips.OperationBoolean.OR] on an image and a constant. + * See [method@Image.boolean_const1]. * - * See also: vips_boolean(), vips_boolean_const(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const]. * * Returns: 0 on success, -1 on error */ @@ -886,12 +896,13 @@ vips_orimage_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_EOR on an image and a constant. - * See vips_boolean_const1(). + * Perform [enum@Vips.OperationBoolean.EOR] on an image and a constant. + * See [method@Image.boolean_const1]. * - * See also: vips_boolean(), vips_boolean_const(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const]. * * Returns: 0 on success, -1 on error */ @@ -914,12 +925,13 @@ vips_eorimage_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_LSHIFT on an image and a constant. - * See vips_boolean_const1(). + * Perform [enum@Vips.OperationBoolean.LSHIFT] on an image and a constant. + * See [method@Image.boolean_const1]. * - * See also: vips_boolean(), vips_boolean_const(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const]. * * Returns: 0 on success, -1 on error */ @@ -942,12 +954,13 @@ vips_lshift_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_RSHIFT on an image and a constant. - * See vips_boolean_const1(). + * Perform [enum@Vips.OperationBoolean.RSHIFT] on an image and a constant. + * See [method@Image.boolean_const1]. * - * See also: vips_boolean(), vips_boolean_const(). + * ::: seealso + * [method@Image.boolean], [method@Image.boolean_const]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/clamp.c b/libvips/arithmetic/clamp.c index 5b53f75663..be22b47998 100644 --- a/libvips/arithmetic/clamp.c +++ b/libvips/arithmetic/clamp.c @@ -170,7 +170,7 @@ vips_clamp_class_init(VipsClampClass *class) _("Maximum value"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsClamp, max), - -INFINITY, INFINITY, 0.0); + -INFINITY, INFINITY, 1.0); } static void @@ -182,20 +182,20 @@ vips_clamp_init(VipsClamp *clamp) /** * vips_clamp: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @min: %gdouble, minimum value - * * @max: %gdouble, maximum value + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * * This operation clamps pixel values to a range, by default 0 - 1. * * Use @min and @max to change the range. * - * See also: vips_sign(), vips_abs(), vips_sdf(). + * ::: tip "Optional arguments" + * * @min: `gdouble`, minimum value + * * @max: `gdouble`, maximum value + * + * ::: seealso + * [method@Image.sign], [method@Image.abs], [ctor@Image.sdf]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/complex.c b/libvips/arithmetic/complex.c index 60010d994a..1ff9649ce2 100644 --- a/libvips/arithmetic/complex.c +++ b/libvips/arithmetic/complex.c @@ -276,10 +276,10 @@ vips_complexv(VipsImage *in, VipsImage **out, /** * vips_complex: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @cmplx: complex operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various operations on complex images. * @@ -303,11 +303,11 @@ vips_complex(VipsImage *in, VipsImage **out, VipsOperationComplex cmplx, ...) /** * vips_polar: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_COMPLEX_POLAR on an image. See vips_complex(). + * Perform [enum@Vips.OperationComplex.POLAR] on an image. See [method@Image.complex]. * * Returns: 0 on success, -1 on error */ @@ -326,11 +326,11 @@ vips_polar(VipsImage *in, VipsImage **out, ...) /** * vips_rect: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_COMPLEX_RECT on an image. See vips_complex(). + * Perform [enum@Vips.OperationComplex.RECT] on an image. See [method@Image.complex]. * * Returns: 0 on success, -1 on error */ @@ -349,11 +349,11 @@ vips_rect(VipsImage *in, VipsImage **out, ...) /** * vips_conj: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_COMPLEX_CONJ on an image. See vips_complex(). + * Perform [enum@Vips.OperationComplex.CONJ] on an image. See [method@Image.complex]. * * Returns: 0 on success, -1 on error */ @@ -449,12 +449,14 @@ G_DEFINE_TYPE(VipsComplex2, vips_complex2, VIPS_TYPE_BINARY); #define CROSS(Q, X1, Y1, X2, Y2) \ { \ if (((X1) == 0.0 && (Y1) == 0.0) || \ - ((X2) == 0.0 && (Y2) == 0.0)) { \ + ((X2) == 0.0 && (Y2) == 0.0) || \ + ((Y1) == 0.0 && (Y2) == 0.0)) { \ Q[0] = 0.0; \ Q[1] = 0.0; \ } \ else if (ABS(Y1) > ABS(Y2)) { \ - double a = Y2 / Y1; \ + double y1 = Y1; /* this suppress C2142 (division by zero) error on MSVC */ \ + double a = Y2 / y1; \ double b = Y1 + Y2 * a; \ double re = (X1 + X2 * a) / b; \ double im = (X2 - X1 * a) / b; \ @@ -464,7 +466,8 @@ G_DEFINE_TYPE(VipsComplex2, vips_complex2, VIPS_TYPE_BINARY); Q[1] = im / mod; \ } \ else { \ - double a = Y1 / Y2; \ + double y2 = Y2; \ + double a = Y1 / y2; \ double b = Y2 + Y1 * a; \ double re = (X1 * a + X2) / b; \ double im = (X2 * a - X1) / b; \ @@ -553,12 +556,12 @@ vips_complex2v(VipsImage *left, VipsImage *right, VipsImage **out, } /** - * vips_complex2: - * @left: input #VipsImage - * @right: input #VipsImage - * @out: (out): output #VipsImage + * vips_complex2: (method) + * @left: input [class@Image] + * @right: input [class@Image] + * @out: (out): output [class@Image] * @cmplx: complex2 operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various binary operations on complex images. * @@ -582,14 +585,14 @@ vips_complex2(VipsImage *left, VipsImage *right, VipsImage **out, } /** - * vips_cross_phase: - * @left: input #VipsImage - * @right: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_cross_phase: (method) + * @left: input [class@Image] + * @right: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_COMPLEX2_CROSS_PHASE on an image. - * See vips_complex2(). + * Perform [enum@Vips.OperationComplex2.CROSS_PHASE] on an image. + * See [method@Image.complex2]. * * Returns: 0 on success, -1 on error */ @@ -787,16 +790,16 @@ vips_complexgetv(VipsImage *in, VipsImage **out, /** * vips_complexget: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @get: complex operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Get components of complex images. * - * The output type is the same as the input type, except #VIPS_FORMAT_COMPLEX - * becomes #VIPS_FORMAT_FLOAT and #VIPS_FORMAT_DPCOMPLEX becomes - * #VIPS_FORMAT_DOUBLE. + * The output type is the same as the input type, except [enum@Vips.BandFormat.COMPLEX] + * becomes [enum@Vips.BandFormat.FLOAT] and [enum@Vips.BandFormat.DPCOMPLEX] becomes + * [enum@Vips.BandFormat.DOUBLE]. * * Returns: 0 on success, -1 on error */ @@ -816,11 +819,11 @@ vips_complexget(VipsImage *in, VipsImage **out, /** * vips_real: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_COMPLEXGET_REAL on an image. See vips_complexget(). + * Perform [enum@Vips.OperationComplexget.REAL] on an image. See [method@Image.complexget]. * * Returns: 0 on success, -1 on error */ @@ -840,11 +843,11 @@ vips_real(VipsImage *in, VipsImage **out, ...) /** * vips_imag: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_COMPLEXGET_IMAG on an image. See vips_complexget(). + * Perform [enum@Vips.OperationComplexget.IMAG] on an image. See [method@Image.complexget]. * * Returns: 0 on success, -1 on error */ @@ -987,15 +990,15 @@ vips_complexform_init(VipsComplexform *complexform) } /** - * vips_complexform: + * vips_complexform: (method) * @left: input image * @right: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Compose two real images to make a complex image. If either @left or @right - * are #VIPS_FORMAT_DOUBLE, @out is #VIPS_FORMAT_DPCOMPLEX. Otherwise @out - * is #VIPS_FORMAT_COMPLEX. @left becomes the real component of @out and + * are [enum@Vips.BandFormat.DOUBLE], @out is [enum@Vips.BandFormat.DPCOMPLEX]. Otherwise @out + * is [enum@Vips.BandFormat.COMPLEX]. @left becomes the real component of @out and * @right the imaginary. * * If the number of bands differs, one of the images @@ -1003,7 +1006,8 @@ vips_complexform_init(VipsComplexform *complexform) * one-band image by joining n copies of the one-band image together, and then * the two n-band images are operated upon. * - * See also: vips_complexget(). + * ::: seealso + * [method@Image.complexget]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/deviate.c b/libvips/arithmetic/deviate.c index 836ac77474..168992a109 100644 --- a/libvips/arithmetic/deviate.c +++ b/libvips/arithmetic/deviate.c @@ -120,7 +120,7 @@ vips_deviate_build(VipsObject *object) s2 = deviate->sum2; g_object_set(object, - "out", sqrt(VIPS_FABS(s2 - (s * s / vals)) / (vals - 1)), + "out", sqrt(fabs(s2 - (s * s / vals)) / (vals - 1)), NULL); return 0; @@ -248,17 +248,18 @@ vips_deviate_init(VipsDeviate *deviate) /** * vips_deviate: (method) - * @in: input #VipsImage + * @in: input [class@Image] * @out: (out): output pixel standard deviation - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation finds the standard deviation of all pixels in @in. It - * operates on all bands of the input image: use vips_stats() if you need + * operates on all bands of the input image: use [method@Image.stats] if you need * to calculate an average for each band. * * Non-complex images only. * - * See also: vips_avg(), vips_stats().. + * ::: seealso + * [method@Image.avg], [method@Image.stats].. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/divide.c b/libvips/arithmetic/divide.c index 26a43263c1..9bf007fa2e 100644 --- a/libvips/arithmetic/divide.c +++ b/libvips/arithmetic/divide.c @@ -97,7 +97,7 @@ G_DEFINE_TYPE(VipsDivide, vips_divide, VIPS_TYPE_BINARY); q[0] = 0.0; \ q[1] = 0.0; \ } \ - else if (VIPS_FABS(right[0]) > VIPS_FABS(right[1])) { \ + else if (fabs(right[0]) > fabs(right[1])) { \ double a = right[1] / right[0]; \ double b = right[0] + right[1] * a; \ \ @@ -220,11 +220,11 @@ vips_divide_init(VipsDivide *divide) } /** - * vips_divide: + * vips_divide: (method) * @left: input image * @right: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates @in1 / @in2 and writes the result to @out. If any * pixels in @in2 are zero, the corresponding pixel in @out is also zero. @@ -239,67 +239,29 @@ vips_divide_init(VipsDivide *divide) * * The two input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic), then the + * [arithmetic](libvips-arithmetic.html)), then the * following table is used to determine the output type: * - * - * Codestin Search App - * - * - * - * input type - * output type - * - * - * - * - * uchar - * float - * - * - * char - * float - * - * - * ushort - * float - * - * - * short - * float - * - * - * uint - * float - * - * - * int - * float - * - * - * float - * float - * - * - * double - * double - * - * - * complex - * complex - * - * - * double complex - * double complex - * - * - * - *
+ * ## [method@Image.divide] type promotion + * + * | input type | output type | + * |----------------|----------------| + * | uchar | float | + * | char | float | + * | ushort | float | + * | short | float | + * | uint | float | + * | int | float | + * | float | float | + * | double | double | + * | complex | complex | + * | double complex | double complex | * * In other words, the output type is just large enough to hold the whole * range of possible values. * - * See also: vips_multiply(), vips_linear(), vips_pow(). + * ::: seealso + * [method@Image.multiply], [method@Image.linear], [method@Image.pow]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/find_trim.c b/libvips/arithmetic/find_trim.c index 892c93d507..85d2d3b4c6 100644 --- a/libvips/arithmetic/find_trim.c +++ b/libvips/arithmetic/find_trim.c @@ -93,7 +93,7 @@ vips_find_trim_build(VipsObject *object) * for this interpretation. */ if (!vips_object_argument_isset(object, "background")) - find_trim->background = vips_array_double_newv(1, + find_trim->background = vips_array_double_newv(1, // FIXME: Invalidates operation cache vips_interpretation_max_alpha(find_trim->in->Type)); /* Flatten out alpha, if any. @@ -254,13 +254,7 @@ vips_find_trim_init(VipsFindTrim *find_trim) * @top: (out): output top edge * @width: (out): output width * @height: (out): output height - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @threshold: %gdouble, background / object threshold - * * @background: #VipsArrayDouble, background colour - * * @line_art: %gboolean, enable line art mode + * @...: `NULL`-terminated list of optional named arguments * * Search @in for the bounding box of the non-background area. * @@ -270,12 +264,12 @@ vips_find_trim_init(VipsFindTrim *find_trim) * the absolute difference are calculated from this binary image and searched * for the first row or column in each direction to obtain the bounding box. * - * If the image is entirely background, vips_find_trim() returns @width == 0 - * and @height == 0. + * If the image is entirely background, [method@Image.find_trim] returns + * @width == 0 and @height == 0. * * @background defaults to 255, or 65535 for 16-bit images. Set another value, - * or use vips_getpoint() to pick a value from an edge. You'll need to flatten - * before vips_getpoint() to get a correct background value. + * or use [method@Image.getpoint] to pick a value from an edge. You'll need + * to flatten before [method@Image.getpoint] to get a correct background value. * * @threshold defaults to 10. * @@ -286,7 +280,13 @@ vips_find_trim_init(VipsFindTrim *find_trim) * * The image needs to be at least 3x3 pixels in size. * - * See also: vips_getpoint(), vips_extract_area(), vips_smartcrop(). + * ::: tip "Optional arguments" + * * @threshold: `gdouble`, background / object threshold + * * @background: [struct@ArrayDouble], background colour + * * @line_art: `gboolean`, enable line art mode + * + * ::: seealso + * [method@Image.getpoint], [method@Image.extract_area], [method@Image.smartcrop]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/getpoint.c b/libvips/arithmetic/getpoint.c index 3af098d60a..0a0e20456a 100644 --- a/libvips/arithmetic/getpoint.c +++ b/libvips/arithmetic/getpoint.c @@ -196,18 +196,19 @@ vips_getpoint_init(VipsGetpoint *getpoint) * @n: length of output vector * @x: position to read * @y: position to read - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Reads a single pixel on an image. * * The pixel values are returned in @vector, the length of the - * array in @n. You must free the array with g_free() when you are done with + * array in @n. You must free the array with [func@GLib.free] when you are done with * it. * * The result array has an element for each band. If @unpack_complex is set, * pixels in complex images are returned as double-length arrays. * - * See also: vips_draw_point(). + * ::: seealso + * [method@Image.draw_point]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/arithmetic/hist_find.c b/libvips/arithmetic/hist_find.c index 29fdc420fc..9f697653a1 100644 --- a/libvips/arithmetic/hist_find.c +++ b/libvips/arithmetic/hist_find.c @@ -451,11 +451,7 @@ vips_hist_find_init(VipsHistFind *hist_find) * vips_hist_find: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @band: band to equalise + * @...: `NULL`-terminated list of optional named arguments * * Find the histogram of @in. Find the histogram for band @band (producing a * one-band histogram), or for all bands (producing an n-band histogram) if @@ -464,7 +460,11 @@ vips_hist_find_init(VipsHistFind *hist_find) * char and uchar images are cast to uchar before histogramming, all other * image types are cast to ushort. * - * See also: vips_hist_find_ndim(), vips_hist_find_indexed(). + * ::: tip "Optional arguments" + * * @band: band to equalise + * + * ::: seealso + * [method@Image.hist_find_ndim], [method@Image.hist_find_indexed]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/hist_find_indexed.c b/libvips/arithmetic/hist_find_indexed.c index 9c61ab7684..d34163bed1 100644 --- a/libvips/arithmetic/hist_find_indexed.c +++ b/libvips/arithmetic/hist_find_indexed.c @@ -117,8 +117,8 @@ histogram_new(VipsHistFindIndexed *indexed) !(hist->reg = vips_region_new(indexed->index_ready))) return NULL; - memset(hist->bins, 0, bands * hist->size * sizeof(double)); - memset(hist->init, 0, hist->size * sizeof(int)); + memset(hist->bins, 0, (size_t) bands * hist->size * sizeof(double)); + memset(hist->init, 0, (size_t) hist->size * sizeof(int)); return hist; } @@ -493,14 +493,11 @@ vips_hist_find_indexed_init(VipsHistFindIndexed *indexed) /** * vips_hist_find_indexed: (method) - * @in: input #VipsImage - * @index: input index #VipsImage + * @in: input [class@Image] + * @index: input index [class@Image] * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @combine: #VipsCombine, combine bins like this * * Make a histogram of @in, but use image @index to pick the bins. In other * words, element zero in @out contains the combination of all the pixels in @in @@ -516,10 +513,15 @@ vips_hist_find_indexed_init(VipsHistFindIndexed *indexed) * Normally, bins are summed, but you can use @combine to set other combine * modes. * - * This operation is useful in conjunction with vips_labelregions(). You can - * use it to find the centre of gravity of blobs in an image, for example. + * This operation is useful in conjunction with [method@Image.labelregions]. + * You can use it to find the centre of gravity of blobs in an image, for + * example. + * + * ::: tip "Optional arguments" + * * @combine: [enum@Combine], combine bins like this * - * See also: vips_hist_find(), vips_labelregions(). + * ::: seealso + * [method@Image.hist_find], [method@Image.labelregions]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/hist_find_ndim.c b/libvips/arithmetic/hist_find_ndim.c index 4e8838f9fc..620d88e624 100644 --- a/libvips/arithmetic/hist_find_ndim.c +++ b/libvips/arithmetic/hist_find_ndim.c @@ -333,11 +333,7 @@ vips_hist_find_ndim_init(VipsHistFindNDim *ndim) * vips_hist_find_ndim: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @bins: number of bins to make on each axis + * @...: `NULL`-terminated list of optional named arguments * * Make a one, two or three dimensional histogram of a 1, 2 or * 3 band image. Divide each axis into @bins bins .. ie. @@ -347,7 +343,11 @@ vips_hist_find_ndim_init(VipsHistFindNDim *ndim) * char and uchar images are cast to uchar before histogramming, all other * image types are cast to ushort. * - * See also: vips_hist_find(), vips_hist_find_indexed(). + * ::: tip "Optional arguments" + * * @bins: number of bins to make on each axis + * + * ::: seealso + * [method@Image.hist_find], [method@Image.hist_find_indexed]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/hough_circle.c b/libvips/arithmetic/hough_circle.c index 9bcbcfabb6..5d4481f0fd 100644 --- a/libvips/arithmetic/hough_circle.c +++ b/libvips/arithmetic/hough_circle.c @@ -234,7 +234,7 @@ vips_hough_circle_class_init(VipsHoughClass *class) _("Scale down dimensions by this factor"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsHoughCircle, scale), - 1, 100000, 3); + 1, 100000, 1); VIPS_ARG_INT(class, "min_radius", 120, _("Min radius"), @@ -263,13 +263,7 @@ vips_hough_circle_init(VipsHoughCircle *hough_circle) * vips_hough_circle: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @scale: scale down dimensions by this much - * * @min_radius: smallest radius to search for - * * @max_radius: largest radius to search for + * @...: `NULL`-terminated list of optional named arguments * * Find the circular Hough transform of an image. @in must be one band, with * non-zero pixels for image edges. @out is three-band, with the third channel @@ -287,7 +281,13 @@ vips_hough_circle_init(VipsHoughCircle *hough_circle) * @in, and reduce the number of radii tested (and hence the number of bands * int @out) by a factor of three as well. * - * See also: vips_hough_line(). + * ::: tip "Optional arguments" + * * @scale: scale down dimensions by this much + * * @min_radius: smallest radius to search for + * * @max_radius: largest radius to search for + * + * ::: seealso + * [method@Image.hough_line]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/hough_line.c b/libvips/arithmetic/hough_line.c index 01e82c20cd..20f6d6956b 100644 --- a/libvips/arithmetic/hough_line.c +++ b/libvips/arithmetic/hough_line.c @@ -169,12 +169,7 @@ vips_hough_line_init(VipsHoughLine *hough_line) * vips_hough_line: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @width: horizontal size of parameter space - * * @height: vertical size of parameter space + * @...: `NULL`-terminated list of optional named arguments * * Find the line Hough transform for @in. @in must have one band. @out has one * band, with pixels being the number of votes for that line. The X dimension @@ -184,7 +179,12 @@ vips_hough_line_init(VipsHoughLine *hough_line) * Use @width @height to set the size of the parameter space image (@out), * that is, how accurate the line determination should be. * - * See also: vips_hough_circle(). + * ::: tip "Optional arguments" + * * @width: horizontal size of parameter space + * * @height: vertical size of parameter space + * + * ::: seealso + * [method@Image.hough_circle]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/invert.c b/libvips/arithmetic/invert.c index 577c9200ba..22b3961ac3 100644 --- a/libvips/arithmetic/invert.c +++ b/libvips/arithmetic/invert.c @@ -191,15 +191,16 @@ vips_invert_init(VipsInvert *invert) * vips_invert: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * For unsigned formats, this operation calculates (max - @in), eg. (255 - * @in) for uchar. For signed and float formats, this operation calculates (-1 * @in). * - * For complex images, only the real part is inverted. See also vips_conj(). + * For complex images, only the real part is inverted. See also [method@Image.conj]. * - * See also: vips_linear(). + * ::: seealso + * [method@Image.linear]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/linear.c b/libvips/arithmetic/linear.c index b438d62eae..10e3308b22 100644 --- a/libvips/arithmetic/linear.c +++ b/libvips/arithmetic/linear.c @@ -503,11 +503,7 @@ vips_linearv(VipsImage *in, VipsImage **out, * @a: (array length=n): array of constants for multiplication * @b: (array length=n): array of constants for addition * @n: length of constant arrays - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @uchar: output uchar pixels + * @...: `NULL`-terminated list of optional named arguments * * Pass an image through a linear transform, ie. (@out = @in * @a + @b). Output * is float for integer input, double for double input, complex for @@ -521,7 +517,11 @@ vips_linearv(VipsImage *in, VipsImage **out, * element and the image only has a single band, the result is a many-band * image where each band corresponds to one array element. * - * See also: vips_linear1(), vips_add(). + * ::: tip "Optional arguments" + * * @uchar: output uchar pixels + * + * ::: seealso + * [method@Image.linear1], [method@Image.add]. * * Returns: 0 on success, -1 on error */ @@ -545,15 +545,15 @@ vips_linear(VipsImage *in, VipsImage **out, * @out: (out): output image * @a: constant for multiplication * @b: constant for addition - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @uchar: output uchar pixels + * Run [method@Image.linear] with a single constant. * - * Run vips_linear() with a single constant. + * ::: tip "Optional arguments" + * * @uchar: output uchar pixels * - * See also: vips_linear(). + * ::: seealso + * [method@Image.linear]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/math.c b/libvips/arithmetic/math.c index 1ac0f7e6ac..18832715d1 100644 --- a/libvips/arithmetic/math.c +++ b/libvips/arithmetic/math.c @@ -1,4 +1,4 @@ -/* VipsMath --- call various -lm functions (trig, log etc.) on images +/* VipsMath -- call various -lm functions (trig, log etc.) on images * * Copyright: 1990, N. Dessipris, based on im_powtra() * Author: Nicos Dessipris @@ -278,10 +278,10 @@ vips_mathv(VipsImage *in, VipsImage **out, VipsOperationMath math, va_list ap) /** * vips_math: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @math: math operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various functions in -lm, the maths library, on images. * @@ -290,7 +290,8 @@ vips_mathv(VipsImage *in, VipsImage **out, VipsOperationMath math, va_list ap) * * Non-complex images only. * - * See also: vips_math2(). + * ::: seealso + * [method@Image.math2]. * * Returns: 0 on success, -1 on error */ @@ -309,11 +310,11 @@ vips_math(VipsImage *in, VipsImage **out, VipsOperationMath math, ...) /** * vips_sin: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_SIN on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.SIN] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -332,11 +333,11 @@ vips_sin(VipsImage *in, VipsImage **out, ...) /** * vips_cos: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_COS on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.COS] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -355,11 +356,11 @@ vips_cos(VipsImage *in, VipsImage **out, ...) /** * vips_tan: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_TAN on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.TAN] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -378,11 +379,11 @@ vips_tan(VipsImage *in, VipsImage **out, ...) /** * vips_asin: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_ASIN on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.ASIN] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -401,11 +402,11 @@ vips_asin(VipsImage *in, VipsImage **out, ...) /** * vips_acos: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_ACOS on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.ACOS] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -424,11 +425,11 @@ vips_acos(VipsImage *in, VipsImage **out, ...) /** * vips_atan: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_ATAN on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.ATAN] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -447,11 +448,11 @@ vips_atan(VipsImage *in, VipsImage **out, ...) /** * vips_sinh: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_SINH on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.SINH] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -470,11 +471,11 @@ vips_sinh(VipsImage *in, VipsImage **out, ...) /** * vips_cosh: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_COSH on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.COSH] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -493,11 +494,11 @@ vips_cosh(VipsImage *in, VipsImage **out, ...) /** * vips_tanh: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_TANH on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.TANH] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -516,11 +517,11 @@ vips_tanh(VipsImage *in, VipsImage **out, ...) /** * vips_asinh: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_ASINH on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.ASINH] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -539,11 +540,11 @@ vips_asinh(VipsImage *in, VipsImage **out, ...) /** * vips_acosh: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_ACOSH on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.ACOSH] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -562,11 +563,11 @@ vips_acosh(VipsImage *in, VipsImage **out, ...) /** * vips_atanh: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_ATANH on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.ATANH] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -585,11 +586,11 @@ vips_atanh(VipsImage *in, VipsImage **out, ...) /** * vips_log: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_LOG on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.LOG] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -608,11 +609,11 @@ vips_log(VipsImage *in, VipsImage **out, ...) /** * vips_log10: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_LOG10 on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.LOG10] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -631,11 +632,11 @@ vips_log10(VipsImage *in, VipsImage **out, ...) /** * vips_exp: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_EXP on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.EXP] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -654,11 +655,11 @@ vips_exp(VipsImage *in, VipsImage **out, ...) /** * vips_exp10: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH_EXP10 on an image. See vips_math(). + * Perform [enum@Vips.OperationMath.EXP10] on an image. See [method@Image.math]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/math2.c b/libvips/arithmetic/math2.c index e139a1b371..9fcaecfef4 100644 --- a/libvips/arithmetic/math2.c +++ b/libvips/arithmetic/math2.c @@ -1,4 +1,4 @@ -/* math2.c --- 2ary math funcs +/* math2.c -- 2ary math funcs * * Copyright: 1990, N. Dessipris * @@ -258,12 +258,12 @@ vips_math2v(VipsImage *left, VipsImage *right, VipsImage **out, } /** - * vips_math2: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage + * vips_math2: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] * @math2: math operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates a 2-ary maths operation on a pair of images * and writes the result to @out. The images may have any @@ -283,10 +283,11 @@ vips_math2v(VipsImage *left, VipsImage *right, VipsImage **out, * * The two input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic), and that format is the + * [arithmetic](libvips-arithmetic.html)), and that format is the * result type. * - * See also: vips_math2_const(). + * ::: seealso + * [method@Image.math2_const]. * * Returns: 0 on success, -1 on error */ @@ -305,14 +306,14 @@ vips_math2(VipsImage *left, VipsImage *right, VipsImage **out, } /** - * vips_pow: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_pow: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_POW on a pair of images. See - * vips_math2(). + * Perform [enum@Vips.OperationMath2.POW] on a pair of images. See + * [method@Image.math2]. * * Returns: 0 on success, -1 on error */ @@ -330,14 +331,14 @@ vips_pow(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_wop: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_wop: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_WOP on a pair of images. See - * vips_math2(). + * Perform [enum@Vips.OperationMath2.WOP] on a pair of images. See + * [method@Image.math2]. * * Returns: 0 on success, -1 on error */ @@ -355,14 +356,14 @@ vips_wop(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_atan2: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_atan2: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_ATAN2 on a pair of images. See - * vips_math2(). + * Perform [enum@Vips.OperationMath2.ATAN2] on a pair of images. See + * [method@Image.math2]. * * Returns: 0 on success, -1 on error */ @@ -508,7 +509,7 @@ vips_math2_constv(VipsImage *in, VipsImage **out, * @math2: math operation to perform * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates various 2-ary maths operations on an image and * an array of constants and writes the result to @out. @@ -526,7 +527,8 @@ vips_math2_constv(VipsImage *in, VipsImage **out, * element and the image only has a single band, the result is a many-band * image where each band corresponds to one array element. * - * See also: vips_math2(), vips_math(). + * ::: seealso + * [method@Image.math2], [method@Image.math]. * * Returns: 0 on success, -1 on error */ @@ -546,14 +548,14 @@ vips_math2_const(VipsImage *in, VipsImage **out, /** * vips_pow_const: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_POW on an image and a constant. See - * vips_math2_const(). + * Perform [enum@Vips.OperationMath2.POW] on an image and a constant. See + * [method@Image.math2_const]. * * Returns: 0 on success, -1 on error */ @@ -573,14 +575,14 @@ vips_pow_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) /** * vips_wop_const: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_WOP on an image and a constant. See - * vips_math2_const(). + * Perform [enum@Vips.OperationMath2.WOP] on an image and a constant. See + * [method@Image.math2_const]. * * Returns: 0 on success, -1 on error */ @@ -600,14 +602,14 @@ vips_wop_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) /** * vips_atan2_const: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_ATAN2 on an image and a constant. See - * vips_math2_const(). + * Perform [enum@Vips.OperationMath2.ATAN2] on an image and a constant. See + * [method@Image.math2_const]. * * Returns: 0 on success, -1 on error */ @@ -631,10 +633,10 @@ vips_atan2_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) * @out: (out): output image * @math2: math operation to perform * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates various 2-ary maths operations on an image and - * a constant. See vips_math2_const(). + * a constant. See [method@Image.math2_const]. * * Returns: 0 on success, -1 on error */ @@ -654,13 +656,13 @@ vips_math2_const1(VipsImage *in, VipsImage **out, /** * vips_pow_const1: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_POW on an image and a constant. See - * vips_math2_const(). + * Perform [enum@Vips.OperationMath2.POW] on an image and a constant. See + * [method@Image.math2_const]. * * Returns: 0 on success, -1 on error */ @@ -680,13 +682,13 @@ vips_pow_const1(VipsImage *in, VipsImage **out, double c, ...) /** * vips_wop_const1: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_WOP on an image and a constant. See - * vips_math2_const(). + * Perform [enum@Vips.OperationMath2.WOP] on an image and a constant. See + * [method@Image.math2_const]. * * Returns: 0 on success, -1 on error */ @@ -706,13 +708,13 @@ vips_wop_const1(VipsImage *in, VipsImage **out, double c, ...) /** * vips_atan2_const1: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_MATH2_ATAN2 on an image and a constant. See - * vips_math2_const(). + * Perform [enum@Vips.OperationMath2.ATAN2] on an image and a constant. See + * [method@Image.math2_const]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/max.c b/libvips/arithmetic/max.c index ad27f45b60..212b9ff9bf 100644 --- a/libvips/arithmetic/max.c +++ b/libvips/arithmetic/max.c @@ -337,7 +337,7 @@ vips_max_stop(VipsStatistic *statistic, void *seq) TYPE m; \ \ for (i = 0; i < sz && values->n < values->size; i++) \ - if (!VIPS_ISNAN(p[i])) \ + if (!isnan(p[i])) \ vips_values_add(values, p[i], x + i / bands, y); \ m = values->value[0]; \ \ @@ -358,7 +358,7 @@ vips_max_stop(VipsStatistic *statistic, void *seq) for (i = 0; i < sz && values->n < values->size; i++) { \ TYPE mod2 = p[0] * p[0] + p[1] * p[1]; \ \ - if (!VIPS_ISNAN(mod2)) \ + if (!isnan(mod2)) \ vips_values_add(values, p[i], x + i / bands, y); \ \ p += 2; \ @@ -474,7 +474,7 @@ vips_max_class_init(VipsMaxClass *class) _("Number of maximum values to find"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsMax, size), - 1, 1000000, 10); + 1, 1000000, 1); VIPS_ARG_BOXED(class, "out_array", 6, _("Output array"), @@ -506,18 +506,9 @@ vips_max_init(VipsMax *max) /** * vips_max: (method) - * @in: input #VipsImage + * @in: input [class@Image] * @out: (out): output pixel maximum - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @x: horizontal position of maximum - * * @y: vertical position of maximum - * * @size: number of maxima to find - * * @out_array: return array of maximum values - * * @x_array: corresponding horizontal positions - * * @y_array: corresponding vertical positions + * @...: `NULL`-terminated list of optional named arguments * * This operation finds the maximum value in an image. * @@ -527,7 +518,7 @@ vips_max_init(VipsMax *max) * Equal values will be sorted by y then x. * * It operates on all - * bands of the input image: use vips_stats() if you need to find an + * bands of the input image: use [method@Image.stats] if you need to find an * maximum for each band. * * For complex images, this operation finds the maximum modulus. @@ -540,7 +531,16 @@ vips_max_init(VipsMax *max) * If there are more than @size maxima, the maxima returned will be a random * selection of the maxima in the image. * - * See also: vips_min(), vips_stats(). + * ::: tip "Optional arguments" + * * @x: horizontal position of maximum + * * @y: vertical position of maximum + * * @size: number of maxima to find + * * @out_array: return array of maximum values + * * @x_array: corresponding horizontal positions + * * @y_array: corresponding vertical positions + * + * ::: seealso + * [method@Image.min], [method@Image.stats]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/maxpair.c b/libvips/arithmetic/maxpair.c index 85112cdb14..88dc55c1f7 100644 --- a/libvips/arithmetic/maxpair.c +++ b/libvips/arithmetic/maxpair.c @@ -70,7 +70,7 @@ G_DEFINE_TYPE(VipsMaxpair, vips_maxpair, VIPS_TYPE_BINARY); TYPE *restrict q = (TYPE *) out; \ \ for (int x = 0; x < sz; x++) \ - q[x] = VIPS_FMAX(left[x], right[x]); \ + q[x] = fmax(left[x], right[x]); \ } static void @@ -161,15 +161,16 @@ vips_maxpair_init(VipsMaxpair *maxpair) } /** - * vips_maxpair: + * vips_maxpair: (method) * @left: input image * @right: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * For each pixel, pick the maximum of a pair of images. * - * See also: vips_minpair(). + * ::: seealso + * [method@Image.minpair]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/measure.c b/libvips/arithmetic/measure.c index 1a8e779a16..73045bf322 100644 --- a/libvips/arithmetic/measure.c +++ b/libvips/arithmetic/measure.c @@ -117,9 +117,9 @@ vips_measure_build(VipsObject *object) /* left/top/width/height default to the size of the image. */ if (!vips_object_argument_isset(object, "width")) - measure->width = vips_image_get_width(ready); + measure->width = vips_image_get_width(ready); // FIXME: Invalidates operation cache if (!vips_object_argument_isset(object, "height")) - measure->height = vips_image_get_height(ready); + measure->height = vips_image_get_height(ready); // FIXME: Invalidates operation cache /* How large are the patches we are to measure? */ @@ -159,8 +159,8 @@ vips_measure_build(VipsObject *object) * averages near zero (can get these if use * measure on IM_TYPE_LAB images). */ - if (dev * 5 > VIPS_FABS(avg) && - VIPS_FABS(avg) > 3) + if (dev * 5 > fabs(avg) && + fabs(avg) > 3) g_warning(_("%s: " "patch %d x %d, " "band %d: " @@ -257,14 +257,7 @@ vips_measure_init(VipsMeasure *measure) * @out: (out): array of measurements * @h: patches across chart * @v: patches down chart - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @left: area of image containing chart - * * @top: area of image containing chart - * * @width: area of image containing chart - * * @height: area of image containing chart + * @...: `NULL`-terminated list of optional named arguments * * Analyse a grid of colour patches, producing an array of patch averages. * The mask has a row for each measured patch and a column for each image @@ -276,7 +269,14 @@ vips_measure_init(VipsMeasure *measure) * @width, @height arguments to indicate the * position of the chart. * - * See also: vips_avg(), vips_deviate(). + * ::: tip "Optional arguments" + * * @left: area of image containing chart + * * @top: area of image containing chart + * * @width: area of image containing chart + * * @height: area of image containing chart + * + * ::: seealso + * [method@Image.avg], [method@Image.deviate]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/min.c b/libvips/arithmetic/min.c index 3b7800d453..411c07933a 100644 --- a/libvips/arithmetic/min.c +++ b/libvips/arithmetic/min.c @@ -337,7 +337,7 @@ vips_min_stop(VipsStatistic *statistic, void *seq) TYPE m; \ \ for (i = 0; i < sz && values->n < values->size; i++) \ - if (!VIPS_ISNAN(p[i])) \ + if (!isnan(p[i])) \ vips_values_add(values, p[i], x + i / bands, y); \ m = values->value[0]; \ \ @@ -358,7 +358,7 @@ vips_min_stop(VipsStatistic *statistic, void *seq) for (i = 0; i < sz && values->n < values->size; i++) { \ TYPE mod2 = p[0] * p[0] + p[1] * p[1]; \ \ - if (!VIPS_ISNAN(mod2)) \ + if (!isnan(mod2)) \ vips_values_add(values, p[i], x + i / bands, y); \ \ p += 2; \ @@ -474,7 +474,7 @@ vips_min_class_init(VipsMinClass *class) _("Number of minimum values to find"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsMin, size), - 1, 1000000, 10); + 1, 1000000, 1); VIPS_ARG_BOXED(class, "out_array", 6, _("Output array"), @@ -506,18 +506,9 @@ vips_min_init(VipsMin *min) /** * vips_min: (method) - * @in: input #VipsImage + * @in: input [class@Image] * @out: (out): output pixel minimum - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @x: horizontal position of minimum - * * @y: vertical position of minimum - * * @size: number of minima to find - * * @out_array: return array of minimum values - * * @x_array: corresponding horizontal positions - * * @y_array: corresponding vertical positions + * @...: `NULL`-terminated list of optional named arguments * * This operation finds the minimum value in an image. * @@ -527,7 +518,7 @@ vips_min_init(VipsMin *min) * Equal values will be sorted by y then x. * * It operates on all - * bands of the input image: use vips_stats() if you need to find an + * bands of the input image: use [method@Image.stats] if you need to find an * minimum for each band. * * For complex images, this operation finds the minimum modulus. @@ -541,7 +532,16 @@ vips_min_init(VipsMin *min) * If there are more than @size minima, the minima returned will be a random * selection of the minima in the image. * - * See also: vips_min(), vips_stats(). + * ::: tip "Optional arguments" + * * @x: horizontal position of minimum + * * @y: vertical position of minimum + * * @size: number of minima to find + * * @out_array: return array of minimum values + * * @x_array: corresponding horizontal positions + * * @y_array: corresponding vertical positions + * + * ::: seealso + * [method@Image.min], [method@Image.stats]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/minpair.c b/libvips/arithmetic/minpair.c index 6b4c653f20..e120f01cab 100644 --- a/libvips/arithmetic/minpair.c +++ b/libvips/arithmetic/minpair.c @@ -70,7 +70,7 @@ G_DEFINE_TYPE(VipsMinpair, vips_minpair, VIPS_TYPE_BINARY); TYPE *restrict q = (TYPE *) out; \ \ for (int x = 0; x < sz; x++) \ - q[x] = VIPS_FMIN(left[x], right[x]); \ + q[x] = fmin(left[x], right[x]); \ } static void @@ -161,15 +161,16 @@ vips_minpair_init(VipsMinpair *minpair) } /** - * vips_minpair: + * vips_minpair: (method) * @left: input image * @right: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * For each pixel, pick the minimum of a pair of images. * - * See also: vips_minpair(). + * ::: seealso + * [method@Image.minpair]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/multiply.c b/libvips/arithmetic/multiply.c index 9c35bc1812..f0f082ff97 100644 --- a/libvips/arithmetic/multiply.c +++ b/libvips/arithmetic/multiply.c @@ -205,11 +205,11 @@ vips_multiply_init(VipsMultiply *multiply) } /** - * vips_multiply: + * vips_multiply: (method) * @left: left-hand image * @right: right-hand image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates @left * @right and writes the result to @out. * @@ -223,67 +223,29 @@ vips_multiply_init(VipsMultiply *multiply) * * The two input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic), then the + * [arithmetic](libvips-arithmetic.html)), then the * following table is used to determine the output type: * - * - * Codestin Search App - * - * - * - * input type - * output type - * - * - * - * - * uchar - * ushort - * - * - * char - * short - * - * - * ushort - * uint - * - * - * short - * int - * - * - * uint - * uint - * - * - * int - * int - * - * - * float - * float - * - * - * double - * double - * - * - * complex - * complex - * - * - * double complex - * double complex - * - * - * - *
+ * ## [method@Image.multiply] type promotion + * + * | input type | output type | + * |----------------|----------------| + * | uchar | ushort | + * | char | short | + * | ushort | uint | + * | short | int | + * | uint | uint | + * | int | int | + * | float | float | + * | double | double | + * | complex | complex | + * | double complex | double complex | * * In other words, the output type is just large enough to hold the whole * range of possible values. * - * See also: vips_add(), vips_linear(). + * ::: seealso + * [method@Image.add], [method@Image.linear]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/profile.c b/libvips/arithmetic/profile.c index 91d837708f..0cd35de628 100644 --- a/libvips/arithmetic/profile.c +++ b/libvips/arithmetic/profile.c @@ -320,14 +320,15 @@ vips_profile_init(VipsProfile *profile) * @in: input image * @columns: (out): distances from top edge * @rows: (out): distances from left edge - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * vips_profile() searches inward from the edge of @in and finds the + * [method@Image.profile] searches inward from the edge of @in and finds the * first non-zero pixel. Pixels in @columns have the distance from the top edge * to the first non-zero pixel in that column, @rows has the distance from the * left edge to the first non-zero pixel in that row. * - * See also: vips_project(), vips_hist_find(). + * ::: seealso + * [method@Image.project], [method@Image.hist_find]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/project.c b/libvips/arithmetic/project.c index e2f7f240df..e6d5173c8c 100644 --- a/libvips/arithmetic/project.c +++ b/libvips/arithmetic/project.c @@ -109,8 +109,8 @@ histogram_new(VipsProject *project) !hist->row_sums) return NULL; - memset(hist->column_sums, 0, psize * in->Xsize); - memset(hist->row_sums, 0, psize * in->Ysize); + memset(hist->column_sums, 0, (size_t) psize * in->Xsize); + memset(hist->row_sums, 0, (size_t) psize * in->Ysize); return hist; } @@ -351,7 +351,7 @@ vips_project_init(VipsProject *project) * @in: input image * @columns: (out): sums of columns * @rows: (out): sums of rows - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Find the horizontal and vertical projections of an image, ie. the sum * of every row of pixels, and the sum of every column of pixels. The output @@ -359,7 +359,8 @@ vips_project_init(VipsProject *project) * * Non-complex images only. * - * See also: vips_hist_find(), vips_profile(). + * ::: seealso + * [method@Image.hist_find], [method@Image.profile]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/relational.c b/libvips/arithmetic/relational.c index 4c28c55b64..1ecbe0810e 100644 --- a/libvips/arithmetic/relational.c +++ b/libvips/arithmetic/relational.c @@ -1,4 +1,4 @@ -/* relational.c --- various relational operations +/* relational.c -- various relational operations * * Modified: * 26/7/93 JC @@ -265,12 +265,12 @@ vips_relationalv(VipsImage *left, VipsImage *right, VipsImage **out, } /** - * vips_relational: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage + * vips_relational: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] * @relational: relational operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various relational operations on pairs of images. * @@ -288,13 +288,15 @@ vips_relationalv(VipsImage *left, VipsImage *right, VipsImage **out, * * The two input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). * * To decide if pixels match exactly, that is have the same value in every - * band, use vips_bandbool() after this operation to AND or OR image bands - * together. + * band, use [method@Image.bandbool] after this operation to AND or OR image + * bands together. * - * See also: vips_boolean(), vips_bandbool(), vips_relational_const(). + * ::: seealso + * [method@Image.boolean], [method@Image.bandbool], + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -313,14 +315,14 @@ vips_relational(VipsImage *left, VipsImage *right, VipsImage **out, } /** - * vips_equal: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_equal: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_EQUAL on a pair of images. See - * vips_relational(). + * Perform [enum@Vips.OperationRelational.EQUAL] on a pair of images. See + * [method@Image.relational]. * * Returns: 0 on success, -1 on error */ @@ -339,14 +341,14 @@ vips_equal(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_notequal: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_notequal: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_NOTEQ on a pair of images. See - * vips_relational(). + * Perform [enum@Vips.OperationRelational.NOTEQ] on a pair of images. See + * [method@Image.relational]. * * Returns: 0 on success, -1 on error */ @@ -365,14 +367,14 @@ vips_notequal(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_more: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_more: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_MORE on a pair of images. See - * vips_relational(). + * Perform [enum@Vips.OperationRelational.MORE] on a pair of images. See + * [method@Image.relational]. * * Returns: 0 on success, -1 on error */ @@ -391,14 +393,14 @@ vips_more(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_moreeq: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_moreeq: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_MOREEQ on a pair of images. See - * vips_relational(). + * Perform [enum@Vips.OperationRelational.MOREEQ] on a pair of images. See + * [method@Image.relational]. * * Returns: 0 on success, -1 on error */ @@ -417,14 +419,14 @@ vips_moreeq(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_less: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_less: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_LESS on a pair of images. See - * vips_relational(). + * Perform [enum@Vips.OperationRelational.LESS] on a pair of images. See + * [method@Image.relational]. * * Returns: 0 on success, -1 on error */ @@ -443,14 +445,14 @@ vips_less(VipsImage *left, VipsImage *right, VipsImage **out, ...) } /** - * vips_lesseq: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_lesseq: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_LESSEQ on a pair of images. See - * vips_relational(). + * Perform [enum@Vips.OperationRelational.LESSEQ] on a pair of images. See + * [method@Image.relational]. * * Returns: 0 on success, -1 on error */ @@ -650,7 +652,7 @@ vips_relational_constv(VipsImage *in, VipsImage **out, * @relational: relational operation to perform * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various relational operations on an image and an array of * constants. @@ -664,7 +666,8 @@ vips_relational_constv(VipsImage *in, VipsImage **out, * element and the image only has a single band, the result is a many-band * image where each band corresponds to one array element. * - * See also: vips_boolean(), vips_relational(). + * ::: seealso + * [method@Image.boolean], [method@Image.relational]. * * Returns: 0 on success, -1 on error */ @@ -684,14 +687,14 @@ vips_relational_const(VipsImage *in, VipsImage **out, /** * vips_equal_const: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_EQUAL on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.EQUAL] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -711,14 +714,14 @@ vips_equal_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) /** * vips_notequal_const: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_NOTEQ on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.NOTEQ] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -739,14 +742,14 @@ vips_notequal_const(VipsImage *in, VipsImage **out, /** * vips_less_const: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_LESS on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.LESS] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -766,14 +769,14 @@ vips_less_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) /** * vips_lesseq_const: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_LESSEQ on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.LESSEQ] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -793,14 +796,14 @@ vips_lesseq_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) /** * vips_more_const: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_MORE on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.MORE] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -820,14 +823,14 @@ vips_more_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) /** * vips_moreeq_const: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage + * @in: input [class@Image] + * @out: (out): output [class@Image] * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_MOREEQ on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.MOREEQ] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -851,12 +854,13 @@ vips_moreeq_const(VipsImage *in, VipsImage **out, const double *c, int n, ...) * @out: (out): output image * @relational: relational operation to perform * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various relational operations on an image and a constant. See - * vips_relational_const(). + * [method@Image.relational_const]. * - * See also: vips_boolean(), vips_relational(). + * ::: seealso + * [method@Image.boolean], [method@Image.relational]. * * Returns: 0 on success, -1 on error */ @@ -879,10 +883,10 @@ vips_relational_const1(VipsImage *in, VipsImage **out, * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_EQUAL on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.EQUAL] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -905,10 +909,10 @@ vips_equal_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_NOTEQ on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.NOTEQ] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -931,10 +935,10 @@ vips_notequal_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_LESS on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.LESS] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -957,10 +961,10 @@ vips_less_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_LESSEQ on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.LESSEQ] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -983,10 +987,10 @@ vips_lesseq_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_MORE on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.MORE] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ @@ -1009,10 +1013,10 @@ vips_more_const1(VipsImage *in, VipsImage **out, double c, ...) * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_RELATIONAL_MOREEQ on an image and a constant. See - * vips_relational_const(). + * Perform [enum@Vips.OperationRelational.MOREEQ] on an image and a constant. See + * [method@Image.relational_const]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/remainder.c b/libvips/arithmetic/remainder.c index 58e8090d12..52f2f5ca34 100644 --- a/libvips/arithmetic/remainder.c +++ b/libvips/arithmetic/remainder.c @@ -113,7 +113,7 @@ vips_remainder_build(VipsObject *object) double a = p1[x]; \ double b = p2[x]; \ \ - q[x] = b ? a - b * VIPS_FLOOR(a / b) : -1; \ + q[x] = b ? a - b * floor(a / b) : -1; \ } \ } @@ -204,15 +204,15 @@ vips_remainder_init(VipsRemainder *remainder) } /** - * vips_remainder: - * @left: left-hand input #VipsImage - * @right: right-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * vips_remainder: (method) + * @left: left-hand input [class@Image] + * @right: right-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates @left % @right (remainder after integer division) * and writes the result to @out. The images may have any - * non-complex format. For float formats, vips_remainder() calculates @in1 - + * non-complex format. For float formats, [method@Image.remainder] calculates @in1 - * @in2 * floor (@in1 / @in2). * * If the images differ in size, the smaller image is enlarged to match the @@ -225,10 +225,11 @@ vips_remainder_init(VipsRemainder *remainder) * * The two input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic), and that format is the + * [arithmetic](libvips-arithmetic.html)), and that format is the * result type. * - * See also: vips_remainder_const(), vips_divide(), vips_round(). + * ::: seealso + * [method@Image.remainder_const], [method@Image.divide], [method@Image.round]. * * Returns: 0 on success, -1 on error */ @@ -390,13 +391,13 @@ vips_remainder_constv(VipsImage *in, VipsImage **out, * @out: (out): output image * @c: (array length=n): array of constants * @n: number of constants in @c - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates @in % @c (remainder after division by an * array of constants) * and writes the result to @out. * The image may have any - * non-complex format. For float formats, vips_remainder_const() calculates + * non-complex format. For float formats, [method@Image.remainder_const] calculates * @in - @c * floor (@in / @c). * * If the array of constants has just one element, that constant is used for @@ -406,7 +407,8 @@ vips_remainder_constv(VipsImage *in, VipsImage **out, * element and the image only has a single band, the result is a many-band * image where each band corresponds to one array element. * - * See also: vips_remainder(), vips_divide(), vips_round(). + * ::: seealso + * [method@Image.remainder], [method@Image.divide], [method@Image.round]. * * Returns: 0 on success, -1 on error */ @@ -429,13 +431,13 @@ vips_remainder_const(VipsImage *in, VipsImage **out, * @in: input image * @out: (out): output image * @c: constant - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates @in % @c (remainder after division by a * constant) * and writes the result to @out. * The image may have any - * non-complex format. For float formats, vips_remainder_const() calculates + * non-complex format. For float formats, [method@Image.remainder_const] calculates * @in - @c * floor (@in / @c). * * If the array of constants has just one element, that constant is used for @@ -445,7 +447,8 @@ vips_remainder_const(VipsImage *in, VipsImage **out, * element and the image only has a single band, the result is a many-band * image where each band corresponds to one array element. * - * See also: vips_remainder(), vips_divide(), vips_round(). + * ::: seealso + * [method@Image.remainder], [method@Image.divide], [method@Image.round]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/round.c b/libvips/arithmetic/round.c index 4dda0a1220..76e22e3965 100644 --- a/libvips/arithmetic/round.c +++ b/libvips/arithmetic/round.c @@ -1,4 +1,4 @@ -/* round.c --- various rounding operations +/* round.c -- various rounding operations * * 20/6/02 JC * - adapted from im_abs() @@ -127,13 +127,13 @@ vips_round_buffer(VipsArithmetic *arithmetic, switch (round->round) { case VIPS_OPERATION_ROUND_RINT: - SWITCH(VIPS_RINT); + SWITCH(rint); break; case VIPS_OPERATION_ROUND_CEIL: - SWITCH(VIPS_CEIL); + SWITCH(ceil); break; case VIPS_OPERATION_ROUND_FLOOR: - SWITCH(VIPS_FLOOR); + SWITCH(floor); break; default: @@ -199,10 +199,10 @@ vips_roundv(VipsImage *in, VipsImage **out, /** * vips_round: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @round: #VipsOperationRound rounding operation to perform - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @round: [class@Operation]Round rounding operation to perform + * @...: `NULL`-terminated list of optional named arguments * * Round to an integral value. * @@ -212,7 +212,8 @@ vips_roundv(VipsImage *in, VipsImage **out, * The format of @out is always the same as @in, so you may wish to cast to an * integer format afterwards. * - * See also: vips_cast() + * ::: seealso + * [method@Image.cast] * * Returns: 0 on success, -1 on error */ @@ -231,12 +232,12 @@ vips_round(VipsImage *in, VipsImage **out, VipsOperationRound round, ...) /** * vips_floor: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Round to an integral value with #VIPS_OPERATION_ROUND_FLOOR. See - * vips_round(). + * Round to an integral value with [enum@Vips.OperationRound.FLOOR]. See + * [method@Image.round]. * * Returns: 0 on success, -1 on error */ @@ -255,12 +256,12 @@ vips_floor(VipsImage *in, VipsImage **out, ...) /** * vips_ceil: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Round to an integral value with #VIPS_OPERATION_ROUND_CEIL. See - * vips_round(). + * Round to an integral value with [enum@Vips.OperationRound.CEIL]. See + * [method@Image.round]. * * Returns: 0 on success, -1 on error */ @@ -279,12 +280,12 @@ vips_ceil(VipsImage *in, VipsImage **out, ...) /** * vips_rint: (method) - * @in: input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Round to an integral value with #VIPS_OPERATION_ROUND_RINT. See - * vips_round(). + * Round to an integral value with [enum@Vips.OperationRound.RINT]. See + * [method@Image.round]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/sign.c b/libvips/arithmetic/sign.c index 47de9d2d7b..f580a7d167 100644 --- a/libvips/arithmetic/sign.c +++ b/libvips/arithmetic/sign.c @@ -187,14 +187,15 @@ vips_sign_init(VipsSign *sign) * vips_sign: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Finds the unit vector in the direction of the pixel value. For non-complex * images, it returns a signed char image with values -1, 0, and 1 for negative, * zero and positive pixels. For complex images, it returns a * complex normalised to length 1. * - * See also: vips_abs(). + * ::: seealso + * [method@Image.abs]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/stats.c b/libvips/arithmetic/stats.c index d85d983a78..e16681f087 100644 --- a/libvips/arithmetic/stats.c +++ b/libvips/arithmetic/stats.c @@ -14,7 +14,7 @@ 31/8/93 JC - forgot to init global max/min properly! sorry. 21/6/95 JC - - still did not init max and min correctly --- now fixed for good + - still did not init max and min correctly -- now fixed for good * 13/1/05 * - use 64 bit arithmetic @@ -160,14 +160,14 @@ vips_stats_build(VipsObject *object) row[COL_AVG] = row[COL_SUM] / pels; row[COL_SD] = sqrt( - VIPS_FABS(row[COL_SUM2] - + fabs(row[COL_SUM2] - (row[COL_SUM] * row[COL_SUM] / pels)) / (pels - 1)); } row0[COL_AVG] = row0[COL_SUM] / vals; row0[COL_SD] = sqrt( - VIPS_FABS(row0[COL_SUM2] - + fabs(row0[COL_SUM2] - (row0[COL_SUM] * row0[COL_SUM] / vals)) / (vals - 1)); @@ -454,15 +454,15 @@ vips_stats_init(VipsStats *stats) * vips_stats: (method) * @in: image to scan * @out: (out): image of statistics - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Find many image statistics in a single pass through the data. @out is a - * one-band #VIPS_FORMAT_DOUBLE image of at least 10 columns by n + 1 + * one-band [enum@Vips.BandFormat.DOUBLE] image of at least 10 columns by n + 1 * (where n is number of bands in image @in) * rows. Columns are statistics, and are, in order: minimum, maximum, sum, * sum of squares, mean, standard deviation, x coordinate of minimum, y * coordinate of minimum, x coordinate of maximum, y coordinate of maximum. - * Later versions of vips_stats() may add more columns. + * Later versions of [method@Image.stats] may add more columns. * * Row 0 has statistics for all * bands together, row 1 has stats for band 1, and so on. @@ -470,7 +470,8 @@ vips_stats_init(VipsStats *stats) * If there is more than one maxima or minima, one of them will be chosen at * random. * - * See also: vips_avg(), vips_min(). + * ::: seealso + * [method@Image.avg], [method@Image.min]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/subtract.c b/libvips/arithmetic/subtract.c index 09e4a944e2..b53968bfc8 100644 --- a/libvips/arithmetic/subtract.c +++ b/libvips/arithmetic/subtract.c @@ -184,11 +184,11 @@ vips_subtract_init(VipsSubtract *subtract) } /** - * vips_subtract: + * vips_subtract: (method) * @in1: input image * @in2: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates @in1 - @in2 and writes the result to @out. * @@ -202,67 +202,29 @@ vips_subtract_init(VipsSubtract *subtract) * * The two input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic), then the + * [arithmetic](libvips-arithmetic.html)), then the * following table is used to determine the output type: * - * - * Codestin Search App - * - * - * - * input type - * output type - * - * - * - * - * uchar - * short - * - * - * char - * short - * - * - * ushort - * int - * - * - * short - * int - * - * - * uint - * int - * - * - * int - * int - * - * - * float - * float - * - * - * double - * double - * - * - * complex - * complex - * - * - * double complex - * double complex - * - * - * - *
+ * ## [method@Image.subtract] type promotion + * + * | input type | output type | + * |----------------|----------------| + * | uchar | short | + * | char | short | + * | ushort | int | + * | short | int | + * | uint | int | + * | int | int | + * | float | float | + * | double | double | + * | complex | complex | + * | double complex | double complex | * * In other words, the output type is just large enough to hold the whole * range of possible values. * - * See also: vips_add(), vips_linear(). + * ::: seealso + * [method@Image.add], [method@Image.linear]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/sum.c b/libvips/arithmetic/sum.c index cb41e08297..1fdca1aa77 100644 --- a/libvips/arithmetic/sum.c +++ b/libvips/arithmetic/sum.c @@ -176,7 +176,7 @@ vips_sumv(VipsImage **in, VipsImage **out, int n, va_list ap) * @in: (array length=n): array of input images * @out: (out): output image * @n: number of input images - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation sums all images in @in and writes the result to @out. * @@ -190,67 +190,29 @@ vips_sumv(VipsImage **in, VipsImage **out, int n, va_list ap) * * The input images are cast up to the smallest common format (see table * Smallest common format in - * arithmetic), then the + * [arithmetic](libvips-arithmetic.html)), then the * following table is used to determine the output type: * - * - * Codestin Search App - * - * - * - * input type - * output type - * - * - * - * - * uchar - * uint - * - * - * char - * int - * - * - * ushort - * uint - * - * - * short - * int - * - * - * uint - * uint - * - * - * int - * int - * - * - * float - * float - * - * - * double - * double - * - * - * complex - * complex - * - * - * double complex - * double complex - * - * - * - *
+ * ## [func@Image.sum] type promotion + * + * | input type | output type | + * |----------------|----------------| + * | uchar | uint | + * | char | int | + * | ushort | uint | + * | short | int | + * | uint | uint | + * | int | int | + * | float | float | + * | double | double | + * | complex | complex | + * | double complex | double complex | * * In other words, the output type is just large enough to hold the whole * range of possible values. * - * See also: vips_add(). + * ::: seealso + * [method@Image.add]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/colour/CMYK2XYZ.c b/libvips/colour/CMYK2XYZ.c index 2d888b5bd5..8269a1d0e5 100644 --- a/libvips/colour/CMYK2XYZ.c +++ b/libvips/colour/CMYK2XYZ.c @@ -206,14 +206,14 @@ vips_CMYK2XYZ_init(VipsCMYK2XYZ *CMYK2XYZ) * vips_CMYK2XYZ: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn CMYK to XYZ. If the image has an embedded ICC profile this will be * used for the conversion. If there is no embedded profile, a generic * fallback profile will be used. * * Conversion is to D65 XYZ with relative intent. If you need more control - * over the process, use vips_icc_import() instead. + * over the process, use [method@Image.icc_import] instead. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/colour/HSV2sRGB.c b/libvips/colour/HSV2sRGB.c index 2555609760..0e22e8ab5b 100644 --- a/libvips/colour/HSV2sRGB.c +++ b/libvips/colour/HSV2sRGB.c @@ -63,7 +63,7 @@ vips_HSV2sRGB_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) float c, x, m; c = p[2] * p[1] / 255.0; - x = c * (1 - VIPS_FABS(fmod(p[0] / SIXTH_OF_CHAR, 2) - 1)); + x = c * (1 - fabsf(fmodf(p[0] / SIXTH_OF_CHAR, 2) - 1)); m = p[2] - c; if (p[0] < (int) SIXTH_OF_CHAR) { @@ -134,15 +134,16 @@ vips_HSV2sRGB_init(VipsHSV2sRGB *HSV2sRGB) * vips_HSV2sRGB: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Convert HSV to sRGB. * * HSV is a crude polar coordinate system for RGB images. It is provided for - * compatibility with other image processing systems. See vips_Lab2LCh() for a + * compatibility with other image processing systems. See [method@Image.Lab2LCh] for a * much better colour space. * - * See also: vips_sRGB2HSV(). + * ::: seealso + * [method@Image.sRGB2HSV]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/LCh2Lab.c b/libvips/colour/LCh2Lab.c index 091f4a4e23..2b1313be38 100644 --- a/libvips/colour/LCh2Lab.c +++ b/libvips/colour/LCh2Lab.c @@ -69,8 +69,8 @@ G_DEFINE_TYPE(VipsLCh2Lab, vips_LCh2Lab, VIPS_TYPE_COLOUR_TRANSFORM); void vips_col_Ch2ab(float C, float h, float *a, float *b) { - *a = C * cos(VIPS_RAD(h)); - *b = C * sin(VIPS_RAD(h)); + *a = C * cosf(VIPS_RAD(h)); + *b = C * sinf(VIPS_RAD(h)); } /* Process a buffer of data. @@ -125,7 +125,7 @@ vips_LCh2Lab_init(VipsLCh2Lab *LCh2Lab) * vips_LCh2Lab: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn LCh to Lab. * diff --git a/libvips/colour/LCh2UCS.c b/libvips/colour/LCh2UCS.c index eeb2fe669a..dfd7b167bf 100644 --- a/libvips/colour/LCh2UCS.c +++ b/libvips/colour/LCh2UCS.c @@ -92,9 +92,9 @@ vips_col_L2Lcmc(float L) float Lcmc; if (L < 16.0) - Lcmc = 1.744 * L; + Lcmc = 1.744F * L; else - Lcmc = 21.75 * log(L) + 0.3838 * L - 38.54; + Lcmc = 21.75F * logf(L) + 0.3838F * L - 38.54F; return Lcmc; } @@ -112,7 +112,7 @@ vips_col_C2Ccmc(float C) { float Ccmc; - Ccmc = 0.162 * C + 10.92 * log(0.638 + 0.07216 * C) + 4.907; + Ccmc = 0.162F * C + 10.92F * logf(0.638F + 0.07216F * C) + 4.907F; if (Ccmc < 0) Ccmc = 0; @@ -136,38 +136,38 @@ vips_col_Ch2hcmc(float C, float h) float hcmc; if (h < 49.1) { - k4 = 133.87; - k5 = -134.5; - k6 = -.924; - k7 = 1.727; - k8 = 340.0; + k4 = 133.87F; + k5 = -134.5F; + k6 = -.924F; + k7 = 1.727F; + k8 = 340.0F; } else if (h < 110.1) { - k4 = 11.78; - k5 = -12.7; - k6 = -.218; - k7 = 2.12; - k8 = 333.0; + k4 = 11.78F; + k5 = -12.7F; + k6 = -.218F; + k7 = 2.12F; + k8 = 333.0F; } else if (h < 269.6) { - k4 = 13.87; - k5 = 10.93; - k6 = 0.14; - k7 = 1.0; - k8 = -83.0; + k4 = 13.87F; + k5 = 10.93F; + k6 = 0.14F; + k7 = 1.0F; + k8 = -83.0F; } else { - k4 = .14; - k5 = 5.23; - k6 = .17; - k7 = 1.61; - k8 = 233.0; + k4 = .14F; + k5 = 5.23F; + k6 = .17F; + k7 = 1.61F; + k8 = 233.0F; } - P = cos(VIPS_RAD(k7 * h + k8)); - D = k4 + k5 * P * pow(VIPS_FABS(P), k6); + P = cosf(VIPS_RAD(k7 * h + k8)); + D = k4 + k5 * P * powf(fabsf(P), k6); g = C * C * C * C; - f = sqrt(g / (g + 1900.0)); + f = sqrtf(g / (g + 1900.0F)); hcmc = h + D * f; return hcmc; @@ -220,7 +220,7 @@ vips_LCh2CMC_init(VipsLCh2CMC *LCh2CMC) * vips_LCh2CMC: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn LCh to CMC. * @@ -233,7 +233,8 @@ vips_LCh2CMC_init(VipsLCh2CMC *LCh2CMC) * This operation generates CMC(1:1). For CMC(2:1), halve Lucs and double * Cucs. * - * See also: vips_CMC2LCh(). + * ::: seealso + * [method@Image.CMC2LCh]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/colour/Lab2LCh.c b/libvips/colour/Lab2LCh.c index f1df78b096..42b43ae7d0 100644 --- a/libvips/colour/Lab2LCh.c +++ b/libvips/colour/Lab2LCh.c @@ -92,7 +92,7 @@ void vips_col_ab2Ch(float a, float b, float *C, float *h) { *h = vips_col_ab2h(a, b); - *C = hypot(a, b); + *C = hypotf(a, b); } static void @@ -111,7 +111,7 @@ vips_Lab2LCh_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) p += 3; - C = sqrt(a * a + b * b); + C = sqrtf(a * a + b * b); h = vips_col_ab2h(a, b); q[0] = L; @@ -146,7 +146,7 @@ vips_Lab2LCh_init(VipsLab2LCh *Lab2LCh) * vips_Lab2LCh: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn Lab to LCh. * diff --git a/libvips/colour/Lab2LabQ.c b/libvips/colour/Lab2LabQ.c index 2059b45937..16694c20ab 100644 --- a/libvips/colour/Lab2LabQ.c +++ b/libvips/colour/Lab2LabQ.c @@ -102,14 +102,14 @@ vips_Lab2LabQ_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) lsbs = (intv & 0x3) << 6; /* 00000011 -> 11000000 */ q[0] = intv >> 2; /* drop bot 2 bits and store */ - fval = 8.0 * p[1]; /* do a */ - intv = VIPS_RINT(fval); + fval = 8.0F * p[1]; /* do a */ + intv = rintf(fval); intv = VIPS_CLIP(-1024, intv, 1023); lsbs |= (intv & 0x7) << 3; /* 00000111 -> 00111000 */ q[1] = intv >> 3; /* drop bot 3 bits & store */ - fval = 8.0 * p[2]; /* do b */ - intv = VIPS_RINT(fval); + fval = 8.0F * p[2]; /* do b */ + intv = rintf(fval); intv = VIPS_CLIP(-1024, intv, 1023); lsbs |= (intv & 0x7); q[2] = intv >> 3; @@ -159,11 +159,12 @@ vips_Lab2LabQ_init(VipsLab2LabQ *Lab2LabQ) * vips_Lab2LabQ: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert a Lab three-band float image to LabQ (#VIPS_CODING_LABQ). + * Convert a Lab three-band float image to LabQ ([enum@Vips.Coding.LABQ]). * - * See also: vips_LabQ2Lab(). + * ::: seealso + * [method@Image.LabQ2Lab]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/Lab2LabS.c b/libvips/colour/Lab2LabS.c index 76a526380a..4f1d99d785 100644 --- a/libvips/colour/Lab2LabS.c +++ b/libvips/colour/Lab2LabS.c @@ -103,11 +103,12 @@ vips_Lab2LabS_init(VipsLab2LabS *Lab2LabS) * vips_Lab2LabS: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn Lab to LabS, signed 16-bit int fixed point. * - * See also: vips_LabQ2Lab(). + * ::: seealso + * [method@Image.LabQ2Lab]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/Lab2XYZ.c b/libvips/colour/Lab2XYZ.c index 5d23c2cfd7..a9c374a047 100644 --- a/libvips/colour/Lab2XYZ.c +++ b/libvips/colour/Lab2XYZ.c @@ -203,15 +203,14 @@ vips_Lab2XYZ_init(VipsLab2XYZ *Lab2XYZ) * vips_Lab2XYZ: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @temp: #VipsArrayDouble, colour temperature + * @...: `NULL`-terminated list of optional named arguments * * Turn Lab to XYZ. The colour temperature defaults to D65, but can be * specified with @temp. * + * ::: tip "Optional arguments" + * * @temp: [struct@ArrayDouble], colour temperature + * * Returns: 0 on success, -1 on error */ int @@ -238,7 +237,8 @@ vips_Lab2XYZ(VipsImage *in, VipsImage **out, ...) * * Calculate XYZ from Lab, D65. * - * See also: vips_Lab2XYZ(). + * ::: seealso + * [method@Image.Lab2XYZ]. */ void vips_col_Lab2XYZ(float L, float a, float b, float *X, float *Y, float *Z) diff --git a/libvips/colour/LabQ2Lab.c b/libvips/colour/LabQ2Lab.c index 174cde10fc..50dee85ca6 100644 --- a/libvips/colour/LabQ2Lab.c +++ b/libvips/colour/LabQ2Lab.c @@ -92,17 +92,17 @@ vips_LabQ2Lab_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) */ l = ((unsigned char *) p)[0]; l = (l << 2) | (lsbs >> 6); - q[0] = (float) l * (100.0 / 1023.0); + q[0] = (float) l * (100.0F / 1023.0F); /* Build a. */ l = VIPS_LSHIFT_INT(p[1], 3) | ((lsbs >> 3) & 0x7); - q[1] = (float) l * 0.125; + q[1] = (float) l * 0.125F; /* And b. */ l = VIPS_LSHIFT_INT(p[2], 3) | (lsbs & 0x7); - q[2] = (float) l * 0.125; + q[2] = (float) l * 0.125F; p += 4; q += 3; @@ -145,11 +145,12 @@ vips_LabQ2Lab_init(VipsLabQ2Lab *LabQ2Lab) * vips_LabQ2Lab: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Unpack a LabQ (#VIPS_CODING_LABQ) image to a three-band float image. + * Unpack a LabQ ([enum@Vips.Coding.LABQ]) image to a three-band float image. * - * See also: vips_LabQ2Lab(), vips_LabQ2LabS(), vips_rad2float(). + * ::: seealso + * [method@Image.LabQ2Lab], [method@Image.LabQ2LabS], [method@Image.rad2float]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/LabQ2LabS.c b/libvips/colour/LabQ2LabS.c index 2978d28b11..b2e604de7e 100644 --- a/libvips/colour/LabQ2LabS.c +++ b/libvips/colour/LabQ2LabS.c @@ -124,11 +124,12 @@ vips_LabQ2LabS_init(VipsLabQ2LabS *LabQ2LabS) * vips_LabQ2LabS: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Unpack a LabQ (#VIPS_CODING_LABQ) image to a three-band short image. + * Unpack a LabQ ([enum@Vips.Coding.LABQ]) image to a three-band short image. * - * See also: vips_LabS2LabQ(), vips_LabQ2LabS(), vips_rad2float(). + * ::: seealso + * [method@Image.LabS2LabQ], [method@Image.LabQ2LabS], [method@Image.rad2float]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/LabQ2sRGB.c b/libvips/colour/LabQ2sRGB.c index 2847efc7c2..55a9335bb7 100644 --- a/libvips/colour/LabQ2sRGB.c +++ b/libvips/colour/LabQ2sRGB.c @@ -136,11 +136,11 @@ calcul_tables(int range, int *Y2v, float *v2Y) float v; if (f <= 0.0031308) - v = 12.92 * f; + v = 12.92F * f; else - v = (1.0 + 0.055) * pow(f, 1.0 / 2.4) - 0.055; + v = (1.0F + 0.055F) * powf(f, 1.0F / 2.4F) - 0.055F; - Y2v[i] = VIPS_RINT((range - 1) * v); + Y2v[i] = rintf((range - 1) * v); } /* Copy the final element. This is used in the piecewise linear @@ -152,9 +152,9 @@ calcul_tables(int range, int *Y2v, float *v2Y) float f = (float) i / (range - 1); if (f <= 0.04045) - v2Y[i] = f / 12.92; + v2Y[i] = f / 12.92F; else - v2Y[i] = pow((f + 0.055) / (1 + 0.055), 2.4); + v2Y[i] = powf((f + 0.055F) / (1 + 0.055F), 2.4F); } } @@ -222,7 +222,8 @@ vips_col_sRGB2scRGB_16(int r, int g, int b, float *R, float *G, float *B) * * Turn scRGB into XYZ. * - * See also: vips_scRGB2XYZ(). + * ::: seealso + * [method@Image.scRGB2XYZ]. */ int vips_col_scRGB2XYZ(float R, float G, float B, float *X, float *Y, float *Z) @@ -231,15 +232,15 @@ vips_col_scRGB2XYZ(float R, float G, float B, float *X, float *Y, float *Z) G *= SCALE; B *= SCALE; - *X = 0.4124 * R + - 0.3576 * G + - 0.1805 * B; - *Y = 0.2126 * R + - 0.7152 * G + - 0.0722 * B; - *Z = 0.0193 * R + - 0.1192 * G + - 0.9505 * B; + *X = 0.4124F * R + + 0.3576F * G + + 0.1805F * B; + *Y = 0.2126F * R + + 0.7152F * G + + 0.0722F * B; + *Z = 0.0193F * R + + 0.1192F * G + + 0.9505F * B; return 0; } @@ -255,7 +256,8 @@ vips_col_scRGB2XYZ(float R, float G, float B, float *X, float *Y, float *Z) * * Turn XYZ into scRGB. * - * See also: vips_XYZ2scRGB(). + * ::: seealso + * [method@Image.XYZ2scRGB]. */ int vips_col_XYZ2scRGB(float X, float Y, float Z, float *R, float *G, float *B) @@ -266,15 +268,15 @@ vips_col_XYZ2scRGB(float X, float Y, float Z, float *R, float *G, float *B) /* Use 6 decimal places of precision for the inverse matrix. */ - *R = 3.240625 * X + - -1.537208 * Y + - -0.498629 * Z; - *G = -0.968931 * X + - 1.875756 * Y + - 0.041518 * Z; - *B = 0.055710 * X + - -0.204021 * Y + - 1.056996 * Z; + *R = 3.240625F * X + + -1.537208F * Y + + -0.498629F * Z; + *G = -0.968931F * X + + 1.875756F * Y + + 0.041518F * Z; + *B = 0.055710F * X + + -0.204021F * Y + + 1.056996F * Z; return 0; } @@ -303,7 +305,7 @@ vips_col_scRGB2sRGB(int range, int *lut, * Don't use isnormal(), it is false for 0.0 and for subnormal * numbers. */ - if (VIPS_ISNAN(R) || VIPS_ISNAN(G) || VIPS_ISNAN(B)) { + if (isnan(R) || isnan(G) || isnan(B)) { *r = 0; *g = 0; *b = 0; @@ -337,19 +339,19 @@ vips_col_scRGB2sRGB(int range, int *lut, CLIP(0, Yf, maxval); Yi = (int) Yf; v = lut[Yi] + (lut[Yi + 1] - lut[Yi]) * (Yf - Yi); - *r = VIPS_RINT(v); + *r = rintf(v); Yf = G * maxval; CLIP(0, Yf, maxval); Yi = (int) Yf; v = lut[Yi] + (lut[Yi + 1] - lut[Yi]) * (Yf - Yi); - *g = VIPS_RINT(v); + *g = rintf(v); Yf = B * maxval; CLIP(0, Yf, maxval); Yi = (int) Yf; v = lut[Yi] + (lut[Yi + 1] - lut[Yi]) * (Yf - Yi); - *b = VIPS_RINT(v); + *b = rintf(v); if (og_ret) *og_ret = og; @@ -392,14 +394,15 @@ vips_col_scRGB2BW(int range, int *lut, float R, float G, float B, int Yi; float v; - /* CIE linear luminance function, see https://en.wikipedia.org/wiki/Grayscale#Colorimetric_(perceptual_luminance-preserving)_conversion_to_grayscale + /* CIE linear luminance function, see + * https://en.wikipedia.org/wiki/Grayscale#Colorimetric_(perceptual_luminance-preserving)_conversion_to_grayscale */ - Y = 0.2126 * R + 0.7152 * G + 0.0722 * B; + Y = 0.2126F * R + 0.7152F * G + 0.0722F * B; /* Y can be Nan. Throw those values out, they will break * our clipping. */ - if (VIPS_ISNAN(Y)) { + if (isnan(Y)) { *g = 0; return -1; @@ -417,7 +420,7 @@ vips_col_scRGB2BW(int range, int *lut, float R, float G, float B, CLIP(0, Yf, maxval); Yi = (int) Yf; v = lut[Yi] + (lut[Yi + 1] - lut[Yi]) * (Yf - Yi); - *g = VIPS_RINT(v); + *g = rintf(v); if (og_ret) *og_ret = og; @@ -454,7 +457,7 @@ build_tables(void *client) for (b = 0; b < 64; b++) { /* Scale to lab space. */ - float L = (l << 2) * (100.0 / 256.0); + float L = (l << 2) * (100.0F / 256.0F); float A = (signed char) (a << 2); float B = (signed char) (b << 2); float X, Y, Z; @@ -569,11 +572,12 @@ vips_LabQ2sRGB_init(VipsLabQ2sRGB *LabQ2sRGB) * vips_LabQ2sRGB: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Unpack a LabQ (#VIPS_CODING_LABQ) image to a three-band short image. + * Unpack a LabQ ([enum@Vips.Coding.LABQ]) image to a three-band short image. * - * See also: vips_LabS2LabQ(), vips_LabQ2sRGB(), vips_rad2float(). + * ::: seealso + * [method@Image.LabS2LabQ], [method@Image.LabQ2sRGB], [method@Image.rad2float]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/LabS2Lab.c b/libvips/colour/LabS2Lab.c index 33ce353fca..8aeae9be52 100644 --- a/libvips/colour/LabS2Lab.c +++ b/libvips/colour/LabS2Lab.c @@ -99,11 +99,12 @@ vips_LabS2Lab_init(VipsLabS2Lab *LabS2Lab) * vips_LabS2Lab: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Convert a LabS three-band signed short image to a three-band float image. * - * See also: vips_LabS2Lab(). + * ::: seealso + * [method@Image.LabS2Lab]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/LabS2LabQ.c b/libvips/colour/LabS2LabQ.c index 962dfbc7c3..89f90834ba 100644 --- a/libvips/colour/LabS2LabQ.c +++ b/libvips/colour/LabS2LabQ.c @@ -149,11 +149,12 @@ vips_LabS2LabQ_init(VipsLabS2LabQ *LabS2LabQ) * vips_LabS2LabQ: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Convert a LabS three-band signed short image to LabQ * - * See also: vips_LabQ2LabS(). + * ::: seealso + * [method@Image.LabQ2LabS]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/UCS2LCh.c b/libvips/colour/UCS2LCh.c index bda6630c07..6ec874c33f 100644 --- a/libvips/colour/UCS2LCh.c +++ b/libvips/colour/UCS2LCh.c @@ -141,7 +141,7 @@ make_hI(void) * vips_col_Lcmc2L: * @Lcmc: L cmc * - * Calculate L from Lcmc using a table. Call vips_col_make_tables_CMC() at + * Calculate L from Lcmc using a table. Call [func@col_make_tables_CMC] at * least once before using this function. * * Returns: L* @@ -151,11 +151,11 @@ vips_col_Lcmc2L(float Lcmc) { int known; - known = VIPS_FLOOR(Lcmc * 10.0); + known = floor(Lcmc * 10.0); known = VIPS_CLIP(0, known, 999); return LI[known] + - (LI[known + 1] - LI[known]) * (Lcmc * 10.0 - known); + (LI[known + 1] - LI[known]) * (Lcmc * 10.0F - known); } /** @@ -163,7 +163,7 @@ vips_col_Lcmc2L(float Lcmc) * @Ccmc: Ccmc * * Calculate C from Ccmc using a table. - * Call vips_col_make_tables_CMC() at + * Call [func@col_make_tables_CMC] at * least once before using this function. * * Returns: C. @@ -173,11 +173,11 @@ vips_col_Ccmc2C(float Ccmc) { int known; - known = VIPS_FLOOR(Ccmc * 10.0); + known = floor(Ccmc * 10.0); known = VIPS_CLIP(0, known, 2999); return CI[known] + - (CI[known + 1] - CI[known]) * (Ccmc * 10.0 - known); + (CI[known + 1] - CI[known]) * (Ccmc * 10.0F - known); } /** @@ -186,7 +186,7 @@ vips_col_Ccmc2C(float Ccmc) * @hcmc: Hue cmc (degrees) * * Calculate h from C and hcmc, using a table. - * Call vips_col_make_tables_CMC() at + * Call [func@col_make_tables_CMC] at * least once before using this function. * * Returns: h. @@ -202,7 +202,7 @@ vips_col_Chcmc2h(float C, float hcmc) r = (int) ((C + 1.0) / 2.0); r = VIPS_CLIP(0, r, 99); - known = VIPS_FLOOR(hcmc); + known = floor(hcmc); known = VIPS_CLIP(0, known, 359); return hI[r][known] + @@ -288,11 +288,12 @@ vips_CMC2LCh_init(VipsCMC2LCh *CMC2LCh) * vips_CMC2LCh: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn LCh to CMC. * - * See also: vips_LCh2CMC(). + * ::: seealso + * [method@Image.LCh2CMC]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/colour/XYZ2CMYK.c b/libvips/colour/XYZ2CMYK.c index a055bd240f..08ab51bfc8 100644 --- a/libvips/colour/XYZ2CMYK.c +++ b/libvips/colour/XYZ2CMYK.c @@ -217,12 +217,12 @@ vips_XYZ2CMYK_init(VipsXYZ2CMYK *XYZ2CMYK) * vips_XYZ2CMYK: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn XYZ to CMYK. * * Conversion is from D65 XYZ with relative intent. If you need more control - * over the process, use vips_icc_export() instead. + * over the process, use [method@Image.icc_export] instead. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/colour/XYZ2Lab.c b/libvips/colour/XYZ2Lab.c index 11be78dfb0..7f27809124 100644 --- a/libvips/colour/XYZ2Lab.c +++ b/libvips/colour/XYZ2Lab.c @@ -97,9 +97,9 @@ table_init(void *client) float Y = (double) i / QUANT_ELEMENTS; if (Y < 0.008856) - cbrt_table[i] = 7.787 * Y + (16.0 / 116.0); + cbrt_table[i] = 7.787F * Y + (16.0F / 116.0F); else - cbrt_table[i] = cbrt(Y); + cbrt_table[i] = cbrtf(Y); } return NULL; @@ -132,9 +132,9 @@ vips_col_XYZ2Lab_helper(VipsXYZ2Lab *XYZ2Lab, f = nZ - i; cbz = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]); - *L = 116.0 * cby - 16.0; - *a = 500.0 * (cbx - cby); - *b = 200.0 * (cby - cbz); + *L = 116.0F * cby - 16.0F; + *a = 500.0F * (cbx - cby); + *b = 200.0F * (cby - cbz); } /* Process a buffer of data. @@ -180,7 +180,8 @@ vips_XYZ2Lab_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) * * Calculate XYZ from Lab, D65. * - * See also: vips_XYZ2Lab(). + * ::: seealso + * [method@Image.XYZ2Lab]. */ void vips_col_XYZ2Lab(float X, float Y, float Z, float *L, float *a, float *b) @@ -256,15 +257,14 @@ vips_XYZ2Lab_init(VipsXYZ2Lab *XYZ2Lab) * vips_XYZ2Lab: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @temp: #VipsArrayDouble, colour temperature + * @...: `NULL`-terminated list of optional named arguments * * Turn XYZ to Lab, optionally specifying the colour temperature. @temp * defaults to D65. * + * ::: tip "Optional arguments" + * * @temp: [struct@ArrayDouble], colour temperature + * * Returns: 0 on success, -1 on error. */ int diff --git a/libvips/colour/XYZ2Yxy.c b/libvips/colour/XYZ2Yxy.c index c46e4a74a9..793680d650 100644 --- a/libvips/colour/XYZ2Yxy.c +++ b/libvips/colour/XYZ2Yxy.c @@ -72,8 +72,14 @@ vips_XYZ2Yxy_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) p += 3; - x = X / total; - y = Y / total; + if (total == 0.0) { + x = 0; + y = 0; + } + else { + x = X / total; + y = Y / total; + } q[0] = Y; q[1] = x; @@ -106,7 +112,7 @@ vips_XYZ2Yxy_init(VipsXYZ2Yxy *XYZ2Yxy) * vips_XYZ2Yxy: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn XYZ to Yxy. * diff --git a/libvips/colour/XYZ2scRGB.c b/libvips/colour/XYZ2scRGB.c index 3329d90aa6..0dfbc17f7d 100644 --- a/libvips/colour/XYZ2scRGB.c +++ b/libvips/colour/XYZ2scRGB.c @@ -47,20 +47,10 @@ #include "pcolour.h" -/* We can't use VipsColourCode as our parent class. We want to handle - * alpha ourselves. - */ - -typedef struct _VipsXYZ2scRGB { - VipsOperation parent_instance; - - VipsImage *in; - VipsImage *out; -} VipsXYZ2scRGB; +typedef VipsColourTransform VipsXYZ2scRGB; +typedef VipsColourTransformClass VipsXYZ2scRGBClass; -typedef VipsOperationClass VipsXYZ2scRGBClass; - -G_DEFINE_TYPE(VipsXYZ2scRGB, vips_XYZ2scRGB, VIPS_TYPE_OPERATION); +G_DEFINE_TYPE(VipsXYZ2scRGB, vips_XYZ2scRGB, VIPS_TYPE_COLOUR_TRANSFORM); /* We used to have the comment: @@ -79,12 +69,12 @@ G_DEFINE_TYPE(VipsXYZ2scRGB, vips_XYZ2scRGB, VIPS_TYPE_OPERATION); */ static void -vips_XYZ2scRGB_line(float *restrict q, float *restrict p, - int extra_bands, int width) +vips_XYZ2scRGB_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) { - int i, j; + float *restrict p = (float *) in[0]; + float *restrict q = (float *) out; - for (i = 0; i < width; i++) { + for (int i = 0; i < width; i++) { const float X = p[0]; const float Y = p[1]; const float Z = p[2]; @@ -100,125 +90,34 @@ vips_XYZ2scRGB_line(float *restrict q, float *restrict p, q[2] = B; q += 3; - - for (j = 0; j < extra_bands; j++) - q[j] = VIPS_CLIP(0, p[j] / 255.0, 1.0); - p += extra_bands; - q += extra_bands; } } -static int -vips_XYZ2scRGB_gen(VipsRegion *out_region, - void *seq, void *a, void *b, gboolean *stop) -{ - VipsRegion *ir = (VipsRegion *) seq; - VipsRect *r = &out_region->valid; - VipsImage *in = ir->im; - - int y; - - if (vips_region_prepare(ir, r)) - return -1; - - VIPS_GATE_START("vips_XYZ2scRGB: work"); - - for (y = 0; y < r->height; y++) { - float *p = (float *) - VIPS_REGION_ADDR(ir, r->left, r->top + y); - float *q = (float *) - VIPS_REGION_ADDR(out_region, r->left, r->top + y); - - vips_XYZ2scRGB_line(q, p, in->Bands - 3, r->width); - } - - VIPS_GATE_STOP("vips_XYZ2scRGB: work"); - - return 0; -} - -static int -vips_XYZ2scRGB_build(VipsObject *object) -{ - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); - VipsXYZ2scRGB *XYZ2scRGB = (VipsXYZ2scRGB *) object; - - VipsImage **t = (VipsImage **) vips_object_local_array(object, 2); - - VipsImage *in; - VipsImage *out; - - if (VIPS_OBJECT_CLASS(vips_XYZ2scRGB_parent_class)->build(object)) - return -1; - - in = XYZ2scRGB->in; - if (vips_check_bands_atleast(class->nickname, in, 3)) - return -1; - - if (vips_cast_float(in, &t[0], NULL)) - return -1; - in = t[0]; - - out = vips_image_new(); - if (vips_image_pipelinev(out, - VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) { - g_object_unref(out); - return -1; - } - out->Type = VIPS_INTERPRETATION_scRGB; - out->BandFmt = VIPS_FORMAT_FLOAT; - - if (vips_image_generate(out, - vips_start_one, vips_XYZ2scRGB_gen, vips_stop_one, - in, XYZ2scRGB)) { - g_object_unref(out); - return -1; - } - - g_object_set(object, "out", out, NULL); - - return 0; -} - static void vips_XYZ2scRGB_class_init(VipsXYZ2scRGBClass *class) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class); - - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class); object_class->nickname = "XYZ2scRGB"; object_class->description = _("transform XYZ to scRGB"); - object_class->build = vips_XYZ2scRGB_build; - - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - VIPS_ARG_IMAGE(class, "in", 1, - _("Input"), - _("Input image"), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET(VipsXYZ2scRGB, in)); - - VIPS_ARG_IMAGE(class, "out", 100, - _("Output"), - _("Output image"), - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET(VipsXYZ2scRGB, out)); + colour_class->process_line = vips_XYZ2scRGB_line; } static void vips_XYZ2scRGB_init(VipsXYZ2scRGB *XYZ2scRGB) { + VipsColour *colour = VIPS_COLOUR(XYZ2scRGB); + + colour->interpretation = VIPS_INTERPRETATION_scRGB; } /** * vips_XYZ2scRGB: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn XYZ to scRGB. * diff --git a/libvips/colour/Yxy2XYZ.c b/libvips/colour/Yxy2XYZ.c index b2664f6be1..480f6997c7 100644 --- a/libvips/colour/Yxy2XYZ.c +++ b/libvips/colour/Yxy2XYZ.c @@ -73,11 +73,11 @@ vips_Yxy2XYZ_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) if (x == 0.0 || y == 0.0) { - X = 0.0; - Z = 0.0; + X = 0.0F; + Z = 0.0F; } else { - double total; + float total; total = Y / y; X = x * total; @@ -117,7 +117,7 @@ vips_Yxy2XYZ_init(VipsYxy2XYZ *Yxy2XYZ) * vips_Yxy2XYZ: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn XYZ to Yxy. * diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index c42dcba8ef..de16cc1cde 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -46,113 +46,6 @@ #include "pcolour.h" -/** - * SECTION: colour - * @short_description: colour operators - * @stability: Stable - * @see_also: arithmetic - * @include: vips/vips.h - * - * These operators let you transform coordinates and images between colour - * spaces, calculate colour differences, and move - * to and from device spaces. - * - * All operations process colour from the first few bands and pass other bands - * through unaltered. This means you can operate on images with alpha channels - * safely. If you move to or from 16-bit RGB, any alpha channels are rescaled - * for you. - * - * Radiance images have four 8-bits bands and store 8 bits of R, G and B and - * another 8 bits of exponent, common to all channels. They are widely used in - * the HDR imaging community. - * - * The colour functions can be divided into three main groups. First, - * functions to transform images between the different colour spaces supported - * by VIPS: #VIPS_INTERPRETATION_sRGB, #VIPS_INTERPRETATION_scRGB, - * #VIPS_INTERPRETATION_B_W, - * #VIPS_INTERPRETATION_XYZ, #VIPS_INTERPRETATION_YXY, - * #VIPS_INTERPRETATION_LAB, - * #VIPS_INTERPRETATION_LCH, and - * #VIPS_INTERPRETATION_CMC. - * - * There are also a set of minor colourspaces which are one of the above in a - * slightly different format: - * #VIPS_INTERPRETATION_LAB, #VIPS_INTERPRETATION_LABQ, - * #VIPS_INTERPRETATION_LABS, #VIPS_INTERPRETATION_LCH, - * #VIPS_INTERPRETATION_RGB16, and #VIPS_INTERPRETATION_GREY16. - * - * Use vips_colourspace() to move an image to a - * target colourspace using the best sequence of colour transform operations. - * - * Secondly, there are a set of operations for - * calculating colour difference metrics. Finally, VIPS wraps LittleCMS and - * uses it to provide a set of operations for reading and writing images with - * ICC profiles. - * - * This figure shows how the VIPS colour spaces interconvert: - * - * - * - * - * - * The colour spaces supported by VIPS are: - * - * * #VIPS_INTERPRETATION_LAB -- CIELAB '76 colourspace with a D65 white. This - * uses three floats for each band, and bands have the obvious range. - * - * There are two - * variants, #VIPS_INTERPRETATION_LABQ and #VIPS_INTERPRETATION_LABS, which - * use ints to store values. These are less precise, but can be quicker to - * store and process. - * - * #VIPS_INTERPRETATION_LCH is the same, but with a*b* as polar coordinates. - * Hue is expressed in degrees. - * - * * #VIPS_INTERPRETATION_XYZ -- CIE XYZ. This uses three floats. - * See #VIPS_D75_X0 and friends for values for the ranges - * under various illuminants. - * - * #VIPS_INTERPRETATION_YXY is the same, but with little x and y. - * - * * #VIPS_INTERPRETATION_scRGB -- a linear colourspace with the sRGB - * primaries. This is useful if you need linear light and don't care - * much what the primaries are. - * - * Linearization is performed with the usual sRGB equations, see below. - * - * * #VIPS_INTERPRETATION_sRGB -- the standard sRGB colourspace, see: - * [wikipedia sRGB](http://en.wikipedia.org/wiki/SRGB). - * - * This uses three 8-bit values for each of RGB. - * - * #VIPS_INTERPRETATION_RGB16 is the same, but using three 16-bit values for - * RGB. - * - * #VIPS_INTERPRETATION_HSV is sRGB, but in polar coordinates. - * #VIPS_INTERPRETATION_LCH is much better, only use HSV if you have to. - * - * * #VIPS_INTERPRETATION_B_W -- a monochrome image, roughly G from sRGB. - * The grey value is - * calculated in linear #VIPS_INTERPRETATION_scRGB space with RGB ratios - * 0.2126, 0.7152, 0.0722 as defined by CIE 1931 linear luminance. - * - * #VIPS_INTERPRETATION_GREY16 is the same, but using 16 bits. - * - * * #VIPS_INTERPRETATION_CMC -- a colour space based on the CMC(1:1) - * colour difference measurement. This is a highly uniform colour space, - * and much better than CIELAB for expressing small differences. - * - * The CMC colourspace is described in "Uniform Colour Space Based on the - * CMC(l:c) Colour-difference Formula", M R Luo and B Rigg, Journal of the - * Society of Dyers and Colourists, vol 102, 1986. Distances in this - * colourspace approximate, within 10% or so, differences in the CMC(l:c) - * colour difference formula. - * - * You can calculate metrics like CMC(2:1) by scaling the spaces before - * finding differences. - * - */ - /* Areas under curves for Dxx. 2 degree observer. */ @@ -272,8 +165,6 @@ vips_colour_build(VipsObject *object) VipsImage **extra_bands; VipsImage *out; - int i; - #ifdef DEBUG printf("vips_colour_build: "); vips_object_print_name(object); @@ -284,11 +175,10 @@ vips_colour_build(VipsObject *object) return -1; if (colour->n > MAX_INPUT_IMAGES) { - vips_error(class->nickname, - "%s", _("too many input images")); + vips_error(class->nickname, "%s", _("too many input images")); return -1; } - for (i = 0; i < colour->n; i++) + for (int i = 0; i < colour->n; i++) if (vips_image_pio_input(colour->in[i])) return -1; @@ -308,7 +198,7 @@ vips_colour_build(VipsObject *object) VipsImage **new_in = (VipsImage **) vips_object_local_array(object, colour->n); - for (i = 0; i < colour->n; i++) { + for (int i = 0; i < colour->n; i++) { if (vips_check_bands_atleast(class->nickname, in[i], colour->input_bands)) return -1; @@ -353,38 +243,50 @@ vips_colour_build(VipsObject *object) if (vips_image_generate(out, vips_start_many, vips_colour_gen, vips_stop_many, in, colour)) { - g_object_unref(out); + VIPS_UNREF(out); return -1; } /* Reattach higher bands, if necessary. If we have more than one input * image, just use the first extra bands. */ - for (i = 0; i < colour->n; i++) + for (int i = 0; i < colour->n; i++) if (extra_bands[i]) { - VipsImage *t1, *t2; + VipsImage **t = (VipsImage **) vips_object_local_array(object, 3); + + double max_alpha_before = + vips_interpretation_max_alpha(extra_bands[i]->Type); + double max_alpha_after = + vips_interpretation_max_alpha(out->Type); + + VipsImage *alpha; - /* We can't just reattach the extra bands: they might - * be float (for example) and we might be trying to - * make a short image. Cast extra to match the body of - * the image. + alpha = extra_bands[i]; + + /* Rescale, if the alpha scale has changed. */ + if (max_alpha_before != max_alpha_after) { + if (vips_linear1(alpha, &t[0], + max_alpha_after / max_alpha_before, 0.0, NULL)) { + VIPS_UNREF(out); + return -1; + } + alpha = t[0]; + } - if (vips_cast(extra_bands[i], &t1, out->BandFmt, - NULL)) { - g_object_unref(out); + if (vips_cast(alpha, &t[1], out->BandFmt, NULL)) { + VIPS_UNREF(out); return -1; } + alpha = t[1]; - if (vips_bandjoin2(out, t1, &t2, - NULL)) { - g_object_unref(t1); - g_object_unref(out); + if (vips_bandjoin2(out, alpha, &t[2], NULL)) { + VIPS_UNREF(out); return -1; } g_object_unref(out); - g_object_unref(t1); - out = t2; + out = t[2]; + t[2] = NULL; break; } @@ -510,12 +412,12 @@ vips_colour_code_build(VipsObject *object) in = code->in; - /* If this is a LABQ and the coder wants uncoded, unpack. + /* We want labq, rad etc. all decoded (unlike colour_build). */ if (in && - in->Coding == VIPS_CODING_LABQ && - code->input_coding == VIPS_CODING_NONE) { - if (vips_LabQ2Lab(in, &t[0], NULL)) + code->input_coding == VIPS_CODING_NONE && + in->Coding != code->input_coding) { + if (vips_image_decode(in, &t[0])) return -1; in = t[0]; } diff --git a/libvips/colour/colourspace.c b/libvips/colour/colourspace.c index 9bca0895f0..850bad52a7 100644 --- a/libvips/colour/colourspace.c +++ b/libvips/colour/colourspace.c @@ -424,9 +424,9 @@ static VipsColourRoute vips_colour_routes[] = { * vips_colourspace_issupported: (method) * @image: input image * - * Test if @image is in a colourspace that vips_colourspace() can process. + * Test if @image is in a colourspace that [method@Image.colourspace] can process. * - * Returns: %TRUE if @image is in a supported colourspace. + * Returns: `TRUE` if @image is in a supported colourspace. */ gboolean vips_colourspace_issupported(const VipsImage *image) @@ -591,22 +591,23 @@ vips_colourspace_init(VipsColourspace *colourspace) * @in: input image * @out: (out): output image * @space: convert to this colour space - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @source_space: input colour space + * @...: `NULL`-terminated list of optional named arguments * * This operation looks at the interpretation field of @in (or uses * @source_space, if set) and runs * a set of colourspace conversion functions to move it to @space. * - * For example, given an image tagged as #VIPS_INTERPRETATION_YXY, running - * vips_colourspace() with @space set to #VIPS_INTERPRETATION_LAB will - * convert with vips_Yxy2XYZ() and vips_XYZ2Lab(). + * For example, given an image tagged as [enum@Vips.Interpretation.YXY], running + * [method@Image.colourspace] with @space set to + * [enum@Vips.Interpretation.LAB] will convert with [method@Image.Yxy2XYZ] + * and [method@Image.XYZ2Lab]. + * + * ::: tip "Optional arguments" + * * @source_space: input colour space * - * See also: vips_colourspace_issupported(), - * vips_image_guess_interpretation(). + * ::: seealso + * [method@Image.colourspace_issupported], + * [method@Image.guess_interpretation]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/dE00.c b/libvips/colour/dE00.c index 710ba4d0d0..4944680476 100644 --- a/libvips/colour/dE00.c +++ b/libvips/colour/dE00.c @@ -133,9 +133,9 @@ vips_col_dE00(float L1, float a1, float b1, */ double Ldb = (L1d + L2d) / 2; double Cdb = (C1d + C2d) / 2; - double hdb = VIPS_FABS(h1d - h2d) < 180 + double hdb = fabs(h1d - h2d) < 180 ? (h1d + h2d) / 2 - : VIPS_FABS(h1d + h2d - 360) / 2; + : fabs(h1d + h2d - 360) / 2; /* dtheta, RC */ @@ -162,7 +162,7 @@ vips_col_dE00(float L1, float a1, float b1, /* hue difference ... careful! */ - double dhd = VIPS_FABS(h1d - h2d) < 180 + double dhd = fabs(h1d - h2d) < 180 ? h1d - h2d : 360 - (h1d - h2d); @@ -247,11 +247,11 @@ vips_dE00_init(VipsdE00 *dE00) } /** - * vips_dE00: + * vips_dE00: (method) * @left: first input image * @right: second input image * @out: output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Calculate dE 00. * diff --git a/libvips/colour/dE76.c b/libvips/colour/dE76.c index f684579cce..f70f2a0bf8 100644 --- a/libvips/colour/dE76.c +++ b/libvips/colour/dE76.c @@ -76,7 +76,7 @@ vips_pythagoras(float L1, float a1, float b1, float L2, float a2, float b2) float da = a1 - a2; float db = b1 - b2; - return sqrt(dL * dL + da * da + db * db); + return sqrtf(dL * dL + da * da + db * db); } /* Find the difference between two buffers of LAB data. @@ -96,7 +96,7 @@ vips__pythagoras_line(VipsColour *colour, float da = p1[1] - p2[1]; float db = p1[2] - p2[2]; - q[x] = sqrt(dL * dL + da * da + db * db); + q[x] = sqrtf(dL * dL + da * da + db * db); p1 += 3; p2 += 3; @@ -124,11 +124,11 @@ vips_dE76_init(VipsdE76 *dE76) } /** - * vips_dE76: + * vips_dE76: (method) * @left: first input image * @right: second input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Calculate dE 76. * diff --git a/libvips/colour/dECMC.c b/libvips/colour/dECMC.c index 5507b9ed1a..fe4e422bbc 100644 --- a/libvips/colour/dECMC.c +++ b/libvips/colour/dECMC.c @@ -72,11 +72,11 @@ vips_dECMC_init(VipsdECMC *dECMC) } /** - * vips_dECMC: + * vips_dECMC: (method) * @left: first input image * @right: second input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Calculate dE CMC. The input images are transformed to CMC colour space and * the euclidean distance between corresponding pixels calculated. @@ -85,7 +85,8 @@ vips_dECMC_init(VipsdECMC *dECMC) * transform the two source images to CMC yourself, scale the channels * appropriately, and call this function. * - * See also: vips_colourspace() + * ::: seealso + * [method@Image.colourspace] * * Returns: 0 on success, -1 on error */ diff --git a/libvips/colour/float2rad.c b/libvips/colour/float2rad.c index 3ea4553864..22f8e3bbf5 100644 --- a/libvips/colour/float2rad.c +++ b/libvips/colour/float2rad.c @@ -228,11 +228,12 @@ vips_float2rad_init(VipsFloat2rad *float2rad) * vips_float2rad: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Convert a three-band float image to Radiance 32-bit packed format. * - * See also: vips_rad2float(), #VIPS_CODING_RAD, vips_LabQ2Lab(). + * ::: seealso + * [method@Image.rad2float], [enum@Vips.Coding.RAD], [method@Image.LabQ2Lab]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/icc_transform.c b/libvips/colour/icc_transform.c index 28ef2eae8d..dd84b575bd 100644 --- a/libvips/colour/icc_transform.c +++ b/libvips/colour/icc_transform.c @@ -106,9 +106,10 @@ * @VIPS_INTENT_RELATIVE: relative colorimetric rendering intent * @VIPS_INTENT_SATURATION: saturation rendering intent * @VIPS_INTENT_ABSOLUTE: absolute colorimetric rendering intent + * @VIPS_INTENT_AUTO: the rendering intent that the profile suggests * - * The rendering intent. #VIPS_INTENT_ABSOLUTE is best for - * scientific work, #VIPS_INTENT_RELATIVE is usually best for + * The rendering intent. [enum@Vips.Intent.ABSOLUTE] is best for + * scientific work, [enum@Vips.Intent.RELATIVE] is usually best for * accurate communication with other imaging libraries. */ @@ -117,8 +118,8 @@ * @VIPS_PCS_LAB: use CIELAB D65 as the Profile Connection Space * @VIPS_PCS_XYZ: use XYZ as the Profile Connection Space * - * Pick a Profile Connection Space for vips_icc_import() and - * vips_icc_export(). LAB is usually best, XYZ can be more convenient in some + * Pick a Profile Connection Space for [method@Image.icc_import] and + * [method@Image.icc_export]. LAB is usually best, XYZ can be more convenient in some * cases. */ @@ -159,6 +160,8 @@ typedef struct _VipsIcc { int depth; gboolean black_point_compensation; + VipsIntent selected_intent; + VipsBlob *in_blob; cmsHPROFILE in_profile; VipsBlob *out_blob; @@ -446,7 +449,7 @@ vips_icc_build(VipsObject *object) if (!(icc->trans = cmsCreateTransform( icc->in_profile, icc->in_icc_format, icc->out_profile, icc->out_icc_format, - icc->intent, flags))) + icc->selected_intent, flags))) return -1; if (VIPS_OBJECT_CLASS(vips_icc_parent_class)->build(object)) @@ -596,8 +599,8 @@ vips_image_is_profile_compatible(VipsImage *image, int profile_bands) * Don't set any errors since this is used to test compatibility. */ static cmsHPROFILE -vips_icc_load_profile_blob(VipsBlob *blob, - VipsImage *image, VipsIntent intent, int direction) +vips_icc_load_profile_blob(VipsIcc *icc, VipsBlob *blob, + VipsImage *image, int direction) { const void *data; size_t size; @@ -607,37 +610,57 @@ vips_icc_load_profile_blob(VipsBlob *blob, #ifdef DEBUG printf("loading %s profile, intent %s, from blob %p\n", direction == LCMS_USED_AS_INPUT ? _("input") : _("output"), - vips_enum_nick(VIPS_TYPE_INTENT, intent), + vips_enum_nick(VIPS_TYPE_INTENT, icc->intent), blob); #endif /*DEBUG*/ data = vips_blob_get(blob, &size); if (!(profile = cmsOpenProfileFromMem(data, size))) { - g_warning("%s", _("corrupt profile")); + g_warning("corrupt profile"); return NULL; } + icc->selected_intent = icc->intent; + if (icc->intent == VIPS_INTENT_AUTO || + !cmsIsIntentSupported(profile, icc->intent, direction)) { + cmsUInt32Number intent = cmsGetHeaderRenderingIntent(profile); + if (intent > VIPS_INTENT_ABSOLUTE) { + VIPS_FREEF(cmsCloseProfile, profile); + g_warning("corrupt profile"); + return NULL; + } + icc->selected_intent = (VipsIntent) intent; + } + + if (icc->intent != VIPS_INTENT_AUTO && + icc->selected_intent != icc->intent) + g_warning(_("fallback to suggested %s intent, as profile " + "does not support %s %s intent"), + vips_enum_nick(VIPS_TYPE_INTENT, icc->selected_intent), + vips_enum_nick(VIPS_TYPE_INTENT, icc->intent), + direction == LCMS_USED_AS_INPUT ? _("input") : _("output")); + #ifdef DEBUG vips_icc_print_profile("loaded from blob to make", profile); #endif /*DEBUG*/ if (!(info = vips_icc_info(cmsGetColorSpace(profile)))) { VIPS_FREEF(cmsCloseProfile, profile); - g_warning("%s", _("unsupported profile")); + g_warning("unsupported profile"); return NULL; } if (image && !vips_image_is_profile_compatible(image, info->bands)) { VIPS_FREEF(cmsCloseProfile, profile); - g_warning("%s", _("profile incompatible with image")); + g_warning("profile incompatible with image"); return NULL; } - if (!cmsIsIntentSupported(profile, intent, direction)) { + if (!cmsIsIntentSupported(profile, icc->selected_intent, direction)) { VIPS_FREEF(cmsCloseProfile, profile); g_warning(_("profile does not support %s %s intent"), - vips_enum_nick(VIPS_TYPE_INTENT, intent), + vips_enum_nick(VIPS_TYPE_INTENT, icc->selected_intent), direction == LCMS_USED_AS_INPUT ? _("input") : _("output")); return NULL; } @@ -654,8 +677,8 @@ vips_icc_verify_blob(VipsIcc *icc, VipsBlob **blob) { if (*blob) { VipsColourCode *code = (VipsColourCode *) icc; - cmsHPROFILE profile = vips_icc_load_profile_blob(*blob, - code->in, icc->intent, LCMS_USED_AS_INPUT); + cmsHPROFILE profile = vips_icc_load_profile_blob(icc, *blob, + code->in, LCMS_USED_AS_INPUT); if (!profile) { vips_area_unref((VipsArea *) *blob); @@ -670,11 +693,12 @@ vips_icc_verify_blob(VipsIcc *icc, VipsBlob **blob) /* Try to set the import profile. We read the input profile like this: * - * embedded filename action - * 0 0 image - * 1 0 image - * 0 1 file - * 1 1 image, then fall back to file + * | embedded | filename | action | + * |----------|----------|-------------------------------| + * | 0 | 0 | image | + * | 1 | 0 | image | + * | 0 | 1 | file | + * | 1 | 1 | image, then fall back to file | * * If averything fails, we fall back to one of our built-in profiles, * depending on the input image. @@ -883,18 +907,18 @@ decode_xyz(guint16 *fixed, float *xyz, int n) Z *= SCALE; /* Transform XYZ D50 to D65, chromatic adaption is done with the - * Bradford transformation. - * See: https://fujiwaratko.sakura.ne.jp/infosci/colorspace/bradford_e.html + * Bradford transformation. See: + * https://fujiwaratko.sakura.ne.jp/infosci/colorspace/bradford_e.html */ - xyz[0] = 0.955513 * X + - -0.023073 * Y + - 0.063309 * Z; - xyz[1] = -0.028325 * X + - 1.009942 * Y + - 0.021055 * Z; - xyz[2] = 0.012329 * X + - -0.020536 * Y + - 1.330714 * Z; + xyz[0] = 0.955513F * X + + -0.023073F * Y + + 0.063309F * Z; + xyz[1] = -0.028325F * X + + 1.009942F * Y + + 0.021055F * Z; + xyz[2] = 0.012329F * X + + -0.020536F * Y + + 1.330714F * Z; xyz += 3; fixed += 3; @@ -904,8 +928,7 @@ decode_xyz(guint16 *fixed, float *xyz, int n) /* Process a buffer of data. */ static void -vips_icc_import_line(VipsColour *colour, - VipsPel *out, VipsPel **in, int width) +vips_icc_import_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) { VipsIcc *icc = (VipsIcc *) colour; @@ -913,7 +936,7 @@ vips_icc_import_line(VipsColour *colour, float *q; int i; - /* Buffer of encoded 16-bit pixels we transform. + /* Transform to PCS pixels here. */ guint16 encoded[3 * PIXEL_BUFFER_SIZE]; @@ -1000,7 +1023,7 @@ vips_icc_export_build(VipsObject *object) if (!vips_object_argument_isset(object, "pcs") && code->in && code->in->Type == VIPS_INTERPRETATION_XYZ) - icc->pcs = VIPS_PCS_XYZ; + icc->pcs = VIPS_PCS_XYZ; // FIXME: Invalidates operation cache if (icc->pcs == VIPS_PCS_LAB) { cmsCIExyY white; @@ -1024,8 +1047,8 @@ vips_icc_export_build(VipsObject *object) } if (icc->out_blob && - !(icc->out_profile = vips_icc_load_profile_blob(icc->out_blob, - NULL, icc->intent, LCMS_USED_AS_OUTPUT))) { + !(icc->out_profile = vips_icc_load_profile_blob(icc, icc->out_blob, + NULL, LCMS_USED_AS_OUTPUT))) { vips_error(class->nickname, "%s", _("no output profile")); return -1; } @@ -1047,18 +1070,18 @@ encode_xyz(float *in, float *out, int n) float Z = in[2] / SCALE; /* Transform XYZ D65 to D50, chromatic adaption is done with the - * Bradford transformation. - * See: https://fujiwaratko.sakura.ne.jp/infosci/colorspace/bradford_e.html + * Bradford transformation. See: + * https://fujiwaratko.sakura.ne.jp/infosci/colorspace/bradford_e.html */ - out[0] = 1.047886 * X + - 0.022919 * Y + - -0.050216 * Z; - out[1] = 0.029582 * X + - 0.990484 * Y + - -0.017079 * Z; - out[2] = -0.009252 * X + - 0.015073 * Y + - 0.751678 * Z; + out[0] = 1.047886F * X + + 0.022919F * Y + + -0.050216F * Z; + out[1] = 0.029582F * X + + 0.990484F * Y + + -0.017079F * Z; + out[2] = -0.009252F * X + + 0.015073F * Y + + 0.751678F * Z; in += 3; out += 3; @@ -1075,7 +1098,7 @@ vips_icc_export_line_xyz(VipsColour *colour, VipsPel *q; int x; - /* Buffer of encoded float pixels we transform to device space. + /* Buffer of PCS pixels we transform to device space. */ float encoded[3 * PIXEL_BUFFER_SIZE]; @@ -1174,7 +1197,7 @@ vips_icc_transform_build(VipsObject *object) code->in && (code->in->Type == VIPS_INTERPRETATION_RGB16 || code->in->Type == VIPS_INTERPRETATION_GREY16)) - icc->depth = 16; + icc->depth = 16; // FIXME: Invalidates operation cache if (vips_icc_set_import(icc, transform->embedded, transform->input_profile_filename)) @@ -1188,8 +1211,8 @@ vips_icc_transform_build(VipsObject *object) } if (icc->out_blob) - icc->out_profile = vips_icc_load_profile_blob(icc->out_blob, - NULL, icc->intent, LCMS_USED_AS_OUTPUT); + icc->out_profile = vips_icc_load_profile_blob(icc, icc->out_blob, + NULL, LCMS_USED_AS_OUTPUT); if (!icc->out_profile) { vips_error(class->nickname, "%s", _("no output profile")); @@ -1273,7 +1296,8 @@ vips_icc_transform_init(VipsIccTransform *transform) * Transform an image from absolute to relative colorimetry using the * MediaWhitePoint stored in the ICC profile. * - * See also: vips_icc_transform(), vips_icc_import(). + * ::: seealso + * [method@Image.icc_transform], [method@Image.icc_import]. * * Returns: 0 on success, -1 on error. */ @@ -1414,36 +1438,36 @@ vips_icc_is_compatible_profile(VipsImage *image, * vips_icc_import: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @pcs: #VipsPCS, use XYZ or LAB PCS - * * @intent: #VipsIntent, transform with this intent - * * @black_point_compensation: %gboolean, enable black point compensation - * * @embedded: %gboolean, use profile embedded in input image - * * @input_profile: %gchararray, get the input profile from here + * Import an image from device space to D65 LAB with an ICC profile. * - * Import an image from device space to D65 LAB with an ICC profile. If @pcs is - * set to #VIPS_PCS_XYZ, use CIE XYZ PCS instead. + * If @pcs is set to [enum@Vips.PCS.XYZ], use CIE XYZ PCS instead. * * The input profile is searched for in three places: * - * 1. If @embedded is set, libvips will try to use any profile in the input - * image metadata. You can test for the presence of an embedded profile - * with vips_image_get_typeof() with #VIPS_META_ICC_NAME as an argument. - * This will return %GType 0 if there is no profile. + * 1. If @embedded is set, libvips will try to use any profile in the input + * image metadata. You can test for the presence of an embedded profile + * with [method@Image.get_typeof] with [const@META_ICC_NAME] as an + * argument. This will return [alias@GObject.Type] 0 if there is no profile. * - * 2. Otherwise, if @input_profile is set, libvips will try to load a - * profile from the named file. This can aslso be the name of one of the - * built-in profiles. + * 2. Otherwise, if @input_profile is set, libvips will try to load a + * profile from the named file. This can also be the name of one of the + * built-in profiles. * - * 3. Otherwise, libvips will try to pick a compatible profile from the set - * of built-in profiles. + * 3. Otherwise, libvips will try to pick a compatible profile from the set + * of built-in profiles. * * If @black_point_compensation is set, LCMS black point compensation is * enabled. * + * ::: tip "Optional arguments" + * * @pcs: [enum@PCS], use XYZ or LAB PCS + * * @intent: [enum@Intent], transform with this intent + * * @black_point_compensation: `gboolean`, enable black point compensation + * * @embedded: `gboolean`, use profile embedded in input image + * * @input_profile: `gchararray`, get the input profile from here + * * Returns: 0 on success, -1 on error. */ int @@ -1463,19 +1487,11 @@ vips_icc_import(VipsImage *in, VipsImage **out, ...) * vips_icc_export: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @pcs: #VipsPCS, use XYZ or LAB PCS - * * @intent: #VipsIntent, transform with this intent - * * @black_point_compensation: %gboolean, enable black point compensation - * * @output_profile: %gchararray, get the output profile from here - * * @depth: %gint, depth of output image in bits + * @...: `NULL`-terminated list of optional named arguments * * Export an image from D65 LAB to device space with an ICC profile. - * If @pcs is - * set to #VIPS_PCS_XYZ, use CIE XYZ PCS instead. + * + * If @pcs is set to [enum@Vips.PCS.XYZ], use CIE XYZ PCS instead. * If @output_profile is not set, use the embedded profile, if any. * If @output_profile is set, export with that and attach it to the output * image. @@ -1483,6 +1499,13 @@ vips_icc_import(VipsImage *in, VipsImage **out, ...) * If @black_point_compensation is set, LCMS black point compensation is * enabled. * + * ::: tip "Optional arguments" + * * @pcs: [enum@PCS], use XYZ or LAB PCS + * * @intent: [enum@Intent], transform with this intent + * * @black_point_compensation: `gboolean`, enable black point compensation + * * @output_profile: `gchararray`, get the output profile from here + * * @depth: `gint`, depth of output image in bits + * * Returns: 0 on success, -1 on error. */ int @@ -1503,45 +1526,45 @@ vips_icc_export(VipsImage *in, VipsImage **out, ...) * @in: input image * @out: (out): output image * @output_profile: get the output profile from here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @pcs: #VipsPCS, use XYZ or LAB PCS - * * @intent: #VipsIntent, transform with this intent - * * @black_point_compensation: %gboolean, enable black point compensation - * * @embedded: %gboolean, use profile embedded in input image - * * @input_profile: %gchararray, get the input profile from here - * * @depth: %gint, depth of output image in bits + * Transform an image with a pair of ICC profiles. * - * Transform an image with a pair of ICC profiles. The input image is moved to - * profile-connection space with the input profile and then to the output - * space with the output profile. + * The input image is moved to profile-connection space with the input + * profile and then to the output space with the output profile. * * The input profile is searched for in three places: * - * 1. If @embedded is set, libvips will try to use any profile in the input - * image metadata. You can test for the presence of an embedded profile - * with vips_image_get_typeof() with #VIPS_META_ICC_NAME as an argument. - * This will return %GType 0 if there is no profile. + * 1. If @embedded is set, libvips will try to use any profile in the input + * image metadata. You can test for the presence of an embedded profile + * with [method@Image.get_typeof] with [const@META_ICC_NAME] as an + * argument. This will return [alias@GObject.Type] 0 if there is no profile. * - * 2. Otherwise, if @input_profile is set, libvips will try to load a - * profile from the named file. This can aslso be the name of one of the - * built-in profiles. + * 2. Otherwise, if @input_profile is set, libvips will try to load a + * profile from the named file. This can also be the name of one of the + * built-in profiles. * - * 3. Otherwise, libvips will try to pick a compatible profile from the set - * of built-in profiles. + * 3. Otherwise, libvips will try to pick a compatible profile from the set + * of built-in profiles. * * If @black_point_compensation is set, LCMS black point compensation is * enabled. * * @depth defaults to 8, or 16 if @in is a 16-bit image. * - * The output image has the output profile attached to the #VIPS_META_ICC_NAME + * The output image has the output profile attached to the [const@META_ICC_NAME] * field. * - * Use vips_icc_import() and vips_icc_export() to do either the first or - * second half of this operation in isolation. + * Use [method@Image.icc_import] and [method@Image.icc_export] to do either + * the first or second half of this operation in isolation. + * + * ::: tip "Optional arguments" + * * @pcs: [enum@PCS], use XYZ or LAB PCS + * * @intent: [enum@Intent], transform with this intent + * * @black_point_compensation: `gboolean`, enable black point compensation + * * @embedded: `gboolean`, use profile embedded in input image + * * @input_profile: `gchararray`, get the input profile from here + * * @depth: `gint`, depth of output image in bits * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/meson.build b/libvips/colour/meson.build index 9e7278f0a9..23ac71dfb1 100644 --- a/libvips/colour/meson.build +++ b/libvips/colour/meson.build @@ -1,43 +1,43 @@ colour_sources = files( - 'profiles.c', - 'profile_load.c', - 'colour.c', 'CMYK2XYZ.c', - 'XYZ2CMYK.c', + 'colour.c', 'colourspace.c', - 'dE76.c', 'dE00.c', + 'dE76.c', 'dECMC.c', + 'float2rad.c', + 'HSV2sRGB.c', 'icc_transform.c', - 'Lab2XYZ.c', + 'Lab2LabQ.c', + 'Lab2LabS.c', 'Lab2LCh.c', + 'Lab2XYZ.c', + 'LabQ2Lab.c', + 'LabQ2LabS.c', + 'LabQ2sRGB.c', + 'LabS2Lab.c', + 'LabS2LabQ.c', 'LCh2Lab.c', 'LCh2UCS.c', + 'profile_load.c', + 'profiles.c', + 'rad2float.c', + 'scRGB2BW.c', + 'scRGB2sRGB.c', + 'scRGB2XYZ.c', + 'sRGB2HSV.c', + 'sRGB2scRGB.c', 'UCS2LCh.c', + 'XYZ2CMYK.c', 'XYZ2Lab.c', + 'XYZ2scRGB.c', 'XYZ2Yxy.c', 'Yxy2XYZ.c', - 'float2rad.c', - 'rad2float.c', - 'Lab2LabQ.c', - 'LabQ2Lab.c', - 'LabS2Lab.c', - 'Lab2LabS.c', - 'LabS2LabQ.c', - 'LabQ2LabS.c', - 'LabQ2sRGB.c', - 'sRGB2scRGB.c', - 'sRGB2HSV.c', - 'HSV2sRGB.c', - 'scRGB2XYZ.c', - 'scRGB2BW.c', - 'XYZ2scRGB.c', - 'scRGB2sRGB.c', -) + ) colour_headers = files( - 'profiles.h', 'pcolour.h', + 'profiles.h', ) libvips_sources += colour_sources diff --git a/libvips/colour/profile_load.c b/libvips/colour/profile_load.c index 3fa18f4ec2..e3e7090f71 100644 --- a/libvips/colour/profile_load.c +++ b/libvips/colour/profile_load.c @@ -171,13 +171,13 @@ vips_profile_load_init(VipsProfileLoad *load) * vips_profile_load: * @name: name of profile to load * @profile: (out): loaded profile - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Load a named profile. * * Profiles are loaded from four sources: * - * - The special name `"none"` means no profile. @profile will be %NULL in this + * - The special name `"none"` means no profile. @profile will be `NULL` in this * case. * * - @name can be the name of one of the ICC profiles embedded in libvips. diff --git a/libvips/colour/rad2float.c b/libvips/colour/rad2float.c index fb4bf0f72f..3a0c7624d5 100644 --- a/libvips/colour/rad2float.c +++ b/libvips/colour/rad2float.c @@ -204,11 +204,12 @@ vips_rad2float_init(VipsRad2float *rad2float) * vips_rad2float: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Unpack a RAD (#VIPS_CODING_RAD) image to a three-band float image. + * Unpack a RAD ([enum@Vips.Coding.RAD]) image to a three-band float image. * - * See also: vips_float2rad(), vips_LabQ2LabS(). + * ::: seealso + * [method@Image.float2rad], [method@Image.LabQ2LabS]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/sRGB2HSV.c b/libvips/colour/sRGB2HSV.c index b3f8d02f43..e1a6194f45 100644 --- a/libvips/colour/sRGB2HSV.c +++ b/libvips/colour/sRGB2HSV.c @@ -68,7 +68,7 @@ vips_sRGB2HSV_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) c_max = p[0]; c_min = p[1]; secondary_diff = p[1] - p[2]; - wrap_around_hue = 255.0; + wrap_around_hue = 255.0F; } else { /* Center blue. @@ -76,7 +76,7 @@ vips_sRGB2HSV_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) c_max = p[2]; c_min = VIPS_MIN(p[1], p[0]); secondary_diff = p[0] - p[1]; - wrap_around_hue = 170.0; + wrap_around_hue = 170.0F; } } else { @@ -86,7 +86,7 @@ vips_sRGB2HSV_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) c_max = p[0]; c_min = p[2]; secondary_diff = p[1] - p[2]; - wrap_around_hue = 0.0; + wrap_around_hue = 0.0F; } else { /* Center green @@ -94,7 +94,7 @@ vips_sRGB2HSV_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) c_max = p[1]; c_min = VIPS_MIN(p[2], p[0]); secondary_diff = p[2] - p[0]; - wrap_around_hue = 85.0; + wrap_around_hue = 85.0F; } } @@ -155,15 +155,16 @@ vips_sRGB2HSV_init(VipssRGB2HSV *sRGB2HSV) * vips_sRGB2HSV: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Convert to HSV. * * HSV is a crude polar coordinate system for RGB images. It is provided for - * compatibility with other image processing systems. See vips_Lab2LCh() for a + * compatibility with other image processing systems. See [method@Image.Lab2LCh] for a * much better colour space. * - * See also: vips_HSV2sRGB(), vips_Lab2LCh(). + * ::: seealso + * [method@Image.HSV2sRGB], [method@Image.Lab2LCh]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/sRGB2scRGB.c b/libvips/colour/sRGB2scRGB.c index 8b151de3ab..7d668d833f 100644 --- a/libvips/colour/sRGB2scRGB.c +++ b/libvips/colour/sRGB2scRGB.c @@ -19,6 +19,8 @@ * - look for RGB16 tag, not just ushort, for the 16-bit path * 24/11/17 lovell * - special path for 3 and 4 band images + * 16/4/25 + * - move on top of ColourCode */ /* @@ -60,31 +62,21 @@ #include "pcolour.h" -/* We can't use VipsColourCode as our parent class. We want to handle - * alpha ourselves so we can get 16 -> 8 bit conversion right. - */ - -typedef struct _VipssRGB2scRGB { - VipsOperation parent_instance; - - VipsImage *in; - VipsImage *out; -} VipssRGB2scRGB; +typedef VipsColourCode VipssRGB2scRGB; +typedef VipsColourCodeClass VipssRGB2scRGBClass; -typedef VipsOperationClass VipssRGB2scRGBClass; +G_DEFINE_TYPE(VipssRGB2scRGB, vips_sRGB2scRGB, VIPS_TYPE_COLOUR_CODE); -G_DEFINE_TYPE(VipssRGB2scRGB, vips_sRGB2scRGB, VIPS_TYPE_OPERATION); - -/* Convert a buffer of 8-bit pixels. - */ static void -vips_sRGB2scRGB_line_8(float *restrict q, VipsPel *restrict p, - int extra_bands, int width) +vips_sRGB2scRGB_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) { - int i, j; + if (colour->in[0]->BandFmt == VIPS_FORMAT_UCHAR) { + float *restrict q; + VipsPel *restrict p; - if (extra_bands == 0) { - for (i = 0; i < width; i++) { + q = (float *) out; + p = in[0]; + for (int i = 0; i < width; i++) { q[0] = vips_v2Y_8[p[0]]; q[1] = vips_v2Y_8[p[1]]; q[2] = vips_v2Y_8[p[2]]; @@ -93,44 +85,13 @@ vips_sRGB2scRGB_line_8(float *restrict q, VipsPel *restrict p, q += 3; } } - else if (extra_bands == 1) { - for (i = 0; i < width; i++) { - q[0] = vips_v2Y_8[p[0]]; - q[1] = vips_v2Y_8[p[1]]; - q[2] = vips_v2Y_8[p[2]]; - q[3] = p[3] / 255.0; - - p += 4; - q += 4; - } - } - else { - for (i = 0; i < width; i++) { - q[0] = vips_v2Y_8[p[0]]; - q[1] = vips_v2Y_8[p[1]]; - q[2] = vips_v2Y_8[p[2]]; + else if (colour->in[0]->BandFmt == VIPS_FORMAT_USHORT) { + float *restrict q; + unsigned short *restrict p; - p += 3; - q += 3; - - for (j = 0; j < extra_bands; j++) - q[j] = p[j] / 255.0; - p += extra_bands; - q += extra_bands; - } - } -} - -/* Convert a buffer of 16-bit pixels. - */ -static void -vips_sRGB2scRGB_line_16(float *restrict q, unsigned short *restrict p, - int extra_bands, int width) -{ - int i, j; - - if (extra_bands == 0) { - for (i = 0; i < width; i++) { + q = (float *) out; + p = (unsigned short *) in[0]; + for (int i = 0; i < width; i++) { q[0] = vips_v2Y_16[p[0]]; q[1] = vips_v2Y_16[p[1]]; q[2] = vips_v2Y_16[p[2]]; @@ -139,162 +100,47 @@ vips_sRGB2scRGB_line_16(float *restrict q, unsigned short *restrict p, q += 3; } } - else if (extra_bands == 1) { - for (i = 0; i < width; i++) { - q[0] = vips_v2Y_16[p[0]]; - q[1] = vips_v2Y_16[p[1]]; - q[2] = vips_v2Y_16[p[2]]; - q[3] = p[3] / 65535.0; - - p += 4; - q += 4; - } - } - else { - for (i = 0; i < width; i++) { - q[0] = vips_v2Y_16[p[0]]; - q[1] = vips_v2Y_16[p[1]]; - q[2] = vips_v2Y_16[p[2]]; - - p += 3; - q += 3; - - for (j = 0; j < extra_bands; j++) - q[j] = p[j] / 65535.0; - p += extra_bands; - q += extra_bands; - } - } -} - -static int -vips_sRGB2scRGB_gen(VipsRegion *out_region, - void *seq, void *a, void *b, gboolean *stop) -{ - VipsRegion *ir = (VipsRegion *) seq; - VipsRect *r = &out_region->valid; - VipsImage *in = ir->im; - - int y; - - if (vips_region_prepare(ir, r)) - return -1; - - VIPS_GATE_START("vips_sRGB2scRGB_gen: work"); - - if (in->BandFmt == VIPS_FORMAT_UCHAR) { - vips_col_make_tables_RGB_8(); - - for (y = 0; y < r->height; y++) { - VipsPel *p = VIPS_REGION_ADDR(ir, r->left, r->top + y); - float *q = (float *) - VIPS_REGION_ADDR(out_region, r->left, r->top + y); - - vips_sRGB2scRGB_line_8(q, p, in->Bands - 3, r->width); - } - } - else { - vips_col_make_tables_RGB_16(); - - for (y = 0; y < r->height; y++) { - VipsPel *p = VIPS_REGION_ADDR(ir, r->left, r->top + y); - float *q = (float *) - VIPS_REGION_ADDR(out_region, r->left, r->top + y); - - vips_sRGB2scRGB_line_16(q, (unsigned short *) p, - in->Bands - 3, r->width); - } - } - - VIPS_GATE_STOP("vips_sRGB2scRGB_gen: work"); - - return 0; + else + g_assert_not_reached(); } static int vips_sRGB2scRGB_build(VipsObject *object) { - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); - VipssRGB2scRGB *sRGB2scRGB = (VipssRGB2scRGB *) object; - - VipsImage **t = (VipsImage **) vips_object_local_array(object, 2); - - VipsImage *in; - VipsImage *out; - VipsBandFormat format; - - if (VIPS_OBJECT_CLASS(vips_sRGB2scRGB_parent_class)->build(object)) - return -1; - - in = sRGB2scRGB->in; - if (vips_check_bands_atleast(class->nickname, in, 3)) - return -1; - - // we are changing the gamma, so any profile on the image can no longer - // work (and will cause horrible problems in any downstream colour - // handling) - if (vips_copy(in, &t[0], NULL)) - return -1; - in = t[0]; - vips_image_remove(in, VIPS_META_ICC_NAME); + VipsColour *colour = (VipsColour *) object; + VipsColourCode *code = (VipsColourCode *) object; - format = in->Type == VIPS_INTERPRETATION_RGB16 - ? VIPS_FORMAT_USHORT - : VIPS_FORMAT_UCHAR; - if (in->BandFmt != format) { - if (vips_cast(in, &t[1], format, NULL)) - return -1; - in = t[1]; - } - - out = vips_image_new(); - if (vips_image_pipelinev(out, - VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) { - g_object_unref(out); - return -1; + // input image we want + if (vips_object_argument_isset(object, "in") && + code->in->Type == VIPS_INTERPRETATION_RGB16) { + vips_col_make_tables_RGB_16(); + code->input_format = VIPS_FORMAT_USHORT; } - out->Type = VIPS_INTERPRETATION_scRGB; - out->BandFmt = VIPS_FORMAT_FLOAT; - - if (vips_image_generate(out, - vips_start_one, vips_sRGB2scRGB_gen, vips_stop_one, - in, sRGB2scRGB)) { - g_object_unref(out); - return -1; + else { + vips_col_make_tables_RGB_8(); + code->input_format = VIPS_FORMAT_UCHAR; } + colour->input_bands = 3; - g_object_set(object, "out", out, NULL); + // output image we make + colour->interpretation = VIPS_INTERPRETATION_scRGB; + colour->format = VIPS_FORMAT_FLOAT; + colour->bands = 3; - return 0; + return VIPS_OBJECT_CLASS(vips_sRGB2scRGB_parent_class)->build(object); } static void vips_sRGB2scRGB_class_init(VipssRGB2scRGBClass *class) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class); - - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class); object_class->nickname = "sRGB2scRGB"; object_class->description = _("convert an sRGB image to scRGB"); object_class->build = vips_sRGB2scRGB_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - - VIPS_ARG_IMAGE(class, "in", 1, - _("Input"), - _("Input image"), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET(VipssRGB2scRGB, in)); - - VIPS_ARG_IMAGE(class, "out", 100, - _("Output"), - _("Output image"), - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET(VipssRGB2scRGB, out)); + colour_class->process_line = vips_sRGB2scRGB_line; } static void @@ -306,15 +152,15 @@ vips_sRGB2scRGB_init(VipssRGB2scRGB *sRGB2scRGB) * vips_sRGB2scRGB: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert an sRGB image to scRGB. The input image can be 8 or 16-bit. + * Convert an sRGB image to scRGB. * - * If the input image is tagged as #VIPS_INTERPRETATION_RGB16, any extra - * channels after RGB are divided by 256. Thus, scRGB alpha is - * always 0 - 255.99. + * RGB16 images are also handled. * - * See also: vips_scRGB2XYZ(), vips_scRGB2sRGB(), vips_rad2float(). + * ::: seealso + * [method@Image.scRGB2XYZ], [method@Image.scRGB2sRGB], + * [method@Image.rad2float]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/scRGB2BW.c b/libvips/colour/scRGB2BW.c index f075d0f57f..2f108d9fc2 100644 --- a/libvips/colour/scRGB2BW.c +++ b/libvips/colour/scRGB2BW.c @@ -2,6 +2,8 @@ * * 17/4/15 * - from scRGB2BW.c + * 16/4/25 + * - move on top of ColourCode */ /* @@ -43,178 +45,99 @@ #include "pcolour.h" -/* We can't use VipsColourCode as our parent class. We want to handle - * alpha ourselves so we can get 16 -> 8 bit conversion right. - */ - typedef struct _VipsscRGB2BW { - VipsOperation parent_instance; + VipsColourCode parent_instance; - VipsImage *in; - VipsImage *out; int depth; } VipsscRGB2BW; -typedef VipsOperationClass VipsscRGB2BWClass; +typedef VipsColourCodeClass VipsscRGB2BWClass; -G_DEFINE_TYPE(VipsscRGB2BW, vips_scRGB2BW, VIPS_TYPE_OPERATION); +G_DEFINE_TYPE(VipsscRGB2BW, vips_scRGB2BW, VIPS_TYPE_COLOUR_CODE); -/* Process a buffer of data. - */ static void -vips_scRGB2BW_line_8(VipsPel *restrict q, float *restrict p, - int extra_bands, int width) +vips_scRGB2BW_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) { - int i, j; + VipsscRGB2BW *scRGB2BW = (VipsscRGB2BW *) colour; - for (i = 0; i < width; i++) { - float R = p[0]; - float G = p[1]; - float B = p[2]; + if (scRGB2BW->depth == 16) { + unsigned short *restrict q; + float *restrict p; - int g; - int og; + q = (unsigned short *) out; + p = (float *) in[0]; + for (int i = 0; i < width; i++) { + const float R = p[0]; + const float G = p[1]; + const float B = p[2]; - vips_col_scRGB2BW_8(R, G, B, &g, &og); + int g; + int og; + vips_col_scRGB2BW_16(R, G, B, &g, &og); - p += 3; + q[0] = g; - q[0] = g; - - q += 1; - - for (j = 0; j < extra_bands; j++) - q[j] = VIPS_CLIP(0, (int) (p[j] * 255.0), UCHAR_MAX); - p += extra_bands; - q += extra_bands; + p += 3; + q += 1; + } } -} - -static void -vips_scRGB2BW_line_16(unsigned short *restrict q, float *restrict p, - int extra_bands, int width) -{ - int i, j; - - for (i = 0; i < width; i++) { - float R = p[0]; - float G = p[1]; - float B = p[2]; - - int g; - int og; - - vips_col_scRGB2BW_16(R, G, B, &g, &og); - - p += 3; - - q[0] = g; - - q += 1; - - for (j = 0; j < extra_bands; j++) - q[j] = VIPS_CLIP(0, (int) (p[j] * 65535.0), USHRT_MAX); - p += extra_bands; - q += extra_bands; + else { + unsigned char *restrict q; + float *restrict p; + + q = (unsigned char *) out; + p = (float *) in[0]; + for (int i = 0; i < width; i++) { + const float R = p[0]; + const float G = p[1]; + const float B = p[2]; + + int g; + int og; + vips_col_scRGB2BW_8(R, G, B, &g, &og); + + q[0] = g; + + p += 3; + q += 1; + } } } -static int -vips_scRGB2BW_gen(VipsRegion *out_region, - void *seq, void *a, void *b, gboolean *stop) -{ - VipsRegion *ir = (VipsRegion *) seq; - VipsscRGB2BW *scRGB2BW = (VipsscRGB2BW *) b; - VipsRect *r = &out_region->valid; - VipsImage *in = ir->im; - - int y; - - if (vips_region_prepare(ir, r)) - return -1; - - VIPS_GATE_START("vips_scRGB2BW_gen: work"); - - for (y = 0; y < r->height; y++) { - float *p = (float *) - VIPS_REGION_ADDR(ir, r->left, r->top + y); - VipsPel *q = (VipsPel *) - VIPS_REGION_ADDR(out_region, r->left, r->top + y); - - if (scRGB2BW->depth == 16) - vips_scRGB2BW_line_16((unsigned short *) q, p, - in->Bands - 3, r->width); - else - vips_scRGB2BW_line_8(q, p, - in->Bands - 3, r->width); - } - - VIPS_GATE_STOP("vips_scRGB2BW_gen: work"); - - return 0; -} - static int vips_scRGB2BW_build(VipsObject *object) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); VipsscRGB2BW *scRGB2BW = (VipsscRGB2BW *) object; + VipsColour *colour = (VipsColour *) object; + VipsColourCode *code = (VipsColourCode *) object; - VipsImage **t = (VipsImage **) vips_object_local_array(object, 2); + // input image we want - VipsImage *in; - VipsBandFormat format; - VipsInterpretation interpretation; - VipsImage *out; + code->input_format = VIPS_FORMAT_FLOAT; + colour->input_bands = 3; - if (VIPS_OBJECT_CLASS(vips_scRGB2BW_parent_class)->build(object)) - return -1; - - in = scRGB2BW->in; - if (vips_check_bands_atleast(class->nickname, in, 3)) - return -1; + // output image we make switch (scRGB2BW->depth) { case 16: - interpretation = VIPS_INTERPRETATION_GREY16; - format = VIPS_FORMAT_USHORT; + colour->interpretation = VIPS_INTERPRETATION_GREY16; + colour->format = VIPS_FORMAT_USHORT; break; case 8: - interpretation = VIPS_INTERPRETATION_B_W; - format = VIPS_FORMAT_UCHAR; + colour->interpretation = VIPS_INTERPRETATION_B_W; + colour->format = VIPS_FORMAT_UCHAR; break; default: - vips_error(class->nickname, - "%s", _("depth must be 8 or 16")); + vips_error(class->nickname, "%s", _("depth must be 8 or 16")); return -1; } - if (vips_cast_float(in, &t[0], NULL)) - return -1; - in = t[0]; + colour->bands = 1; - out = vips_image_new(); - if (vips_image_pipelinev(out, - VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) { - g_object_unref(out); - return -1; - } - out->Type = interpretation; - out->BandFmt = format; - out->Bands = in->Bands - 2; - - if (vips_image_generate(out, - vips_start_one, vips_scRGB2BW_gen, vips_stop_one, - in, scRGB2BW)) { - g_object_unref(out); - return -1; - } - - g_object_set(object, "out", out, NULL); - - return 0; + return VIPS_OBJECT_CLASS(vips_scRGB2BW_parent_class)->build(object); } static void @@ -222,7 +145,7 @@ vips_scRGB2BW_class_init(VipsscRGB2BWClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class); + VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class); gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -231,19 +154,7 @@ vips_scRGB2BW_class_init(VipsscRGB2BWClass *class) object_class->description = _("convert scRGB to BW"); object_class->build = vips_scRGB2BW_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - - VIPS_ARG_IMAGE(class, "in", 1, - _("Input"), - _("Input image"), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET(VipsscRGB2BW, in)); - - VIPS_ARG_IMAGE(class, "out", 100, - _("Output"), - _("Output image"), - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET(VipsscRGB2BW, out)); + colour_class->process_line = vips_scRGB2BW_line; VIPS_ARG_INT(class, "depth", 130, _("Depth"), @@ -263,18 +174,16 @@ vips_scRGB2BW_init(VipsscRGB2BW *scRGB2BW) * vips_scRGB2BW: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @depth: depth of output image in bits + * @...: `NULL`-terminated list of optional named arguments * * Convert an scRGB image to greyscale. Set @depth to 16 to get 16-bit output. * - * If @depth is 16, any extra channels after RGB are - * multiplied by 256. + * ::: tip "Optional arguments" + * * @depth: depth of output image in bits * - * See also: vips_LabS2LabQ(), vips_sRGB2scRGB(), vips_rad2float(). + * ::: seealso + * [method@Image.LabS2LabQ], [method@Image.sRGB2scRGB], + * [method@Image.rad2float]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/colour/scRGB2XYZ.c b/libvips/colour/scRGB2XYZ.c index fe5b6a187d..61ca9db732 100644 --- a/libvips/colour/scRGB2XYZ.c +++ b/libvips/colour/scRGB2XYZ.c @@ -49,28 +49,18 @@ #include "pcolour.h" -/* We can't use VipsColourCode as our parent class. We want to handle - * alpha ourselves. - */ - -typedef struct _VipsscRGB2XYZ { - VipsOperation parent_instance; - - VipsImage *in; - VipsImage *out; -} VipsscRGB2XYZ; +typedef VipsColourTransform VipsscRGB2XYZ; +typedef VipsColourTransformClass VipsscRGB2XYZClass; -typedef VipsOperationClass VipsscRGB2XYZClass; - -G_DEFINE_TYPE(VipsscRGB2XYZ, vips_scRGB2XYZ, VIPS_TYPE_OPERATION); +G_DEFINE_TYPE(VipsscRGB2XYZ, vips_scRGB2XYZ, VIPS_TYPE_COLOUR_TRANSFORM); static void -vips_scRGB2XYZ_line(float *restrict q, float *restrict p, - int extra_bands, int width) +vips_scRGB2XYZ_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) { - int i, j; + float *restrict p = (float *) in[0]; + float *restrict q = (float *) out; - for (i = 0; i < width; i++) { + for (int i = 0; i < width; i++) { const float R = p[0] * VIPS_D65_Y0; const float G = p[1] * VIPS_D65_Y0; const float B = p[2] * VIPS_D65_Y0; @@ -79,137 +69,40 @@ vips_scRGB2XYZ_line(float *restrict q, float *restrict p, * as the original is defined in a separate file and is part of * the public API so a compiler will not inline. */ - q[0] = 0.4124 * R + - 0.3576 * G + - 0.1805 * B; - q[1] = 0.2126 * R + - 0.7152 * G + - 0.0722 * B; - q[2] = 0.0193 * R + - 0.1192 * G + - 0.9505 * B; + q[0] = 0.4124F * R + 0.3576F * G + 0.1805F * B; + q[1] = 0.2126F * R + 0.7152F * G + 0.0722F * B; + q[2] = 0.0193F * R + 0.1192F * G + 0.9505F * B; p += 3; q += 3; - - for (j = 0; j < extra_bands; j++) - q[j] = VIPS_CLIP(0, p[j] * 255.0, 255.0); - p += extra_bands; - q += extra_bands; } } -static int -vips_scRGB2XYZ_gen(VipsRegion *out_region, - void *seq, void *a, void *b, gboolean *stop) -{ - VipsRegion *ir = (VipsRegion *) seq; - VipsRect *r = &out_region->valid; - VipsImage *in = ir->im; - - int y; - - if (vips_region_prepare(ir, r)) - return -1; - - VIPS_GATE_START("vips_scRGB2XYZ_gen: work"); - - for (y = 0; y < r->height; y++) { - float *p = (float *) - VIPS_REGION_ADDR(ir, r->left, r->top + y); - float *q = (float *) - VIPS_REGION_ADDR(out_region, r->left, r->top + y); - - vips_scRGB2XYZ_line(q, p, in->Bands - 3, r->width); - } - - VIPS_GATE_STOP("vips_scRGB2XYZ_gen: work"); - - return 0; -} - -static int -vips_scRGB2XYZ_build(VipsObject *object) -{ - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); - VipsscRGB2XYZ *scRGB2XYZ = (VipsscRGB2XYZ *) object; - - VipsImage **t = (VipsImage **) vips_object_local_array(object, 2); - - VipsImage *in; - VipsImage *out; - - if (VIPS_OBJECT_CLASS(vips_scRGB2XYZ_parent_class)->build(object)) - return -1; - - in = scRGB2XYZ->in; - if (vips_check_bands_atleast(class->nickname, in, 3)) - return -1; - - if (vips_cast_float(in, &t[0], NULL)) - return -1; - in = t[0]; - - out = vips_image_new(); - if (vips_image_pipelinev(out, - VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) { - g_object_unref(out); - return -1; - } - out->Type = VIPS_INTERPRETATION_XYZ; - out->BandFmt = VIPS_FORMAT_FLOAT; - - if (vips_image_generate(out, - vips_start_one, vips_scRGB2XYZ_gen, vips_stop_one, - in, scRGB2XYZ)) { - g_object_unref(out); - return -1; - } - - g_object_set(object, "out", out, NULL); - - return 0; -} - static void vips_scRGB2XYZ_class_init(VipsscRGB2XYZClass *class) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class); - - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class); object_class->nickname = "scRGB2XYZ"; object_class->description = _("transform scRGB to XYZ"); - object_class->build = vips_scRGB2XYZ_build; - - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - VIPS_ARG_IMAGE(class, "in", 1, - _("Input"), - _("Input image"), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET(VipsscRGB2XYZ, in)); - - VIPS_ARG_IMAGE(class, "out", 100, - _("Output"), - _("Output image"), - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET(VipsscRGB2XYZ, out)); + colour_class->process_line = vips_scRGB2XYZ_line; } static void vips_scRGB2XYZ_init(VipsscRGB2XYZ *scRGB2XYZ) { + VipsColour *colour = VIPS_COLOUR(scRGB2XYZ); + + colour->interpretation = VIPS_INTERPRETATION_XYZ; } /** * vips_scRGB2XYZ: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Turn XYZ to scRGB. * diff --git a/libvips/colour/scRGB2sRGB.c b/libvips/colour/scRGB2sRGB.c index e6d6315089..92d17ec376 100644 --- a/libvips/colour/scRGB2sRGB.c +++ b/libvips/colour/scRGB2sRGB.c @@ -27,6 +27,8 @@ * - cut about to make scRGB2sRGB.c * 12/2/15 * - add 16-bit alpha handling + * 16/4/25 + * - move on top of ColourCode */ /* @@ -68,117 +70,65 @@ #include "pcolour.h" -/* We can't use VipsColourCode as our parent class. We want to handle - * alpha ourselves so we can get 16 -> 8 bit conversion right. - */ - typedef struct _VipsscRGB2sRGB { - VipsOperation parent_instance; + VipsColourCode parent_instance; - VipsImage *in; - VipsImage *out; int depth; } VipsscRGB2sRGB; -typedef VipsOperationClass VipsscRGB2sRGBClass; +typedef VipsColourCodeClass VipsscRGB2sRGBClass; -G_DEFINE_TYPE(VipsscRGB2sRGB, vips_scRGB2sRGB, VIPS_TYPE_OPERATION); +G_DEFINE_TYPE(VipsscRGB2sRGB, vips_scRGB2sRGB, VIPS_TYPE_COLOUR_CODE); -/* Process a buffer of data. - */ static void -vips_scRGB2sRGB_line_8(VipsPel *restrict q, float *restrict p, - int extra_bands, int width) +vips_scRGB2sRGB_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) { - int i, j; + VipsscRGB2sRGB *scRGB2sRGB = (VipsscRGB2sRGB *) colour; - for (i = 0; i < width; i++) { - float R = p[0]; - float G = p[1]; - float B = p[2]; + if (scRGB2sRGB->depth == 16) { + unsigned short *restrict q; + float *restrict p; - int r, g, b; + q = (unsigned short *) out; + p = (float *) in[0]; + for (int i = 0; i < width; i++) { + const float R = p[0]; + const float G = p[1]; + const float B = p[2]; - vips_col_scRGB2sRGB_8(R, G, B, &r, &g, &b, NULL); + int r, g, b; + vips_col_scRGB2sRGB_16(R, G, B, &r, &g, &b, NULL); - p += 3; + q[0] = r; + q[1] = g; + q[2] = b; - q[0] = r; - q[1] = g; - q[2] = b; - - q += 3; - - for (j = 0; j < extra_bands; j++) - q[j] = VIPS_CLIP(0, (int) (p[j] * 255.0), UCHAR_MAX); - p += extra_bands; - q += extra_bands; + p += 3; + q += 3; + } } -} - -static void -vips_scRGB2sRGB_line_16(unsigned short *restrict q, float *restrict p, - int extra_bands, int width) -{ - int i, j; - - for (i = 0; i < width; i++) { - float R = p[0]; - float G = p[1]; - float B = p[2]; - - int r, g, b; - - vips_col_scRGB2sRGB_16(R, G, B, &r, &g, &b, NULL); - - p += 3; - - q[0] = r; - q[1] = g; - q[2] = b; - - q += 3; - - for (j = 0; j < extra_bands; j++) - q[j] = VIPS_CLIP(0, (int) (p[j] * 65535.0), USHRT_MAX); - p += extra_bands; - q += extra_bands; - } -} - -static int -vips_scRGB2sRGB_gen(VipsRegion *out_region, - void *seq, void *a, void *b, gboolean *stop) -{ - VipsRegion *ir = (VipsRegion *) seq; - VipsscRGB2sRGB *scRGB2sRGB = (VipsscRGB2sRGB *) b; - VipsRect *r = &out_region->valid; - VipsImage *in = ir->im; - - int y; - - if (vips_region_prepare(ir, r)) - return -1; - - VIPS_GATE_START("vips_scRGB2sRGB_gen: work"); - - for (y = 0; y < r->height; y++) { - float *p = (float *) - VIPS_REGION_ADDR(ir, r->left, r->top + y); - VipsPel *q = (VipsPel *) - VIPS_REGION_ADDR(out_region, r->left, r->top + y); - - if (scRGB2sRGB->depth == 16) - vips_scRGB2sRGB_line_16((unsigned short *) q, p, - in->Bands - 3, r->width); - else - vips_scRGB2sRGB_line_8(q, p, - in->Bands - 3, r->width); + else { + unsigned char *restrict q; + float *restrict p; + + q = (unsigned char *) out; + p = (float *) in[0]; + for (int i = 0; i < width; i++) { + const float R = p[0]; + const float G = p[1]; + const float B = p[2]; + + int r, g, b; + vips_col_scRGB2sRGB_8(R, G, B, &r, &g, &b, NULL); + + q[0] = r; + q[1] = g; + q[2] = b; + + p += 3; + q += 3; + } } - - VIPS_GATE_STOP("vips_scRGB2sRGB_gen: work"); - - return 0; } static int @@ -186,38 +136,25 @@ vips_scRGB2sRGB_build(VipsObject *object) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); VipsscRGB2sRGB *scRGB2sRGB = (VipsscRGB2sRGB *) object; + VipsColour *colour = (VipsColour *) object; + VipsColourCode *code = (VipsColourCode *) object; - VipsImage **t = (VipsImage **) vips_object_local_array(object, 2); + // input image we want - VipsImage *in; - VipsBandFormat format; - VipsInterpretation interpretation; - VipsImage *out; + code->input_format = VIPS_FORMAT_FLOAT; + colour->input_bands = 3; - if (VIPS_OBJECT_CLASS(vips_scRGB2sRGB_parent_class)->build(object)) - return -1; - - in = scRGB2sRGB->in; - if (vips_check_bands_atleast(class->nickname, in, 3)) - return -1; - - // we are changing the gamma, so any profile on the image can no longer - // work (and will cause horrible problems in any downstream colour - // handling) - if (vips_copy(in, &t[0], NULL)) - return -1; - in = t[0]; - vips_image_remove(in, VIPS_META_ICC_NAME); + // output image we make switch (scRGB2sRGB->depth) { case 16: - interpretation = VIPS_INTERPRETATION_RGB16; - format = VIPS_FORMAT_USHORT; + colour->interpretation = VIPS_INTERPRETATION_RGB16; + colour->format = VIPS_FORMAT_USHORT; break; case 8: - interpretation = VIPS_INTERPRETATION_sRGB; - format = VIPS_FORMAT_UCHAR; + colour->interpretation = VIPS_INTERPRETATION_sRGB; + colour->format = VIPS_FORMAT_UCHAR; break; default: @@ -225,29 +162,9 @@ vips_scRGB2sRGB_build(VipsObject *object) return -1; } - if (vips_cast_float(in, &t[1], NULL)) - return -1; - in = t[1]; + colour->bands = 3; - out = vips_image_new(); - if (vips_image_pipelinev(out, - VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) { - g_object_unref(out); - return -1; - } - out->Type = interpretation; - out->BandFmt = format; - - if (vips_image_generate(out, - vips_start_one, vips_scRGB2sRGB_gen, vips_stop_one, - in, scRGB2sRGB)) { - g_object_unref(out); - return -1; - } - - g_object_set(object, "out", out, NULL); - - return 0; + return VIPS_OBJECT_CLASS(vips_scRGB2sRGB_parent_class)->build(object); } static void @@ -255,28 +172,16 @@ vips_scRGB2sRGB_class_init(VipsscRGB2sRGBClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class); + VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class); gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; object_class->nickname = "scRGB2sRGB"; - object_class->description = _("convert an scRGB image to sRGB"); + object_class->description = _("convert scRGB to sRGB"); object_class->build = vips_scRGB2sRGB_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - - VIPS_ARG_IMAGE(class, "in", 1, - _("Input"), - _("Input image"), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET(VipsscRGB2sRGB, in)); - - VIPS_ARG_IMAGE(class, "out", 100, - _("Output"), - _("Output image"), - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET(VipsscRGB2sRGB, out)); + colour_class->process_line = vips_scRGB2sRGB_line; VIPS_ARG_INT(class, "depth", 130, _("Depth"), @@ -296,18 +201,16 @@ vips_scRGB2sRGB_init(VipsscRGB2sRGB *scRGB2sRGB) * vips_scRGB2sRGB: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @depth: depth of output image in bits + * @...: `NULL`-terminated list of optional named arguments * * Convert an scRGB image to sRGB. Set @depth to 16 to get 16-bit output. * - * If @depth is 16, any extra channels after RGB are - * multiplied by 256. + * ::: tip "Optional arguments" + * * @depth: depth of output image in bits * - * See also: vips_LabS2LabQ(), vips_sRGB2scRGB(), vips_rad2float(). + * ::: seealso + * [method@Image.LabS2LabQ], [method@Image.sRGB2scRGB], + * [method@Image.rad2float]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/addalpha.c b/libvips/conversion/addalpha.c index 2932296481..2025782ca1 100644 --- a/libvips/conversion/addalpha.c +++ b/libvips/conversion/addalpha.c @@ -102,11 +102,12 @@ vips_addalpha_init(VipsAddAlpha *addalpha) * vips_addalpha: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Append an alpha channel. * - * See also: vips_image_hasalpha(). + * ::: seealso + * [method@Image.hasalpha]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/arrayjoin.c b/libvips/conversion/arrayjoin.c index 6136e7fff7..90081e4d5b 100644 --- a/libvips/conversion/arrayjoin.c +++ b/libvips/conversion/arrayjoin.c @@ -64,7 +64,7 @@ typedef struct _VipsArrayjoin { VipsArrayImage *in; int across; int shim; - VipsArea *background; + VipsArrayDouble *background; VipsAlign halign; VipsAlign valign; int hspacing; @@ -224,7 +224,7 @@ vips_arrayjoin_build(VipsObject *object) */ band = (VipsImage **) vips_object_local_array(object, n); if (vips__bandalike_vec(class->nickname, - in, band, n, join->background->n)) + in, band, n, VIPS_AREA(join->background)->n)) return -1; in = band; @@ -240,15 +240,15 @@ vips_arrayjoin_build(VipsObject *object) } if (!vips_object_argument_isset(object, "hspacing")) - join->hspacing = hspacing; + join->hspacing = hspacing; // FIXME: Invalidates operation cache if (!vips_object_argument_isset(object, "vspacing")) - join->vspacing = vspacing; + join->vspacing = vspacing; // FIXME: Invalidates operation cache hspacing = join->hspacing; vspacing = join->vspacing; if (!vips_object_argument_isset(object, "across")) - join->across = n; + join->across = n; // FIXME: Invalidates operation cache /* How many images down the grid? */ @@ -452,9 +452,7 @@ vips_arrayjoin_init(VipsArrayjoin *join) { /* Init our instance fields. */ - join->background = - vips_area_new_array(G_TYPE_DOUBLE, sizeof(double), 1); - ((double *) (join->background->data))[0] = 0.0; + join->background = vips_array_double_newv(1, 0.0); } static int @@ -475,17 +473,7 @@ vips_arrayjoinv(VipsImage **in, VipsImage **out, int n, va_list ap) * @in: (array length=n) (transfer none): array of input images * @out: (out): output image * @n: number of input images - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @across: %gint, number of images per row - * * @shim: %gint, space between images, in pixels - * * @background: #VipsArrayDouble, background ink colour - * * @halign: #VipsAlign, low, centre or high alignment - * * @valign: #VipsAlign, low, centre or high alignment - * * @hspacing: %gint, horizontal distance between images - * * @vspacing: %gint, vertical distance between images + * @...: `NULL`-terminated list of optional named arguments * * Lay out the images in @in in a grid. The grid is @across images across and * however high is necessary to use up all of @in. Images are set down @@ -511,12 +499,22 @@ vips_arrayjoinv(VipsImage **in, VipsImage **out, int n, va_list ap) * * The input images are cast up to the smallest common type (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). * - * vips_colourspace() can be useful for moving the images to a common + * [method@Image.colourspace] can be useful for moving the images to a common * colourspace for compositing. * - * See also: vips_join(), vips_insert(), vips_colourspace(). + * ::: tip "Optional arguments" + * * @across: `gint`, number of images per row + * * @shim: `gint`, space between images, in pixels + * * @background: [struct@ArrayDouble], background ink colour + * * @halign: [enum@Align], low, centre or high alignment + * * @valign: [enum@Align], low, centre or high alignment + * * @hspacing: `gint`, horizontal distance between images + * * @vspacing: `gint`, vertical distance between images + * + * ::: seealso + * [method@Image.join], [method@Image.insert], [method@Image.colourspace]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/autorot.c b/libvips/conversion/autorot.c index 0dcedbd47a..f4f589d34b 100644 --- a/libvips/conversion/autorot.c +++ b/libvips/conversion/autorot.c @@ -90,7 +90,7 @@ vips_autorot_remove_angle_sub(VipsImage *image, * @image: image to remove orientation from * * Remove the orientation tag on @image. Also remove any exif orientation tags. - * You must vips_copy() the image before calling this function since it + * You must [method@Image.copy] the image before calling this function since it * modifies metadata. */ void @@ -235,20 +235,19 @@ vips_autorot_init(VipsAutorot *autorot) * vips_autorot: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @angle: output #VipsAngle the image was rotated by - * * @flip: output %gboolean whether the image was flipped + * @...: `NULL`-terminated list of optional named arguments * * 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 + * upright. The [const@META_ORIENTATION] tag is removed from @out to prevent * accidental double rotation. * * Read @angle to find the amount the image was rotated by. Read @flip to * see if the image was also flipped. * + * ::: tip "Optional arguments" + * * @angle: output [enum@Angle] the image was rotated by + * * @flip: output `gboolean` whether the image was flipped + * * Returns: 0 on success, -1 on error */ int diff --git a/libvips/conversion/bandbool.c b/libvips/conversion/bandbool.c index 33b977a3f3..69f6109d6d 100644 --- a/libvips/conversion/bandbool.c +++ b/libvips/conversion/bandbool.c @@ -1,4 +1,4 @@ -/* bandbool.c --- bool op across image bands +/* bandbool.c -- bool op across image bands * * 7/12/12 * - from boolean.c @@ -258,14 +258,14 @@ vips_bandboolv(VipsImage *in, VipsImage **out, /** * vips_bandbool: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] * @boolean: boolean operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Perform various boolean operations across the bands of an image. For * example, a three-band uchar image operated on with - * #VIPS_OPERATION_BOOLEAN_AND will produce a one-band uchar image where each + * [enum@Vips.OperationBoolean.AND] will produce a one-band uchar image where each * pixel is the bitwise and of the band elements of the corresponding pixel in * the input image. * @@ -275,10 +275,11 @@ vips_bandboolv(VipsImage *in, VipsImage **out, * * The output image always has one band. * - * This operation is useful in conjunction with vips_relational(). You can use + * This operation is useful in conjunction with [method@Image.relational]. You can use * it to see if all image bands match exactly. * - * See also: vips_boolean_const(). + * ::: seealso + * [method@Image.boolean_const]. * * Returns: 0 on success, -1 on error */ @@ -298,12 +299,12 @@ vips_bandbool(VipsImage *in, VipsImage **out, /** * vips_bandand: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_AND on an image. See - * vips_bandbool(). + * Perform [enum@Vips.OperationBoolean.AND] on an image. See + * [method@Image.bandbool]. * * Returns: 0 on success, -1 on error */ @@ -322,12 +323,12 @@ vips_bandand(VipsImage *in, VipsImage **out, ...) /** * vips_bandor: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_OR on an image. See - * vips_bandbool(). + * Perform [enum@Vips.OperationBoolean.OR] on an image. See + * [method@Image.bandbool]. * * Returns: 0 on success, -1 on error */ @@ -346,12 +347,12 @@ vips_bandor(VipsImage *in, VipsImage **out, ...) /** * vips_bandeor: (method) - * @in: left-hand input #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments + * @in: left-hand input [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * - * Perform #VIPS_OPERATION_BOOLEAN_EOR on an image. See - * vips_bandbool(). + * Perform [enum@Vips.OperationBoolean.EOR] on an image. See + * [method@Image.bandbool]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/bandfold.c b/libvips/conversion/bandfold.c index 707e6d3187..7bd659b935 100644 --- a/libvips/conversion/bandfold.c +++ b/libvips/conversion/bandfold.c @@ -96,7 +96,7 @@ vips_bandfold_gen(VipsRegion *out_region, /* We can't use vips_region_region() since we change pixel * coordinates. */ - memcpy(q, p, psize * r->width); + memcpy(q, p, (size_t) psize * r->width); } return 0; @@ -116,7 +116,8 @@ vips_bandfold_build(VipsObject *object) return -1; if (bandfold->factor == 0) - bandfold->factor = bandfold->in->Xsize; + bandfold->factor = bandfold->in->Xsize; // FIXME: Invalidates operation cache + if (bandfold->in->Xsize % bandfold->factor != 0) { vips_error(class->nickname, "%s", _("@factor must be a factor of image width")); @@ -182,18 +183,18 @@ vips_bandfold_init(VipsBandfold *bandfold) * vips_bandfold: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @factor: fold by this factor + * @...: `NULL`-terminated list of optional named arguments * * Fold up an image horizontally: width is collapsed into bands. * Use @factor to set how much to fold by: @factor 3, for example, will make * the output image three times narrower than the input, and with three times * as many bands. By default the whole of the input width is folded up. * - * See also: vips_csvload(), vips_bandunfold(). + * ::: tip "Optional arguments" + * * @factor: `gint`, fold by this factor + * + * ::: seealso + * [ctor@Image.csvload], [method@Image.bandunfold]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/bandjoin.c b/libvips/conversion/bandjoin.c index 511740a4c3..099397131b 100644 --- a/libvips/conversion/bandjoin.c +++ b/libvips/conversion/bandjoin.c @@ -230,7 +230,7 @@ vips_bandjoinv(VipsImage **in, VipsImage **out, int n, va_list ap) * @in: (array length=n) (transfer none): array of input images * @out: (out): output image * @n: number of input images - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Join a set of images together, bandwise. * @@ -244,9 +244,10 @@ vips_bandjoinv(VipsImage **in, VipsImage **out, int n, va_list ap) * * The input images are cast up to the smallest common type (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). * - * See also: vips_insert(). + * ::: seealso + * [method@Image.insert]. * * Returns: 0 on success, -1 on error */ @@ -264,13 +265,13 @@ vips_bandjoin(VipsImage **in, VipsImage **out, int n, ...) } /** - * vips_bandjoin2: + * vips_bandjoin2: (method) * @in1: first input image * @in2: second input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Join a pair of images together, bandwise. See vips_bandjoin(). + * Join a pair of images together, bandwise. See [func@Image.bandjoin]. * * Returns: 0 on success, -1 on error */ @@ -473,11 +474,12 @@ vips_bandjoin_constv(VipsImage *in, VipsImage **out, * @out: (out): output image * @c: (array length=n): array of constants to append * @n: number of constants - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Append a set of constant bands to an image. * - * See also: vips_bandjoin(). + * ::: seealso + * [func@Image.bandjoin]. * * Returns: 0 on success, -1 on error */ @@ -499,7 +501,7 @@ vips_bandjoin_const(VipsImage *in, VipsImage **out, double *c, int n, ...) * @in: input image * @out: (out): output image * @c: constant to append - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Append a single constant band to an image. * diff --git a/libvips/conversion/bandmean.c b/libvips/conversion/bandmean.c index 730e62eba8..535f89ffb1 100644 --- a/libvips/conversion/bandmean.c +++ b/libvips/conversion/bandmean.c @@ -224,14 +224,15 @@ vips_bandmean_init(VipsBandmean *bandmean) * vips_bandmean: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation writes a one-band image where each pixel is the average of * the bands for that pixel in the input image. The output band format is * the same as the input band format. Integer types use round-to-nearest * averaging. * - * See also: vips_add(), vips_avg(), vips_recomb() + * ::: seealso + * [method@Image.add], [method@Image.avg], [method@Image.recomb] * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/bandrank.c b/libvips/conversion/bandrank.c index ef26ba2019..41b7b5ec46 100644 --- a/libvips/conversion/bandrank.c +++ b/libvips/conversion/bandrank.c @@ -223,7 +223,7 @@ vips_bandrank_build(VipsObject *object) bandary->out_bands = band[0]->Bands; if (bandrank->index == -1) - bandrank->index = bandary->n / 2; + bandrank->index = bandary->n / 2; // FIXME: Invalidates operation cache } if (VIPS_OBJECT_CLASS(vips_bandrank_parent_class)->build(object)) @@ -291,11 +291,7 @@ vips_bandrankv(VipsImage **in, VipsImage **out, int n, va_list ap) * @in: (array length=n): array of input images * @out: (out): output image * @n: number of input images - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @index: pick this index from list of sorted values + * @...: `NULL`-terminated list of optional named arguments * * Sorts the images @in band-element-wise, then outputs an * image in which each band element is selected from the sorted list by the @@ -314,7 +310,11 @@ vips_bandrankv(VipsImage **in, VipsImage **out, int n, va_list ap) * * Smaller input images are expanded by adding black pixels. * - * See also: vips_rank(). + * ::: tip "Optional arguments" + * * @index: `gint`, pick this index from list of sorted values + * + * ::: seealso + * [method@Image.rank]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/bandunfold.c b/libvips/conversion/bandunfold.c index 6bec18c835..56928e6811 100644 --- a/libvips/conversion/bandunfold.c +++ b/libvips/conversion/bandunfold.c @@ -99,7 +99,7 @@ vips_bandunfold_gen(VipsRegion *out_region, /* We can't use vips_region_region() since we change pixel * coordinates. */ - memcpy(q, p, r->width * psize); + memcpy(q, p, (size_t) r->width * psize); } return 0; @@ -119,7 +119,8 @@ vips_bandunfold_build(VipsObject *object) return -1; if (bandunfold->factor == 0) - bandunfold->factor = bandunfold->in->Bands; + bandunfold->factor = bandunfold->in->Bands; // FIXME: Invalidates operation cache + if (bandunfold->in->Bands % bandunfold->factor != 0) { vips_error(class->nickname, "%s", _("@factor must be a factor of image bands")); @@ -185,18 +186,18 @@ vips_bandunfold_init(VipsBandunfold *bandunfold) * vips_bandunfold: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @factor: unfold by this factor + * @...: `NULL`-terminated list of optional named arguments * * Unfold image bands into x axis. * Use @factor to set how much to unfold by: @factor 3, for example, will make * the output image three times wider than the input, and with one third * as many bands. By default, all bands are unfolded. * - * See also: vips_csvload(), vips_bandfold(). + * ::: tip "Optional arguments" + * * @factor: unfold by this factor + * + * ::: seealso + * [ctor@Image.csvload], [method@Image.bandfold]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/byteswap.c b/libvips/conversion/byteswap.c index e2c3b33006..b5f65ab3ba 100644 --- a/libvips/conversion/byteswap.c +++ b/libvips/conversion/byteswap.c @@ -250,11 +250,12 @@ vips_byteswap_init(VipsByteswap *byteswap) * vips_byteswap: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Swap the byte order in an image. * - * See also: vips_rawload(). + * ::: seealso + * [ctor@Image.rawload]. * * Returns: 0 on success, -1 on error. */ @@ -271,7 +272,7 @@ vips_byteswap(VipsImage *in, VipsImage **out, ...) return result; } -/* Convenience function: swap if @swap is %TRUE, otherwise copy. +/* Convenience function: swap if @swap is `TRUE`, otherwise copy. */ int vips__byteswap_bool(VipsImage *in, VipsImage **out, gboolean swap) diff --git a/libvips/conversion/cache.c b/libvips/conversion/cache.c index f7e6b57012..ab56de929f 100644 --- a/libvips/conversion/cache.c +++ b/libvips/conversion/cache.c @@ -129,7 +129,7 @@ vips_cache_class_init(VipsCacheClass *class) _("Maximum number of tiles to cache"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsCache, max_tiles), - -1, 1000000, 1000); + -1, 1000000, 250); } static void @@ -143,25 +143,19 @@ vips_cache_init(VipsCache *cache) } /** - * vips_cache: (method) + * vips_cache: * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @tile_width: width of tiles in cache - * * @tile_height: height of tiles in cache - * * @max_tiles: maximum number of tiles to cache - * - * This operation behaves rather like vips_copy() between images + * This operation behaves rather like [method@Image.copy] between images * @in and @out, except that it keeps a cache of computed pixels. * This cache is made of up to @max_tiles tiles (a value of -1 * means any number of tiles), and each tile is of size @tile_width * by @tile_height pixels. By default it will cache 250 128 x 128 pixel tiles, * enough for two 1920 x 1080 images. * - * This operation is a thin wrapper over vips_sink_screen(), see the + * This operation is a thin wrapper over [method@Image.sink_screen], see the * documentation for that operation for details. * * It uses a set of background threads to calculate pixels and the various @@ -170,7 +164,13 @@ vips_cache_init(VipsCache *cache) * of those pixels have been calculated. Pixels are calculated with a set of * threads. * - * See also: vips_tilecache(). + * ::: tip "Optional arguments" + * * @tile_width: width of tiles in cache + * * @tile_height: height of tiles in cache + * * @max_tiles: maximum number of tiles to cache + * + * ::: seealso + * [method@Image.tilecache]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/cast.c b/libvips/conversion/cast.c index fb945d2312..e362d343d0 100644 --- a/libvips/conversion/cast.c +++ b/libvips/conversion/cast.c @@ -488,8 +488,7 @@ vips_cast_build(VipsObject *object) if (cast->shift && !vips_band_format_isint(in->BandFmt) && vips_band_format_isint(cast->format)) { - if (vips_cast(in, &t[1], - vips_image_guess_format(in), NULL)) + if (vips_cast(in, &t[1], vips_image_guess_format(in), NULL)) return -1; in = t[1]; } @@ -563,24 +562,24 @@ vips_castv(VipsImage *in, VipsImage **out, VipsBandFormat format, va_list ap) * @in: input image * @out: (out): output image * @format: format to convert to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @shift: %gboolean, integer values are shifted + * @...: `NULL`-terminated list of optional named arguments * * Convert @in to @format. You can convert between any pair of formats. * Floats are truncated (not rounded). Out of range values are clipped. * * Casting from complex to real returns the real part. * - * If @shift is %TRUE, integer values are shifted up and down. For example, + * If @shift is `TRUE`, integer values are shifted up and down. For example, * casting from unsigned 8 bit to unsigned 16 bit would * shift every value left by 8 bits. The bottom bit is copied into the new * bits, so 255 would become 65535. * - * See also: vips_scale(), vips_complexform(), vips_real(), vips_imag(), - * vips_cast_uchar(), vips_msb(). + * ::: tip "Optional arguments" + * * @shift: `gboolean`, integer values are shifted + * + * ::: seealso + * [method@Image.scale], [method@Image.complexform], [method@Image.real], + * [method@Image.imag], [method@Image.cast_uchar], [method@Image.msb]. * * Returns: 0 on success, -1 on error */ @@ -601,9 +600,12 @@ vips_cast(VipsImage *in, VipsImage **out, VipsBandFormat format, ...) * vips_cast_uchar: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert @in to #VIPS_FORMAT_UCHAR. See vips_cast(). + * Convert @in to [enum@Vips.BandFormat.UCHAR]. See [method@Image.cast]. + * + * ::: tip "Optional arguments" + * * @shift: `gboolean`, integer values are shifted * * Returns: 0 on success, -1 on error */ @@ -624,9 +626,12 @@ vips_cast_uchar(VipsImage *in, VipsImage **out, ...) * vips_cast_char: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments + * + * Convert @in to [enum@Vips.BandFormat.CHAR]. See [method@Image.cast]. * - * Convert @in to #VIPS_FORMAT_CHAR. See vips_cast(). + * ::: tip "Optional arguments" + * * @shift: `gboolean`, integer values are shifted * * Returns: 0 on success, -1 on error */ @@ -647,9 +652,12 @@ vips_cast_char(VipsImage *in, VipsImage **out, ...) * vips_cast_ushort: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert @in to #VIPS_FORMAT_USHORT. See vips_cast(). + * Convert @in to [enum@Vips.BandFormat.USHORT]. See [method@Image.cast]. + * + * ::: tip "Optional arguments" + * * @shift: `gboolean`, integer values are shifted * * Returns: 0 on success, -1 on error */ @@ -670,9 +678,12 @@ vips_cast_ushort(VipsImage *in, VipsImage **out, ...) * vips_cast_short: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments + * + * Convert @in to [enum@Vips.BandFormat.SHORT]. See [method@Image.cast]. * - * Convert @in to #VIPS_FORMAT_SHORT. See vips_cast(). + * ::: tip "Optional arguments" + * * @shift: `gboolean`, integer values are shifted * * Returns: 0 on success, -1 on error */ @@ -693,9 +704,12 @@ vips_cast_short(VipsImage *in, VipsImage **out, ...) * vips_cast_uint: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert @in to #VIPS_FORMAT_UINT. See vips_cast(). + * Convert @in to [enum@Vips.BandFormat.UINT]. See [method@Image.cast]. + * + * ::: tip "Optional arguments" + * * @shift: `gboolean`, integer values are shifted * * Returns: 0 on success, -1 on error */ @@ -716,9 +730,12 @@ vips_cast_uint(VipsImage *in, VipsImage **out, ...) * vips_cast_int: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments + * + * Convert @in to [enum@Vips.BandFormat.INT]. See [method@Image.cast]. * - * Convert @in to #VIPS_FORMAT_INT. See vips_cast(). + * ::: tip "Optional arguments" + * * @shift: `gboolean`, integer values are shifted * * Returns: 0 on success, -1 on error */ @@ -739,9 +756,9 @@ vips_cast_int(VipsImage *in, VipsImage **out, ...) * vips_cast_float: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert @in to #VIPS_FORMAT_FLOAT. See vips_cast(). + * Convert @in to [enum@Vips.BandFormat.FLOAT]. See [method@Image.cast]. * * Returns: 0 on success, -1 on error */ @@ -762,9 +779,9 @@ vips_cast_float(VipsImage *in, VipsImage **out, ...) * vips_cast_double: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert @in to #VIPS_FORMAT_DOUBLE. See vips_cast(). + * Convert @in to [enum@Vips.BandFormat.DOUBLE]. See [method@Image.cast]. * * Returns: 0 on success, -1 on error */ @@ -785,9 +802,9 @@ vips_cast_double(VipsImage *in, VipsImage **out, ...) * vips_cast_complex: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert @in to #VIPS_FORMAT_COMPLEX. See vips_cast(). + * Convert @in to [enum@Vips.BandFormat.COMPLEX]. See [method@Image.cast]. * * Returns: 0 on success, -1 on error */ @@ -808,9 +825,9 @@ vips_cast_complex(VipsImage *in, VipsImage **out, ...) * vips_cast_dpcomplex: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convert @in to #VIPS_FORMAT_DPCOMPLEX. See vips_cast(). + * Convert @in to [enum@Vips.BandFormat.DPCOMPLEX]. See [method@Image.cast]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/composite.cpp b/libvips/conversion/composite.cpp index 2c5bafd66f..a2bae42fc8 100644 --- a/libvips/conversion/composite.cpp +++ b/libvips/conversion/composite.cpp @@ -899,7 +899,7 @@ vips_composite_base_blend3(VipsCompositeSequence *seq, /* You can't sqrt a vector, so we must loop. */ for (int b = 0; b < 3; b++) { - double g; + float g; if (B[b] <= 0.25) g = ((16 * B[b] - 12) * B[b] + 4) * B[b]; @@ -958,7 +958,7 @@ vips_combine_pixels(VipsCompositeSequence *seq, VipsPel *q) T *restrict tq = (T *restrict) q; T **restrict tp = (T * *restrict) seq->p; - double B[MAX_BANDS + 1]; + double B[MAX_BANDS + 1] = { 0.0 }; double aB; /* Load and scale the base pixel to 0 - 1. @@ -1387,7 +1387,7 @@ vips_composite_base_build(VipsObject *object) break; } - composite->compositing_space = any_16 + composite->compositing_space = any_16 // FIXME: Invalidates operation cache ? (all_grey ? VIPS_INTERPRETATION_GREY16 : VIPS_INTERPRETATION_RGB16) diff --git a/libvips/conversion/conversion.c b/libvips/conversion/conversion.c index 628624a271..4787e9ad1e 100644 --- a/libvips/conversion/conversion.c +++ b/libvips/conversion/conversion.c @@ -49,58 +49,33 @@ #include "pconversion.h" -/** - * SECTION: conversion - * @short_description: convert images in some way: change band format, change header, insert, extract, join - * @see_also: resample - * @stability: Stable - * @include: vips/vips.h - * - * These operations convert an image in some way. They can be split into a two - * main groups. - * - * The first set of operations change an image's format in some way. You - * can change the band format (for example, cast to 32-bit unsigned - * int), form complex images from real images, convert images to - * matrices and back, change header fields, and a few others. - * - * The second group move pixels about in some way. You can flip, rotate, - * extract, insert and join pairs of images in various ways. - * - */ - /** * vips_composite: * @in: (array length=n) (transfer none): array of input images * @out: (out): output image * @n: number of input images - * @mode: array of (@n - 1) #VipsBlendMode - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @compositing_space: #VipsInterpretation to composite in - * * @premultiplied: %gboolean, images are already premultiplied - * * @x: #VipsArrayInt, array of (@n - 1) x coordinates - * * @y: #VipsArrayInt, array of (@n - 1) y coordinates + * @mode: array of (@n - 1) [enum@BlendMode] + * @...: `NULL`-terminated list of optional named arguments * * Composite an array of images together. * * Images are placed in a stack, with @in[0] at the bottom and @in[@n - 1] at * the top. Pixels are blended together working from the bottom upwards, with - * the blend mode at each step being set by the corresponding #VipsBlendMode + * the blend mode at each step being set by the corresponding [enum@BlendMode] * in @mode. * * Images are transformed to a compositing space before processing. This is - * #VIPS_INTERPRETATION_sRGB, #VIPS_INTERPRETATION_B_W, - * #VIPS_INTERPRETATION_RGB16, or #VIPS_INTERPRETATION_GREY16 + * [enum@Vips.Interpretation.sRGB], [enum@Vips.Interpretation.B_W], + * [enum@Vips.Interpretation.RGB16], or [enum@Vips.Interpretation.GREY16] * by default, depending on * how many bands and bits the input images have. You can select any other - * space, such as #VIPS_INTERPRETATION_LAB or #VIPS_INTERPRETATION_scRGB. + * space, such as [enum@Vips.Interpretation.LAB] or + * [enum@Vips.Interpretation.scRGB]. * * The output image is in the compositing space. It will always be - * #VIPS_FORMAT_FLOAT unless one of the inputs is #VIPS_FORMAT_DOUBLE, in - * which case the output will be double as well. + * [enum@Vips.BandFormat.FLOAT] unless one of the inputs is + * [enum@Vips.BandFormat.DOUBLE], in which case the output will be double + * as well. * * Complex images are not supported. * @@ -113,10 +88,17 @@ * against that rectangle. * * Image are normally treated as unpremultiplied, so this operation can be used - * directly on PNG images. If your images have been through vips_premultiply(), - * set @premultiplied. + * directly on PNG images. If your images have been through + * [method@Image.premultiply], set @premultiplied. * - * See also: vips_insert(). + * ::: tip "Optional arguments" + * * @compositing_space: [enum@Interpretation] to composite in + * * @premultiplied: `gboolean`, images are already premultiplied + * * @x: [struct@ArrayInt], array of (@n - 1) x coordinates + * * @y: [struct@ArrayInt], array of (@n - 1) y coordinates + * + * ::: seealso + * [method@Image.insert]. * * Returns: 0 on success, -1 on error */ @@ -127,16 +109,15 @@ * @overlay: second input image * @out: (out): output image * @mode: composite with this blend mode - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @compositing_space: #VipsInterpretation to composite in - * * @premultiplied: %gboolean, images are already premultiplied - * * @x: %gint, position of overlay - * * @y: %gint, position of overlay + * Composite @overlay on top of @base with @mode. See [func@Image.composite]. * - * Composite @overlay on top of @base with @mode. See vips_composite(). + * ::: tip "Optional arguments" + * * @compositing_space: [enum@Interpretation] to composite in + * * @premultiplied: `gboolean`, images are already premultiplied + * * @x: `gint`, position of overlay + * * @y: `gint`, position of overlay * * Returns: 0 on success, -1 on error */ @@ -169,12 +150,11 @@ * @VIPS_BLEND_MODE_DIFFERENCE: difference of the two * @VIPS_BLEND_MODE_EXCLUSION: somewhat like DIFFERENCE, but lower-contrast * - * The various Porter-Duff and PDF blend modes. See vips_composite(), + * The various Porter-Duff and PDF blend modes. See [func@Image.composite], * for example. * - * The Cairo docs have a nice explanation of all the blend modes: - * - * https://www.cairographics.org/operators + * The Cairo docs have [a nice explanation of all the blend + * modes](https://www.cairographics.org/operators). * * The non-separable modes are not implemented. */ @@ -185,12 +165,13 @@ * @VIPS_ALIGN_CENTRE: align centre * @VIPS_ALIGN_HIGH: align high coordinate edge * - * See vips_join() and so on. + * See [method@Image.join] and so on. * - * Operations like vips_join() need to be told whether to align images on the + * Operations like [method@Image.join] need to be told whether to align images on the * low or high coordinate edge, or centre. * - * See also: vips_join(). + * ::: seealso + * [method@Image.join]. */ /** @@ -200,11 +181,12 @@ * @VIPS_ANGLE_D180: 180 degree rotate * @VIPS_ANGLE_D270: 90 degrees anti-clockwise * - * See vips_rot() and so on. + * See [method@Image.rot] and so on. * * Fixed rotate angles. * - * See also: vips_rot(). + * ::: seealso + * [method@Image.rot]. */ /** @@ -218,14 +200,15 @@ * @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 + * by [method@Image.smartcrop], for example, to decide what parts of the image to * keep. * - * #VIPS_INTERESTING_NONE and #VIPS_INTERESTING_LOW mean the same -- the - * crop is positioned at the top or left. #VIPS_INTERESTING_HIGH positions at + * [enum@Vips.Interesting.NONE] and [enum@Vips.Interesting.LOW] mean the same -- the + * crop is positioned at the top or left. [enum@Vips.Interesting.HIGH] positions at * the bottom or right. * - * See also: vips_smartcrop(). + * ::: seealso + * [method@Image.smartcrop]. */ /** @@ -240,7 +223,7 @@ * @VIPS_COMPASS_DIRECTION_SOUTH_WEST: south-west * @VIPS_COMPASS_DIRECTION_NORTH_WEST: north-west * - * A direction on a compass. Used for vips_gravity(), for example. + * A direction on a compass. Used for [method@Image.gravity], for example. */ /** @@ -254,11 +237,12 @@ * @VIPS_ANGLE45_D270: 90 degrees anti-clockwise * @VIPS_ANGLE45_D315: 45 degrees anti-clockwise * - * See vips_rot45() and so on. + * See [method@Image.rot45] and so on. * * Fixed rotate angles. * - * See also: vips_rot45(). + * ::: seealso + * [method@Image.rot45]. */ /** @@ -270,29 +254,30 @@ * @VIPS_EXTEND_WHITE: extend with white (all bits set) pixels * @VIPS_EXTEND_BACKGROUND: extend with colour from the @background property * - * See vips_embed(), vips_conv(), vips_affine() and so on. + * See [method@Image.embed], [method@Image.conv], [method@Image.affine] and so on. * * When the edges of an image are extended, you can specify * how you want the extension done. * - * #VIPS_EXTEND_BLACK --- new pixels are black, ie. all bits are zero. + * [enum@Vips.Extend.BLACK] -- new pixels are black, ie. all bits are zero. * - * #VIPS_EXTEND_COPY --- each new pixel takes the value of the nearest edge + * [enum@Vips.Extend.COPY] -- each new pixel takes the value of the nearest edge * pixel * - * #VIPS_EXTEND_REPEAT --- the image is tiled to fill the new area + * [enum@Vips.Extend.REPEAT] -- the image is tiled to fill the new area * - * #VIPS_EXTEND_MIRROR --- the image is reflected and tiled to reduce hash + * [enum@Vips.Extend.MIRROR] -- the image is reflected and tiled to reduce hash * edges * - * #VIPS_EXTEND_WHITE --- new pixels are white, ie. all bits are set + * [enum@Vips.Extend.WHITE] -- new pixels are white, ie. all bits are set * - * #VIPS_EXTEND_BACKGROUND --- colour set from the @background property + * [enum@Vips.Extend.BACKGROUND] -- colour set from the @background property * * We have to specify the exact value of each enum member since we have to * keep these frozen for back compat with vips7. * - * See also: vips_embed(). + * ::: seealso + * [method@Image.embed]. */ /** @@ -300,12 +285,13 @@ * @VIPS_DIRECTION_HORIZONTAL: left-right * @VIPS_DIRECTION_VERTICAL: top-bottom * - * See vips_flip(), vips_join() and so on. + * See [method@Image.flip], [method@Image.join] and so on. * - * Operations like vips_flip() need to be told whether to flip left-right or + * Operations like [method@Image.flip] need to be told whether to flip left-right or * top-bottom. * - * See also: vips_flip(), vips_join(). + * ::: seealso + * [method@Image.flip], [method@Image.join]. */ G_DEFINE_ABSTRACT_TYPE(VipsConversion, vips_conversion, VIPS_TYPE_OPERATION); diff --git a/libvips/conversion/copy.c b/libvips/conversion/copy.c index c8cfadbb35..2191546aa8 100644 --- a/libvips/conversion/copy.c +++ b/libvips/conversion/copy.c @@ -178,8 +178,7 @@ vips_copy_build(VipsObject *object) return -1; if (copy->swap) - g_warning("%s", - _("copy swap is deprecated, use byteswap instead")); + g_warning("copy swap is deprecated, use byteswap instead"); if (vips_image_pipelinev(conversion->out, VIPS_DEMAND_STYLE_THINSTRIP, copy->in, NULL)) @@ -363,20 +362,7 @@ vips_copy_init(VipsCopy *copy) * vips_copy: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @width: %gint, set image width - * * @height: %gint, set image height - * * @bands: %gint, set image bands - * * @format: #VipsBandFormat, set image format - * * @coding: #VipsCoding, set image coding - * * @interpretation: #VipsInterpretation, set image interpretation - * * @xres: %gdouble, set image xres - * * @yres: %gdouble, set image yres - * * @xoffset: %gint, set image xoffset - * * @yoffset: %gint, set image yoffset + * @...: `NULL`-terminated list of optional named arguments * * Copy an image, optionally modifying the header. VIPS copies images by * copying pointers, so this operation is instant, even for very large images. @@ -386,7 +372,21 @@ vips_copy_init(VipsCopy *copy) * you can turn a 4-band uchar image into a 2-band ushort image, but you * cannot change a 100 x 100 RGB image into a 300 x 100 mono image. * - * See also: vips_byteswap(), vips_bandfold(), vips_bandunfold(). + * ::: tip "Optional arguments" + * * @width: `gint`, set image width + * * @height: `gint`, set image height + * * @bands: `gint`, set image bands + * * @format: [enum@BandFormat], set image format + * * @coding: [enum@Coding], set image coding + * * @interpretation: [enum@Interpretation], set image interpretation + * * @xres: `gdouble`, set image xres + * * @yres: `gdouble`, set image yres + * * @xoffset: `gint`, set image xoffset + * * @yoffset: `gint`, set image yoffset + * + * ::: seealso + * [method@Image.byteswap], [method@Image.bandfold], + * [method@Image.bandunfold]. * * Returns: 0 on success, -1 on error. */ @@ -407,16 +407,17 @@ vips_copy(VipsImage *in, VipsImage **out, ...) * vips_copy_file: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * A simple convenience function to copy an image to a file, then copy * again to output. If the image is already a file, just copy straight * through. * - * The file is allocated with vips_image_new_temp_file(). + * The file is allocated with [ctor@Image.new_temp_file]. * The file is automatically deleted when @out is closed. * - * See also: vips_copy(), vips_image_new_temp_file(). + * ::: seealso + * [method@Image.copy], [ctor@Image.new_temp_file]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/embed.c b/libvips/conversion/embed.c index c1cbf181de..3620ebb51b 100644 --- a/libvips/conversion/embed.c +++ b/libvips/conversion/embed.c @@ -217,7 +217,7 @@ vips_embed_base_paint_edge(VipsEmbedBase *base, */ for (y = 0; y < todo.height; y++) { q = VIPS_REGION_ADDR(out_region, todo.left, todo.top + y); - memcpy(q, p, bs * todo.width); + memcpy(q, p, (size_t) bs * todo.width); } } @@ -371,7 +371,7 @@ vips_embed_base_build(VipsObject *object) if (!vips_object_argument_isset(object, "extend") && vips_object_argument_isset(object, "background")) - base->extend = VIPS_EXTEND_BACKGROUND; + base->extend = VIPS_EXTEND_BACKGROUND; // FIXME: Invalidates operation cache if (base->extend == VIPS_EXTEND_BACKGROUND) if (!(base->ink = vips__vector_to_ink( @@ -680,20 +680,19 @@ vips_embed_init(VipsEmbed *embed) * @y: place @in at this y position in @out * @width: @out should be this many pixels across * @height: @out should be this many pixels down - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * The opposite of [method@Image.extract_area]: embed @in within an image of + * size @width by @height at position @x, @y. * - * * @extend: #VipsExtend to generate the edge pixels (default: black) - * * @background: #VipsArrayDouble colour for edge pixels + * @extend controls what appears in the new pels, see [enum@Extend]. * - * The opposite of vips_extract_area(): embed @in within an image of size - * @width by @height at position @x, @y. + * ::: tip "Optional arguments" + * * @extend: [enum@Extend] to generate the edge pixels (default: [enum@Vips.Extend.BLACK]) + * * @background: [struct@ArrayDouble] colour for edge pixels * - * @extend - * controls what appears in the new pels, see #VipsExtend. - * - * See also: vips_extract_area(), vips_insert(). + * ::: seealso + * [method@Image.extract_area], [method@Image.insert]. * * Returns: 0 on success, -1 on error. */ @@ -822,26 +821,25 @@ vips_gravity_init(VipsGravity *gravity) } /** - * vips_gravity: + * vips_gravity: (method) * @in: input image * @out: output image * @direction: place @in at this direction in @out * @width: @out should be this many pixels across * @height: @out should be this many pixels down - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @extend: #VipsExtend to generate the edge pixels (default: black) - * * @background: #VipsArrayDouble colour for edge pixels + * The opposite of [method@Image.extract_area]: place @in within an image of + * size @width by @height at a certain gravity. * - * The opposite of vips_extract_area(): place @in within an image of size - * @width by @height at a certain gravity. + * @extend controls what appears in the new pels, see [enum@Extend]. * - * @extend - * controls what appears in the new pels, see #VipsExtend. + * ::: tip "Optional arguments" + * * @extend: [enum@Extend] to generate the edge pixels (default: [enum@Vips.Extend.BLACK]) + * * @background: [struct@ArrayDouble] colour for edge pixels * - * See also: vips_extract_area(), vips_insert(). + * ::: seealso + * [method@Image.extract_area], [method@Image.insert]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/extract.c b/libvips/conversion/extract.c index fe7dedad40..1307d27aa9 100644 --- a/libvips/conversion/extract.c +++ b/libvips/conversion/extract.c @@ -246,11 +246,12 @@ vips_extract_area_init(VipsExtractArea *extract) * @top: top edge of area to extract * @width: width of area to extract * @height: height of area to extract - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Extract an area from an image. The area must fit within @in. * - * See also: vips_extract_bands(), vips_smartcrop(). + * ::: seealso + * [method@Image.extract_band], [method@Image.smartcrop]. * * Returns: 0 on success, -1 on error. */ @@ -304,11 +305,12 @@ vips_crop_get_type(void) * @top: top edge of area to extract * @width: width of area to extract * @height: height of area to extract - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * A synonym for vips_extract_area(). + * A synonym for [method@Image.extract_area]. * - * See also: vips_extract_bands(), vips_smartcrop(). + * ::: seealso + * [method@Image.extract_band], [method@Image.smartcrop]. * * Returns: 0 on success, -1 on error. */ @@ -460,17 +462,17 @@ vips_extract_band_init(VipsExtractBand *extract) * @in: input image * @out: (out): output image * @band: index of first band to extract - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @n: number of bands to extract + * @...: `NULL`-terminated list of optional named arguments * * Extract a band or bands from an image. Extracting out of range is an error. * * @n defaults to 1. * - * See also: vips_extract_area(). + * ::: tip "Optional arguments" + * * @n: `gint`, number of bands to extract + * + * ::: seealso + * [method@Image.extract_area]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/falsecolour.c b/libvips/conversion/falsecolour.c index e25286e121..dfed8f85d8 100644 --- a/libvips/conversion/falsecolour.c +++ b/libvips/conversion/falsecolour.c @@ -392,14 +392,15 @@ vips_falsecolour_init(VipsFalsecolour *falsecolour) * vips_falsecolour: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Force @in to 1 band, 8-bit, then transform to * a 3-band 8-bit image with a false colour * map. The map is supposed to make small differences in brightness more * obvious. * - * See also: vips_maplut(). + * ::: seealso + * [method@Image.maplut]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/flatten.c b/libvips/conversion/flatten.c index 92754d7cd4..de6a7e9353 100644 --- a/libvips/conversion/flatten.c +++ b/libvips/conversion/flatten.c @@ -326,7 +326,7 @@ vips_flatten_build(VipsObject *object) * interpretation. */ if (!vips_object_argument_isset(object, "max_alpha")) - flatten->max_alpha = vips_interpretation_max_alpha(in->Type); + flatten->max_alpha = vips_interpretation_max_alpha(in->Type); // FIXME: Invalidates operation cache /* Is max_alpha less than the numeric range of this image? If it is, * we can get int overflow. @@ -336,8 +336,7 @@ vips_flatten_build(VipsObject *object) */ original_format = VIPS_FORMAT_NOTSET; if (vips_band_format_isint(in->BandFmt) && - flatten->max_alpha < - vips_image_get_format_max(in->BandFmt)) { + flatten->max_alpha < vips_image_get_format_max(in->BandFmt)) { original_format = in->BandFmt; if (vips_cast(in, &t[1], VIPS_FORMAT_DOUBLE, NULL)) return -1; @@ -345,8 +344,7 @@ vips_flatten_build(VipsObject *object) } t[2] = vips_image_new(); - if (vips_image_pipelinev(t[2], - VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) + if (vips_image_pipelinev(t[2], VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) return -1; t[2]->Bands -= 1; @@ -379,8 +377,7 @@ vips_flatten_build(VipsObject *object) return -1; if (vips_image_generate(t[2], - vips_start_one, vips_flatten_gen, vips_stop_one, - in, flatten)) + vips_start_one, vips_flatten_gen, vips_stop_one, in, flatten)) return -1; in = t[2]; } @@ -447,12 +444,7 @@ vips_flatten_init(VipsFlatten *flatten) * vips_flatten: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @background: #VipsArrayDouble colour for new pixels - * * @max_alpha: %gdouble, maximum value for alpha + * @...: `NULL`-terminated list of optional named arguments * * Take the last band of @in as an alpha and use it to blend the * remaining channels with @background. @@ -461,14 +453,18 @@ vips_flatten_init(VipsFlatten *flatten) * and 0 means 100% background. @background defaults to zero (black). * * @max_alpha has the default value 255, or 65535 for images tagged as - * #VIPS_INTERPRETATION_RGB16 or - * #VIPS_INTERPRETATION_GREY16. + * [enum@Vips.Interpretation.RGB16] or [enum@Vips.Interpretation.GREY16]. * * Useful for flattening PNG images to RGB. * * Non-complex images only. * - * See also: vips_premultiply(), vips_pngload(). + * ::: tip "Optional arguments" + * * @background: [struct@ArrayDouble] colour for new pixels + * * @max_alpha: `gdouble`, maximum value for alpha + * + * ::: seealso + * [method@Image.premultiply], [ctor@Image.pngload]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/flip.c b/libvips/conversion/flip.c index 0f56a12fa0..3cd160dd16 100644 --- a/libvips/conversion/flip.c +++ b/libvips/conversion/flip.c @@ -260,11 +260,12 @@ vips_flip_init(VipsFlip *flip) * @in: input image * @out: (out): output image * @direction: flip horizontally or vertically - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Flips an image left-right or up-down. * - * See also: vips_rot(). + * ::: seealso + * [method@Image.rot]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/gamma.c b/libvips/conversion/gamma.c index 92f8debd59..cb57f8356f 100644 --- a/libvips/conversion/gamma.c +++ b/libvips/conversion/gamma.c @@ -149,7 +149,7 @@ vips_gamma_class_init(VipsGammaClass *class) _("Gamma factor"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsGamma, exponent), - 0.000001, 1000.0, 2.4); + 0.000001, 1000.0, 1.0 / 2.4); } static void @@ -162,16 +162,16 @@ vips_gamma_init(VipsGamma *gamma) * vips_gamma: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @exponent: gamma, default 1.0 / 2.4 + * @...: `NULL`-terminated list of optional named arguments * * Calculate @in ** (1 / @exponent), normalising to the maximum range of the * input type. For float types use 1.0 as the maximum. * - * See also: vips_identity(), vips_pow_const1(), vips_maplut() + * ::: tip "Optional arguments" + * * @exponent: `gdouble`, gamma, default 1.0 / 2.4 + * + * ::: seealso + * [ctor@Image.identity], [method@Image.pow_const1], [method@Image.maplut] * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/grid.c b/libvips/conversion/grid.c index 83d67bbee7..759b54eef4 100644 --- a/libvips/conversion/grid.c +++ b/libvips/conversion/grid.c @@ -238,7 +238,7 @@ vips_grid_init(VipsGrid *grid) * @tile_height: chop into tiles this high * @across: tiles across * @down: tiles down - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Chop a tall thin image up into a set of tiles, lay the tiles out in a grid. * @@ -252,7 +252,8 @@ vips_grid_init(VipsGrid *grid) * only really need two of these. Requiring three is a double-check that the * image has the expected geometry. * - * See also: vips_embed(), vips_insert(), vips_join(). + * ::: seealso + * [method@Image.embed], [method@Image.insert], [method@Image.join]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/ifthenelse.c b/libvips/conversion/ifthenelse.c index b716330723..d89e7ddd9b 100644 --- a/libvips/conversion/ifthenelse.c +++ b/libvips/conversion/ifthenelse.c @@ -1,4 +1,4 @@ -/* ifthenelse.c --- use a condition image to join two images together +/* ifthenelse.c -- use a condition image to join two images together * * Modified: * 9/2/95 JC @@ -557,16 +557,12 @@ vips_ifthenelse_init(VipsIfthenelse *ifthenelse) } /** - * vips_ifthenelse: - * @cond: condition #VipsImage - * @in1: then #VipsImage - * @in2: else #VipsImage - * @out: (out): output #VipsImage - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @blend: blend smoothly between @in1 and @in2 + * vips_ifthenelse: (method) + * @cond: condition [class@Image] + * @in1: then [class@Image] + * @in2: else [class@Image] + * @out: (out): output [class@Image] + * @...: `NULL`-terminated list of optional named arguments * * This operation scans the condition image @cond * and uses it to select pixels from either the then image @in1 or the else @@ -582,12 +578,18 @@ vips_ifthenelse_init(VipsIfthenelse *ifthenelse) * If the images differ in size, the smaller images are enlarged to match the * largest by adding zero pixels along the bottom and right. * - * If @blend is %TRUE, then values in @out are smoothly blended between @in1 + * If @blend is `TRUE`, then values in @out are smoothly blended between @in1 * and @in2 using the formula: * - * @out = (@cond / 255) * @in1 + (1 - @cond / 255) * @in2 + * ``` + * out = (cond / 255) * in1 + (1 - cond / 255) * in2 + * ``` + * + * ::: tip "Optional arguments" + * * @blend: `gboolean`, blend smoothly between @in1 and @in2 * - * See also: vips_equal(). + * ::: seealso + * [method@Image.equal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/insert.c b/libvips/conversion/insert.c index ccfec3de3d..c38945db1e 100644 --- a/libvips/conversion/insert.c +++ b/libvips/conversion/insert.c @@ -139,7 +139,7 @@ vips__insert_just_one(VipsRegion *out_region, VipsRegion *ir, int x, int y) return 0; } -/* Paste in parts of ir that fall within out_region --- ir is an input REGION +/* Paste in parts of ir that fall within out_region -- ir is an input REGION * for an image positioned at pos within out_region. * * Also used by vips_arrayjoin. @@ -518,16 +518,11 @@ vips_insert_init(VipsInsert *insert) * @out: (out): output image * @x: left position of @sub * @y: top position of @sub - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @expand: expand output to hold whole of both images - * * @background: colour for new pixels + * @...: `NULL`-terminated list of optional named arguments * * Insert @sub into @main at position @x, @y. * - * Normally @out shows the whole of @main. If @expand is #TRUE then @out is + * Normally @out shows the whole of @main. If @expand is `TRUE` then @out is * made large enough to hold all of @main and @sub. * Any areas of @out not coming from * either @main or @sub are set to @background (default 0). @@ -542,9 +537,14 @@ vips_insert_init(VipsInsert *insert) * * The two input images are cast up to the smallest common type (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). + * + * ::: tip "Optional arguments" + * * @expand: `gdouble`, expand output to hold whole of both images + * * @background: [struct@ArrayDouble], colour for new pixels * - * See also: vips_join(), vips_embed(), vips_extract_area(). + * ::: seealso + * [method@Image.join], [method@Image.embed], [method@Image.extract_area]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/join.c b/libvips/conversion/join.c index ef7896d5d3..f0c181b976 100644 --- a/libvips/conversion/join.c +++ b/libvips/conversion/join.c @@ -81,7 +81,7 @@ typedef struct _VipsJoin { VipsDirection direction; gboolean expand; int shim; - VipsArea *background; + VipsArrayDouble *background; VipsAlign align; } VipsJoin; @@ -284,33 +284,22 @@ vips_join_class_init(VipsJoinClass *class) static void vips_join_init(VipsJoin *join) { - /* Init our instance fields. - */ - join->background = - vips_area_new_array(G_TYPE_DOUBLE, sizeof(double), 1); - ((double *) (join->background->data))[0] = 0.0; + join->background = vips_array_double_newv(1, 0.0); } /** - * vips_join: + * vips_join: (method) * @in1: first input image * @in2: second input image * @out: (out): output image * @direction: join horizontally or vertically - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @expand: %TRUE to expand the output image to hold all of the input pixels - * * @shim: space between images, in pixels - * * @background: background ink colour - * * @align: low, centre or high alignment + * @...: `NULL`-terminated list of optional named arguments * * Join @in1 and @in2 together, left-right or up-down depending on the value * of @direction. * * If one is taller or wider than the - * other, @out will be has high as the smaller. If @expand is %TRUE, then + * other, @out will be has high as the smaller. If @expand is `TRUE`, then * the output will be expanded to contain all of the input pixels. * * Use @align to set the edge that the images align on. By default, they align @@ -328,12 +317,20 @@ vips_join_init(VipsJoin *join) * * The two input images are cast up to the smallest common type (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). * * If you are going to be joining many thousands of images in a regular - * grid, vips_arrayjoin() is a better choice. + * grid, [func@Image.arrayjoin] is a better choice. + * + * ::: tip "Optional arguments" + * * @expand: `gboolean`, `TRUE` to expand the output image to hold all of + * the input pixels + * * @shim: `gint`, space between images, in pixels + * * @background: [struct@ArrayDouble], background ink colour + * * @align: [enumAlign], low, centre or high alignment * - * See also: vips_arrayjoin(), vips_insert(). + * ::: seealso + * [func@Image.arrayjoin], [method@Image.insert]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/msb.c b/libvips/conversion/msb.c index f27bc7ef33..d0d83711b8 100644 --- a/libvips/conversion/msb.c +++ b/libvips/conversion/msb.c @@ -254,7 +254,7 @@ vips_msb_class_init(VipsMsbClass *class) _("Band to msb"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsMsb, band), - 0, 100000000, 0); + -1, 100000000, -1); } static void @@ -267,11 +267,7 @@ vips_msb_init(VipsMsb *msb) * vips_msb: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @band: %gint, msb just this band + * @...: `NULL`-terminated list of optional named arguments * * Turn any integer image to 8-bit unsigned char by discarding all but the most * significant byte. Signed values are converted to unsigned by adding 128. @@ -280,7 +276,11 @@ vips_msb_init(VipsMsb *msb) * * This operator also works for LABQ coding. * - * See also: vips_scale(), vips_cast(). + * ::: tip "Optional arguments" + * * @band: `gint`, msb just this band + * + * ::: seealso + * [method@Image.scale], [method@Image.cast]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/premultiply.c b/libvips/conversion/premultiply.c index 335964013f..31910f5e50 100644 --- a/libvips/conversion/premultiply.c +++ b/libvips/conversion/premultiply.c @@ -224,7 +224,7 @@ vips_premultiply_build(VipsObject *object) * interpretation. */ if (!vips_object_argument_isset(object, "max_alpha")) - premultiply->max_alpha = vips_interpretation_max_alpha(in->Type); + premultiply->max_alpha = vips_interpretation_max_alpha(in->Type); // FIXME: Invalidates operation cache if (in->BandFmt == VIPS_FORMAT_DOUBLE) conversion->out->BandFmt = VIPS_FORMAT_DOUBLE; @@ -281,21 +281,17 @@ vips_premultiply_init(VipsPremultiply *premultiply) * vips_premultiply: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @max_alpha: %gdouble, maximum value for alpha + * @...: `NULL`-terminated list of optional named arguments * * Premultiplies any alpha channel. - * The final band is taken to be the alpha - * and the bands are transformed as: * - * |[ - * alpha = clip(0, in[in.bands - 1], @max_alpha); - * norm = alpha / @max_alpha; - * out = [in[0] * norm, ..., in[in.bands - 1] * norm, alpha]; - * ]| + * The final band is taken to be the alpha and the bands are transformed as: + * + * ``` + * alpha = clip(0, in[in.bands - 1], max_alpha) + * norm = alpha / max_alpha + * out = [in[0] * norm, ..., in[in.bands - 1] * norm, alpha] + * ``` * * So for an N-band image, the first N - 1 bands are multiplied by the clipped * and normalised final band, the final band is clipped. @@ -303,16 +299,20 @@ vips_premultiply_init(VipsPremultiply *premultiply) * the image is passed through unaltered. * * The result is - * #VIPS_FORMAT_FLOAT unless the input format is #VIPS_FORMAT_DOUBLE, in which - * case the output is double as well. + * [enum@Vips.BandFormat.FLOAT] unless the input format is + * [enum@Vips.BandFormat.DOUBLE], in which case the output is double as well. * * @max_alpha has the default value 255, or 65535 for images tagged as - * #VIPS_INTERPRETATION_RGB16 or - * #VIPS_INTERPRETATION_GREY16. + * [enum@Vips.Interpretation.RGB16] or [enum@Vips.Interpretation.GREY16], and + * 1.0 for images tagged as [enum@Vips.Interpretation.scRGB]. * * Non-complex images only. * - * See also: vips_unpremultiply(), vips_flatten(). + * ::: tip "Optional arguments" + * * @max_alpha: `gdouble`, maximum value for alpha + * + * ::: seealso + * [method@Image.unpremultiply], [method@Image.flatten]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/recomb.c b/libvips/conversion/recomb.c index 8bf50558e7..b5c3b9c6b3 100644 --- a/libvips/conversion/recomb.c +++ b/libvips/conversion/recomb.c @@ -243,7 +243,7 @@ vips_recomb_init(VipsRecomb *recomb) * @in: input image * @out: (out): output image * @m: recombination matrix - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation recombines an image's bands. Each pixel in @in is treated as * an n-element vector, where n is the number of bands in @in, and multiplied by @@ -254,7 +254,8 @@ vips_recomb_init(VipsRecomb *recomb) * * It's useful for various sorts of colour space conversions. * - * See also: vips_bandmean(). + * ::: seealso + * [method@Image.bandmean]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/replicate.c b/libvips/conversion/replicate.c index 5f33b3fb7f..b828f589ad 100644 --- a/libvips/conversion/replicate.c +++ b/libvips/conversion/replicate.c @@ -224,11 +224,12 @@ vips_replicate_init(VipsReplicate *replicate) * @out: (out): output image * @across: repeat input this many times across * @down: repeat input this many times down - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Repeats an image many times. * - * See also: vips_extract_area(). + * ::: seealso + * [method@Image.extract_area]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/rot.c b/libvips/conversion/rot.c index 9e9bab811e..0daf1ecad7 100644 --- a/libvips/conversion/rot.c +++ b/libvips/conversion/rot.c @@ -391,14 +391,15 @@ vips_rotv(VipsImage *in, VipsImage **out, VipsAngle angle, va_list ap) * @in: input image * @out: (out): output image * @angle: rotation angle - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Rotate @in by a multiple of 90 degrees. * - * Use vips_similarity() to rotate by an arbitrary angle. vips_rot45() is - * useful for rotating convolution masks by 45 degrees. + * Use [method@Image.similarity] to rotate by an arbitrary angle. + * [method@Image.rot45] is useful for rotating convolution masks by 45 degrees. * - * See also: vips_flip(), vips_similarity(), vips_rot45(). + * ::: seealso + * [method@Image.flip], [method@Image.similarity], [method@Image.rot45]. * * Returns: 0 on success, -1 on error */ @@ -416,14 +417,15 @@ vips_rot(VipsImage *in, VipsImage **out, VipsAngle angle, ...) } /** - * vips_rot90: + * vips_rot90: (method) * @in: input image * @out: output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Rotate @in by 90 degrees clockwise. A convenience function over vips_rot(). + * Rotate @in by 90 degrees clockwise. A convenience function over [method@Image.rot]. * - * See also: vips_rot(). + * ::: seealso + * [method@Image.rot]. * * Returns: 0 on success, -1 on error */ @@ -444,11 +446,12 @@ vips_rot90(VipsImage *in, VipsImage **out, ...) * vips_rot180: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Rotate @in by 180 degrees. A convenience function over vips_rot(). + * Rotate @in by 180 degrees. A convenience function over [method@Image.rot]. * - * See also: vips_rot(). + * ::: seealso + * [method@Image.rot]. * * Returns: 0 on success, -1 on error */ @@ -469,11 +472,12 @@ vips_rot180(VipsImage *in, VipsImage **out, ...) * vips_rot270: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Rotate @in by 270 degrees clockwise. A convenience function over vips_rot(). + * Rotate @in by 270 degrees clockwise. A convenience function over [method@Image.rot]. * - * See also: vips_rot(). + * ::: seealso + * [method@Image.rot]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/rot45.c b/libvips/conversion/rot45.c index 440930b36c..6a754796b5 100644 --- a/libvips/conversion/rot45.c +++ b/libvips/conversion/rot45.c @@ -288,19 +288,19 @@ vips_rot45_init(VipsRot45 *rot45) * vips_rot45: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @angle: #VipsAngle45 rotation angle + * @...: `NULL`-terminated list of optional named arguments * * Rotate @in by a multiple of 45 degrees. Odd-length sides and square images * only. * * This operation is useful for rotating convolution masks. Use - * vips_similarity() to rotate images by arbitrary angles. + * [method@Image.similarity] to rotate images by arbitrary angles. + * + * ::: tip "Optional arguments" + * * @angle: [enum@Angle45], rotation angle * - * See also: vips_rot(), vips_similarity(). + * ::: seealso + * [method@Image.rot], [method@Image.similarity]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/scale.c b/libvips/conversion/scale.c index 4a51fe0e82..3170fa1967 100644 --- a/libvips/conversion/scale.c +++ b/libvips/conversion/scale.c @@ -182,12 +182,7 @@ vips_scale_init(VipsScale *scale) * vips_scale: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @log: log scale pixels - * * @exp: exponent for log scale + * @...: `NULL`-terminated list of optional named arguments * * Search the image for the maximum and minimum value, then return the image * as unsigned 8-bit, scaled so that the maximum value is 255 and the @@ -196,7 +191,12 @@ vips_scale_init(VipsScale *scale) * If @log is set, transform with log10(1.0 + pow(x, @exp)) + .5, * then scale so max == 255. By default, @exp is 0.25. * - * See also: vips_cast(). + * ::: tip "Optional arguments" + * * @log: `gboolean`, log scale pixels + * * @exp: `gdouble`, exponent for log scale + * + * ::: seealso + * [method@Image.cast]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/sequential.c b/libvips/conversion/sequential.c index 07860f235b..a1d6afa63c 100644 --- a/libvips/conversion/sequential.c +++ b/libvips/conversion/sequential.c @@ -84,7 +84,7 @@ typedef struct _VipsSequential { /* Lock access to y_pos with this. */ - GMutex *lock; + GMutex lock; /* The next read from our source will fetch this scanline, ie. it's 0 * when we start. @@ -102,13 +102,13 @@ typedef VipsConversionClass VipsSequentialClass; G_DEFINE_TYPE(VipsSequential, vips_sequential, VIPS_TYPE_CONVERSION); static void -vips_sequential_dispose(GObject *gobject) +vips_sequential_finalize(GObject *gobject) { VipsSequential *sequential = (VipsSequential *) gobject; - VIPS_FREEF(vips_g_mutex_free, sequential->lock); + g_mutex_clear(&sequential->lock); - G_OBJECT_CLASS(vips_sequential_parent_class)->dispose(gobject); + G_OBJECT_CLASS(vips_sequential_parent_class)->finalize(gobject); } static int @@ -126,14 +126,14 @@ vips_sequential_generate(VipsRegion *out_region, VIPS_GATE_START("vips_sequential_generate: wait"); - vips__worker_lock(sequential->lock); + vips__worker_lock(&sequential->lock); VIPS_GATE_STOP("vips_sequential_generate: wait"); /* If we've seen an error, everything must stop. */ if (sequential->error) { - g_mutex_unlock(sequential->lock); + g_mutex_unlock(&sequential->lock); return -1; } @@ -157,7 +157,7 @@ vips_sequential_generate(VipsRegion *out_region, area.height = VIPS_MIN(sequential->tile_height, r->top - area.top); if (vips_region_prepare(ir, &area)) { sequential->error = -1; - g_mutex_unlock(sequential->lock); + g_mutex_unlock(&sequential->lock); return -1; } @@ -172,13 +172,13 @@ vips_sequential_generate(VipsRegion *out_region, if (vips_region_prepare(ir, r) || vips_region_region(out_region, ir, r, r->left, r->top)) { sequential->error = -1; - g_mutex_unlock(sequential->lock); + g_mutex_unlock(&sequential->lock); return -1; } sequential->y_pos = VIPS_MAX(sequential->y_pos, VIPS_RECT_BOTTOM(r)); - g_mutex_unlock(sequential->lock); + g_mutex_unlock(&sequential->lock); return 0; } @@ -231,7 +231,7 @@ vips_sequential_class_init(VipsSequentialClass *class) VIPS_DEBUG_MSG("vips_sequential_class_init\n"); - gobject_class->dispose = vips_sequential_dispose; + gobject_class->finalize = vips_sequential_finalize; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -270,7 +270,7 @@ vips_sequential_class_init(VipsSequentialClass *class) static void vips_sequential_init(VipsSequential *sequential) { - sequential->lock = vips_g_mutex_new(); + g_mutex_init(&sequential->lock); sequential->tile_height = 1; sequential->error = 0; sequential->trace = FALSE; @@ -280,21 +280,21 @@ vips_sequential_init(VipsSequential *sequential) * vips_sequential: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @tile_height: height of cache strips - * - * This operation behaves rather like vips_copy() between images + * This operation behaves rather like [method@Image.copy] between images * @in and @out, except that it checks that pixels on @in are only requested * top-to-bottom. This operation is useful for loading file formats which are * strictly top-to-bottom, like PNG. * * @tile_height can be used to set the size of the tiles that - * vips_sequential() uses. The default value is 1. + * [method@Image.sequential] uses. The default value is 1. + * + * ::: tip "Optional arguments" + * * @tile_height: `gint`, height of cache strips * - * See also: vips_cache(), vips_linecache(), vips_tilecache(). + * ::: seealso + * [method@Image.linecache], [method@Image.tilecache]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/smartcrop.c b/libvips/conversion/smartcrop.c index d4b758878b..481fdbc4bb 100644 --- a/libvips/conversion/smartcrop.c +++ b/libvips/conversion/smartcrop.c @@ -386,8 +386,8 @@ vips_smartcrop_build(VipsObject *object) case VIPS_INTERESTING_ALL: left = 0; top = 0; - smartcrop->width = in->Xsize; - smartcrop->height = in->Ysize; + smartcrop->width = in->Xsize; // FIXME: Invalidates operation cache + smartcrop->height = in->Ysize; // FIXME: Invalidates operation cache break; default: @@ -491,14 +491,7 @@ vips_smartcrop_init(VipsSmartcrop *smartcrop) * @out: (out): output image * @width: width of area to extract * @height: height of area to extract - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @interesting: #VipsInteresting to use to find interesting areas (default: #VIPS_INTERESTING_ATTENTION) - * * @premultiplied: %gboolean, input image already has premultiplied alpha - * * @attention_x: %gint, horizontal position of attention centre when using attention based cropping - * * @attention_y: %gint, vertical position of attention centre when using attention based cropping + * @...: `NULL`-terminated list of optional named arguments * * Crop an image down to a specified width and height by removing boring parts. * @@ -508,7 +501,17 @@ vips_smartcrop_init(VipsSmartcrop *smartcrop) * You can test xoffset / yoffset on @out to find the location of the crop * within the input image. * - * See also: vips_extract_area(). + * ::: tip "Optional arguments" + * * @interesting: [enum@Interesting] to use to find interesting areas + * (default: [enum@Vips.Interesting.ATTENTION]) + * * @premultiplied: `gboolean`, input image already has premultiplied alpha + * * @attention_x: `gint`, horizontal position of attention centre when + * using attention based cropping (output) + * * @attention_y: `gint`, vertical position of attention centre when + * using attention based cropping (output) + * + * ::: seealso + * [method@Image.extract_area]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/subsample.c b/libvips/conversion/subsample.c index 461d261fb2..c5a6b06caf 100644 --- a/libvips/conversion/subsample.c +++ b/libvips/conversion/subsample.c @@ -302,11 +302,7 @@ vips_subsample_init(VipsSubsample *subsample) * @out: (out): output image * @xfac: horizontal shrink factor * @yfac: vertical shrink factor - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @point: turn on point sample mode + * @...: `NULL`-terminated list of optional named arguments * * Subsample an image by an integer fraction. This is fast, nearest-neighbour * shrink. @@ -318,7 +314,11 @@ vips_subsample_init(VipsSubsample *subsample) * If @point is set, @in will always be sampled in points. This can be faster * if the previous operations in the pipeline are very slow. * - * See also: vips_affine(), vips_shrink(), vips_zoom(). + * ::: tip "Optional arguments" + * * @point: `gboolean`, turn on point sample mode + * + * ::: seealso + * [method@Image.affine], [method@Image.shrink], [method@Image.zoom]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/switch.c b/libvips/conversion/switch.c index 1e2bc31e24..199edd3c06 100644 --- a/libvips/conversion/switch.c +++ b/libvips/conversion/switch.c @@ -228,7 +228,7 @@ vips_switchv(VipsImage **tests, VipsImage **out, int n, va_list ap) * @tests: (array length=n): test these images * @out: (out): output index image * @n: number of input images - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * The @tests images are evaluated and at each point the index of the first * non-zero value is written to @out. If all @tests are false, the value @@ -238,9 +238,10 @@ vips_switchv(VipsImage **tests, VipsImage **out, int n, va_list ap) * bounding box of the set of images in @tests, and that size is used for * @out. @tests can have up to 255 elements. * - * Combine with vips_case() to make an efficient multi-way vips_ifthenelse(). + * Combine with [method@Image.case] to make an efficient multi-way [method@Image.ifthenelse]. * - * See also: vips_maplut(), vips_case(), vips_ifthenelse(). + * ::: seealso + * [method@Image.maplut], [method@Image.case], [method@Image.ifthenelse]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/tilecache.c b/libvips/conversion/tilecache.c index 0e4d2f302e..5c6ed65b0d 100644 --- a/libvips/conversion/tilecache.c +++ b/libvips/conversion/tilecache.c @@ -129,8 +129,8 @@ typedef struct _VipsBlockCache { gboolean threaded; gboolean persistent; - GMutex *lock; /* Lock everything here */ - GCond *new_tile; /* A new tile is ready */ + GMutex lock; /* Lock everything here */ + GCond new_tile; /* A new tile is ready */ GHashTable *tiles; /* Tiles, hashed by coordinates */ GQueue *recycle; /* Queue of unreffed tiles to reuse */ } VipsBlockCache; @@ -152,14 +152,23 @@ vips_block_cache_drop_all(VipsBlockCache *cache) g_hash_table_remove_all(cache->tiles); } +static void +vips_block_cache_finalize(GObject *gobject) +{ + VipsBlockCache *cache = (VipsBlockCache *) gobject; + + g_mutex_clear(&cache->lock); + g_cond_clear(&cache->new_tile); + + G_OBJECT_CLASS(vips_block_cache_parent_class)->finalize(gobject); +} + static void vips_block_cache_dispose(GObject *gobject) { VipsBlockCache *cache = (VipsBlockCache *) gobject; vips_block_cache_drop_all(cache); - VIPS_FREEF(vips_g_mutex_free, cache->lock); - VIPS_FREEF(vips_g_cond_free, cache->new_tile); if (cache->tiles) g_assert(g_hash_table_size(cache->tiles) == 0); @@ -342,14 +351,14 @@ vips_block_cache_minimise(VipsImage *image, VipsBlockCache *cache) { VIPS_DEBUG_MSG("vips_block_cache_minimise:\n"); - g_mutex_lock(cache->lock); + g_mutex_lock(&cache->lock); /* We can't drop tiles that are in use. */ g_hash_table_foreach_remove(cache->tiles, vips_tile_unlocked, NULL); - g_mutex_unlock(cache->lock); + g_mutex_unlock(&cache->lock); } static int @@ -384,6 +393,7 @@ vips_block_cache_class_init(VipsBlockCacheClass *class) VIPS_DEBUG_MSG("vips_block_cache_class_init\n"); + gobject_class->finalize = vips_block_cache_finalize; gobject_class->dispose = vips_block_cache_dispose; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -481,8 +491,8 @@ vips_block_cache_init(VipsBlockCache *cache) cache->threaded = FALSE; cache->persistent = FALSE; - cache->lock = vips_g_mutex_new(); - cache->new_tile = vips_g_cond_new(); + g_mutex_init(&cache->lock); + g_cond_init(&cache->new_tile); cache->tiles = g_hash_table_new_full( (GHashFunc) vips_rect_hash, (GEqualFunc) vips_rect_equal, @@ -615,7 +625,7 @@ vips_tile_cache_gen(VipsRegion *out_region, VIPS_GATE_START("vips_tile_cache_gen: wait1"); - vips__worker_lock(cache->lock); + vips__worker_lock(&cache->lock); VIPS_GATE_STOP("vips_tile_cache_gen: wait1"); @@ -674,7 +684,7 @@ vips_tile_cache_gen(VipsRegion *out_region, * mode, we keep the lock and make 'em wait. */ if (cache->threaded) - g_mutex_unlock(cache->lock); + g_mutex_unlock(&cache->lock); /* Don't compute if we've seen an error * previously. @@ -688,7 +698,7 @@ vips_tile_cache_gen(VipsRegion *out_region, if (cache->threaded) { VIPS_GATE_START("vips_tile_cache_gen: wait2"); - g_mutex_lock(cache->lock); + g_mutex_lock(&cache->lock); VIPS_GATE_STOP("vips_tile_cache_gen: wait2"); } @@ -718,7 +728,7 @@ vips_tile_cache_gen(VipsRegion *out_region, /* Let everyone know there's a new DATA tile. * They need to all check their work lists. */ - g_cond_broadcast(cache->new_tile); + g_cond_broadcast(&cache->new_tile); break; } @@ -741,7 +751,7 @@ vips_tile_cache_gen(VipsRegion *out_region, VIPS_GATE_START("vips_tile_cache_gen: wait3"); - vips__worker_cond_wait(cache->new_tile, cache->lock); + vips__worker_cond_wait(&cache->new_tile, &cache->lock); VIPS_GATE_STOP("vips_tile_cache_gen: wait3"); @@ -749,7 +759,7 @@ vips_tile_cache_gen(VipsRegion *out_region, } } - g_mutex_unlock(cache->lock); + g_mutex_unlock(&cache->lock); return result; } @@ -820,42 +830,43 @@ vips_tile_cache_init(VipsTileCache *cache) * vips_tilecache: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: * - * * @tile_width: width of tiles in cache - * * @tile_height: height of tiles in cache - * * @max_tiles: maximum number of tiles to cache - * * @access: hint expected access pattern #VipsAccess - * * @threaded: allow many threads - * * @persistent: don't drop cache at end of computation - * - * This operation behaves rather like vips_copy() between images + * This operation behaves rather like [method@Image.copy] between images * @in and @out, except that it keeps a cache of computed pixels. * This cache is made of up to @max_tiles tiles (a value of -1 * means any number of tiles), and each tile is of size @tile_width * by @tile_height pixels. * * Each cache tile is made with a single call to - * vips_region_prepare(). + * [method@Region.prepare]. * * When the cache fills, a tile is chosen for reuse. If @access is - * #VIPS_ACCESS_RANDOM, then the least-recently-used tile is reused. If - * @access is #VIPS_ACCESS_SEQUENTIAL + * [enum@Vips.Access.RANDOM], then the least-recently-used tile is reused. If + * @access is [enum@Vips.Access.SEQUENTIAL] * the top-most tile is reused. * * By default, @tile_width and @tile_height are 128 pixels, and the operation - * will cache up to 1,000 tiles. @access defaults to #VIPS_ACCESS_RANDOM. + * will cache up to 1,000 tiles. @access defaults to [enum@Vips.Access.RANDOM]. * * Normally, only a single thread at once is allowed to calculate tiles. If - * you set @threaded to %TRUE, vips_tilecache() will allow many threads to - * calculate tiles at once, and share the cache between them. + * you set @threaded to `TRUE`, [method@Image.tilecache] will allow many + * threads to calculate tiles at once, and share the cache between them. * * Normally the cache is dropped when computation finishes. Set @persistent to - * %TRUE to keep the cache between computations. + * `TRUE` to keep the cache between computations. + * + * ::: tip "Optional arguments" + * * @tile_width: `gint`, width of tiles in cache + * * @tile_height: `gint`, height of tiles in cache + * * @max_tiles: `gint`, maximum number of tiles to cache + * * @access: [enum@Access], hint expected access pattern + * * @threaded: `gboolean`, allow many threads + * * @persistent: `gboolean`, don't drop cache at end of computation * - * See also: vips_cache(), vips_linecache(). + * ::: seealso + * [method@Image.linecache]. * * Returns: 0 on success, -1 on error. */ @@ -889,7 +900,7 @@ vips_line_cache_gen(VipsRegion *out_region, VIPS_GATE_START("vips_line_cache_gen: wait"); - vips__worker_lock(block_cache->lock); + vips__worker_lock(&block_cache->lock); VIPS_GATE_STOP("vips_line_cache_gen: wait"); @@ -897,13 +908,13 @@ vips_line_cache_gen(VipsRegion *out_region, */ if (out_region->valid.height > block_cache->max_tiles * block_cache->tile_height) { - block_cache->max_tiles = + block_cache->max_tiles = // FIXME: Invalidates operation cache 1 + (out_region->valid.height / block_cache->tile_height); VIPS_DEBUG_MSG("vips_line_cache_gen: bumped max_tiles to %d\n", block_cache->max_tiles); } - g_mutex_unlock(block_cache->lock); + g_mutex_unlock(&block_cache->lock); return vips_tile_cache_gen(out_region, seq, a, b, stop); } @@ -922,7 +933,7 @@ vips_line_cache_build(VipsObject *object) VIPS_DEBUG_MSG("vips_line_cache_build\n"); if (!vips_object_argument_isset(object, "access")) - block_cache->access = VIPS_ACCESS_SEQUENTIAL; + block_cache->access = VIPS_ACCESS_SEQUENTIAL; // FIXME: Invalidates operation cache if (VIPS_OBJECT_CLASS(vips_line_cache_parent_class)->build(object)) return -1; @@ -931,7 +942,7 @@ vips_line_cache_build(VipsObject *object) */ vips_get_tile_size(block_cache->in, &tile_width, &tile_height, &n_lines); - block_cache->tile_width = block_cache->in->Xsize; + block_cache->tile_width = block_cache->in->Xsize; // FIXME: Invalidates operation cache /* Output has two buffers n_lines height, so 2 * n_lines is the maximum * non-locality from threading. Double again for conv, rounding, etc. @@ -941,7 +952,7 @@ vips_line_cache_build(VipsObject *object) * minimum of two strips, so we can handle requests that straddle a * tile boundary. */ - block_cache->max_tiles = VIPS_MAX(2, + block_cache->max_tiles = VIPS_MAX(2, // FIXME: Invalidates operation cache 4 * n_lines / block_cache->tile_height); VIPS_DEBUG_MSG("vips_line_cache_build: n_lines = %d\n", @@ -993,36 +1004,35 @@ vips_line_cache_init(VipsLineCache *cache) * vips_linecache: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @access: hint expected access pattern #VipsAccess - * * @tile_height: height of tiles in cache - * * @threaded: allow many threads - * - * This operation behaves rather like vips_copy() between images + * This operation behaves rather like [method@Image.copy] between images * @in and @out, except that it keeps a cache of computed scanlines. * * The number of lines cached is enough for a small amount of non-local * access. * - * Each cache tile is made with a single call to - * vips_region_prepare(). + * Each cache tile is made with a single call to [method@Region.prepare]. * * When the cache fills, a tile is chosen for reuse. If @access is - * #VIPS_ACCESS_RANDOM, then the least-recently-used tile is reused. If - * @access is #VIPS_ACCESS_SEQUENTIAL, then - * the top-most tile is reused. @access defaults to #VIPS_ACCESS_RANDOM. + * [enum@Vips.Access.RANDOM], then the least-recently-used tile is reused. If + * @access is [enum@Vips.Access.SEQUENTIAL], then + * the top-most tile is reused. @access defaults to [enum@Vips.Access.RANDOM]. * * @tile_height can be used to set the size of the strips that - * vips_linecache() uses. The default is 1 (a single scanline). + * [method@Image.linecache] uses. The default is 1 (a single scanline). * * Normally, only a single thread at once is allowed to calculate tiles. If - * you set @threaded to %TRUE, vips_linecache() will allow many threads to - * calculate tiles at once and share the cache between them. + * you set @threaded to `TRUE`, [method@Image.linecache] will allow many + * threads to calculate tiles at once and share the cache between them. + * + * ::: tip "Optional arguments" + * * @access: [enum@Access], hint expected access pattern + * * @tile_height: `gint`, height of tiles in cache + * * @threaded: `gboolean`, allow many threads * - * See also: vips_cache(), vips_tilecache(). + * ::: seealso + * [method@Image.tilecache]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/conversion/transpose3d.c b/libvips/conversion/transpose3d.c index 4151ed44bd..8334c0691a 100644 --- a/libvips/conversion/transpose3d.c +++ b/libvips/conversion/transpose3d.c @@ -126,7 +126,7 @@ vips_transpose3d_build(VipsObject *object) if (!vips_object_argument_isset(object, "page_height")) { if (vips_image_get_int(in, - VIPS_META_PAGE_HEIGHT, &transpose3d->page_height)) + VIPS_META_PAGE_HEIGHT, &transpose3d->page_height)) // FIXME: Invalidates operation cache return -1; } @@ -186,27 +186,27 @@ vips_transpose3d_init(VipsTranspose3d *transpose3d) * vips_transpose3d: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page_height: %gint, size of each input page + * @...: `NULL`-terminated list of optional named arguments * * Transpose a volumetric image. * * Volumetric images are very tall, thin images, with the metadata item - * #VIPS_META_PAGE_HEIGHT set to the height of each sub-image. + * [const@META_PAGE_HEIGHT] set to the height of each sub-image. * * This operation swaps the two major dimensions, so that page N in the * output contains the Nth scanline, in order, from each input page. * - * You can override the #VIPS_META_PAGE_HEIGHT metadata item with the optional + * You can override the [const@META_PAGE_HEIGHT] metadata item with the optional * @page_height parameter. * - * #VIPS_META_PAGE_HEIGHT in the output image is the number of pages in the + * [const@META_PAGE_HEIGHT] in the output image is the number of pages in the * input image. * - * See also: vips_grid(). + * ::: tip "Optional arguments" + * * @page_height: `gint`, size of each input page + * + * ::: seealso + * [method@Image.grid]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/unpremultiply.c b/libvips/conversion/unpremultiply.c index afec9ff575..80bdb7d8ce 100644 --- a/libvips/conversion/unpremultiply.c +++ b/libvips/conversion/unpremultiply.c @@ -138,7 +138,7 @@ G_DEFINE_TYPE(VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION); \ for (x = 0; x < width; x++) { \ IN alpha = p[alpha_band]; \ - OUT factor = VIPS_ABS(alpha) < 0.01 ? 0 : max_alpha / alpha; \ + OUT factor = fabs(alpha) < 0.01 ? 0 : max_alpha / alpha; \ \ for (i = 0; i < alpha_band; i++) \ q[i] = factor * p[i]; \ @@ -158,7 +158,7 @@ G_DEFINE_TYPE(VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION); \ for (x = 0; x < width; x++) { \ IN alpha = p[3]; \ - OUT factor = VIPS_ABS(alpha) < 0.01 ? 0 : max_alpha / alpha; \ + OUT factor = fabs(alpha) < 0.01 ? 0 : max_alpha / alpha; \ \ q[0] = factor * p[0]; \ q[1] = factor * p[1]; \ @@ -281,12 +281,12 @@ vips_unpremultiply_build(VipsObject *object) * interpretation. */ if (!vips_object_argument_isset(object, "max_alpha")) - unpremultiply->max_alpha = vips_interpretation_max_alpha(in->Type); + unpremultiply->max_alpha = vips_interpretation_max_alpha(in->Type); // FIXME: Invalidates operation cache /* 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; + unpremultiply->alpha_band = in->Bands - 1; // FIXME: Invalidates operation cache if (in->BandFmt == VIPS_FORMAT_DOUBLE) conversion->out->BandFmt = VIPS_FORMAT_DOUBLE; @@ -350,41 +350,41 @@ vips_unpremultiply_init(VipsUnpremultiply *unpremultiply) * vips_unpremultiply: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @max_alpha: %gdouble, maximum value for alpha - * * @alpha_band: %gint, band containing alpha data + * @...: `NULL`-terminated list of optional named arguments * * Unpremultiplies any alpha channel. + * * 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); - * norm = (double) alpha / @max_alpha; + * ``` + * alpha = (int) clip(0, in[in.bands - 1], max_alpha); + * norm = (double) alpha / max_alpha * if (alpha == 0) - * out = [0, ..., 0, alpha]; + * out = [0, ..., 0, alpha] * else - * out = [in[0] / norm, ..., in[in.bands - 1] / norm, alpha]; - * ]| + * out = [in[0] / norm, ..., in[in.bands - 1] / norm, alpha] + * ``` * * 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. * - * The result is - * #VIPS_FORMAT_FLOAT unless the input format is #VIPS_FORMAT_DOUBLE, in which - * case the output is double as well. + * The result is [enum@Vips.BandFormat.FLOAT] unless the input format is + * [enum@Vips.BandFormat.DOUBLE], in which case the output is double as well. * * @max_alpha has the default value 255, or 65535 for images tagged as - * #VIPS_INTERPRETATION_RGB16 or - * #VIPS_INTERPRETATION_GREY16. + * [enum@Vips.Interpretation.RGB16] or [enum@Vips.Interpretation.GREY16], and + * 1.0 for images tagged as [enum@Vips.Interpretation.scRGB. * * Non-complex images only. * - * See also: vips_premultiply(), vips_flatten(). + * ::: tip "Optional arguments" + * * @max_alpha: `gdouble`, maximum value for alpha + * * @alpha_band: `gint`, band containing alpha data + * + * ::: seealso + * [method@Image.premultiply], [method@Image.flatten]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/wrap.c b/libvips/conversion/wrap.c index 29a43b9d6f..9d725eddcb 100644 --- a/libvips/conversion/wrap.c +++ b/libvips/conversion/wrap.c @@ -76,9 +76,9 @@ vips_wrap_build(VipsObject *object) return -1; if (!vips_object_argument_isset(object, "x")) - wrap->x = wrap->in->Xsize / 2; + wrap->x = wrap->in->Xsize / 2; // FIXME: Invalidates operation cache if (!vips_object_argument_isset(object, "y")) - wrap->y = wrap->in->Ysize / 2; + wrap->y = wrap->in->Ysize / 2; // FIXME: Invalidates operation cache /* Clock arithmetic: we want negative x/y to wrap around * nicely. @@ -145,18 +145,19 @@ vips_wrap_init(VipsWrap *wrap) * vips_wrap: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Slice an image up and move the segments about so that the pixel that was + * at 0, 0 is now at @x, @y. * - * * @x: horizontal displacement - * * @y: vertical displacement + * If @x and @y are not set, they default to the centre of the image. * - * Slice an image up and move the segments about so that the pixel that was - * at 0, 0 is now at @x, @y. If @x and @y are not set, they default to the - * centre of the image. + * ::: tip "Optional arguments" + * * @x: horizontal displacement + * * @y: vertical displacement * - * See also: vips_embed(), vips_replicate(). + * ::: seealso + * [method@Image.embed], [method@Image.replicate]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/conversion/zoom.c b/libvips/conversion/zoom.c index b1c99c748e..3051747099 100644 --- a/libvips/conversion/zoom.c +++ b/libvips/conversion/zoom.c @@ -401,12 +401,13 @@ vips_zoom_init(VipsZoom *zoom) * @out: (out): output image * @xfac: horizontal scale factor * @yfac: vertical scale factor - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Zoom an image by repeating pixels. This is fast nearest-neighbour * zoom. * - * See also: vips_affine(), vips_subsample(). + * ::: seealso + * [method@Image.affine], [method@Image.subsample]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/convolution/canny.c b/libvips/convolution/canny.c index 9571f16f8e..d5afa8f07a 100644 --- a/libvips/convolution/canny.c +++ b/libvips/convolution/canny.c @@ -476,12 +476,7 @@ vips_canny_init(VipsCanny *canny) * vips_canny: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @sigma: %gdouble, sigma for gaussian blur - * * @precision: #VipsPrecision, calculation accuracy + * @...: `NULL`-terminated list of optional named arguments * * Find edges by Canny's method: The maximum of the derivative of the gradient * in the direction of the gradient. Output is float, except for uchar input, @@ -492,13 +487,18 @@ vips_canny_init(VipsCanny *canny) * usually a good value. * * Use @precision to set the precision of edge detection. For uchar images, - * setting this to #VIPS_PRECISION_INTEGER will make edge detection much + * setting this to [enum@Vips.Precision.INTEGER] will make edge detection much * faster, but sacrifice some sensitivity. * * You will probably need to process the output further to eliminate weak * edges. * - * See also: vips_sobel(). + * ::: tip "Optional arguments" + * * @sigma: `gdouble`, sigma for gaussian blur + * * @precision: [enum@Precision], calculation accuracy + * + * ::: seealso + * [method@Image.sobel]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/convolution/compass.c b/libvips/convolution/compass.c index 989d1ce050..877a70b66b 100644 --- a/libvips/convolution/compass.c +++ b/libvips/convolution/compass.c @@ -218,22 +218,22 @@ vips_compass_init(VipsCompass *compass) * @in: input image * @out: (out): output image * @mask: convolve with this mask - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @times: %gint, how many times to rotate and convolve - * * @angle: #VipsAngle45, rotate mask by this much between colvolutions - * * @combine: #VipsCombine, combine results like this - * * @precision: #VipsPrecision, precision for blur, default float - * * @layers: %gint, number of layers for approximation - * * @cluster: %gint, cluster lines closer than this distance + * @...: `NULL`-terminated list of optional named arguments * * This convolves @in with @mask @times times, rotating @mask by @angle * each time. By default, it comvolves twice, rotating by 90 degrees, taking * the maximum result. * - * See also: vips_conv(). + * ::: tip "Optional arguments" + * * @times: `gint`, how many times to rotate and convolve + * * @angle: [enum@Angle45], rotate mask by this much between colvolutions + * * @combine: [enum@Combine], combine results like this + * * @precision: [enum@Precision], precision for blur, default float + * * @layers: `gint`, number of layers for approximation + * * @cluster: `gint`, cluster lines closer than this distance + * + * ::: seealso + * [method@Image.conv]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/convolution/conv.c b/libvips/convolution/conv.c index 3779a2ae6d..dfd8bd9789 100644 --- a/libvips/convolution/conv.c +++ b/libvips/convolution/conv.c @@ -165,46 +165,39 @@ vips_conv_init(VipsConv *conv) * @in: input image * @out: (out): output image * @mask: convolve with this mask - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @precision: #VipsPrecision, calculation accuracy - * * @layers: %gint, number of layers for approximation - * * @cluster: %gint, cluster lines closer than this distance - * - * Convolution. + * @...: `NULL`-terminated list of optional named arguments * * Perform a convolution of @in with @mask. + * * Each output pixel is calculated as: * - * |[ + * ``` * sigma[i]{pixel[i] * mask[i]} / scale + offset - * ]| + * ``` * * where scale and offset are part of @mask. * * By default, @precision is - * #VIPS_PRECISION_FLOAT. The output image - * is always #VIPS_FORMAT_FLOAT unless @in is #VIPS_FORMAT_DOUBLE, in which case - * @out is also #VIPS_FORMAT_DOUBLE. + * [enum@Vips.Precision.FLOAT]. The output image + * is always [enum@Vips.BandFormat.FLOAT] unless @in is + * [enum@Vips.BandFormat.DOUBLE], in which case @out is also + * [enum@Vips.BandFormat.DOUBLE]. * - * If @precision is #VIPS_PRECISION_INTEGER, then - * elements of @mask are converted to - * integers before convolution, using rint(), - * and the output image - * always has the same #VipsBandFormat as the input image. + * If @precision is [enum@Vips.Precision.INTEGER], then elements of @mask + * are converted to integers before convolution, using `rint()`, + * and the output image always has the same [enum@BandFormat] as the input + * image. * - * For #VIPS_FORMAT_UCHAR images and #VIPS_PRECISION_INTEGER @precision, - * vips_conv() uses a fast vector path based on + * For [enum@Vips.BandFormat.UCHAR] images and [enum@Vips.Precision.INTEGER] + * @precision, [method@Image.conv] uses a fast vector path based on * half-float arithmetic. This can produce slightly different results. * Disable the vector path with `--vips-novector` or `VIPS_NOVECTOR` or - * vips_vector_set_enabled(). + * [func@vector_set_enabled]. * - * If @precision is #VIPS_PRECISION_APPROXIMATE then, like - * #VIPS_PRECISION_INTEGER, @mask is converted to int before convolution, and - * the output image - * always has the same #VipsBandFormat as the input image. + * If @precision is [enum@Vips.Precision.APPROXIMATE] then, like + * [enum@Vips.Precision.INTEGER], @mask is converted to int before + * convolution, and the output image + * always has the same [enum@BandFormat] as the input image. * * Larger values for @layers give more accurate * results, but are slower. As @layers approaches the mask radius, the @@ -215,7 +208,13 @@ vips_conv_init(VipsConv *conv) * Smaller values of @cluster will give more accurate results, but be slower * and use more memory. 10% of the mask radius is a good rule of thumb. * - * See also: vips_convsep(). + * ::: tip "Optional arguments" + * * @precision: [enum@Precision], calculation accuracy + * * @layers: `gint`, number of layers for approximation + * * @cluster: `gint`, cluster lines closer than this distance + * + * ::: seealso + * [method@Image.convsep]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/convolution/conva.c b/libvips/convolution/conva.c index fcb6f81178..bf69ea7e22 100644 --- a/libvips/convolution/conva.c +++ b/libvips/convolution/conva.c @@ -331,10 +331,10 @@ vips_conva_decompose_hlines(VipsConva *conva) * fixed n-lines which includes any negative parts. */ depth = (max - min) / conva->layers; - layers_above = VIPS_CEIL(max / depth); + layers_above = ceil(max / depth); depth = max / layers_above; - layers_below = VIPS_FLOOR(min / depth); - conva->layers = layers_above - layers_below; + layers_below = floor(min / depth); + conva->layers = layers_above - layers_below; // FIXME: Invalidates operation cache VIPS_DEBUG_MSG("vips_conva_decompose_hlines: depth = %g, layers = %d\n", depth, conva->layers); @@ -744,7 +744,7 @@ vips_conva_decompose_boxes(VipsConva *conva) for (z = 0; z < size; z++) sum += fabs(coeff[z]); - conva->divisor = VIPS_RINT(area * scale / sum); + conva->divisor = rint(area * scale / sum); conva->rounding = (conva->divisor + 1) / 2; conva->offset = offset; @@ -983,7 +983,7 @@ vips_conva_horizontal(VipsConva *conva, VipsImage *in, VipsImage **out) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(conva); - /* Prepare output. Consider a 7x7 mask and a 7x7 image --- the output + /* Prepare output. Consider a 7x7 mask and a 7x7 image -- the output * would be 1x1. */ *out = vips_image_new(); @@ -1233,7 +1233,7 @@ vips_conva_vertical(VipsConva *conva, VipsImage *in, VipsImage **out) VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(conva); VipsConvolution *convolution = (VipsConvolution *) conva; - /* Prepare output. Consider a 7x7 mask and a 7x7 image --- the output + /* Prepare output. Consider a 7x7 mask and a 7x7 image -- the output * would be 1x1. */ *out = vips_image_new(); @@ -1346,19 +1346,14 @@ vips_conva_init(VipsConva *conva) * @in: input image * @out: (out): output image * @mask: convolution mask - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @layers: %gint, number of layers for approximation - * * @cluster: %gint, cluster lines closer than this distance + * @...: `NULL`-terminated list of optional named arguments * * Perform an approximate integer convolution of @in with @mask. - * This is a low-level operation, see - * vips_conv() for something more convenient. + * This is a low-level operation, see [method@Image.conv] for something more + * convenient. * * The output image - * always has the same #VipsBandFormat as the input image. + * always has the same [enum@BandFormat] as the input image. * Elements of @mask are converted to * integers before convolution. * @@ -1371,7 +1366,12 @@ vips_conva_init(VipsConva *conva) * Smaller values of @cluster will give more accurate results, but be slower * and use more memory. 10% of the mask radius is a good rule of thumb. * - * See also: vips_conv(). + * ::: tip "Optional arguments" + * * @layers: `gint`, number of layers for approximation + * * @cluster: `gint`, cluster lines closer than this distance + * + * ::: seealso + * [method@Image.conv]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/convolution/convasep.c b/libvips/convolution/convasep.c index 64c9fa7bcc..4db41193a5 100644 --- a/libvips/convolution/convasep.c +++ b/libvips/convolution/convasep.c @@ -303,7 +303,7 @@ vips_convasep_decompose(VipsConvasep *convasep) for (z = 0; z < convasep->width; z++) sum += coeff[z]; - convasep->divisor = VIPS_RINT(sum * area / scale); + convasep->divisor = rint(sum * area / scale); if (convasep->divisor == 0) convasep->divisor = 1; convasep->rounding = (convasep->divisor + 1) / 2; @@ -934,14 +934,10 @@ vips_convasep_init(VipsConvasep *convasep) * @in: input image * @out: (out): output image * @mask: convolve with this mask - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @layers: %gint, number of layers for approximation + * @...: `NULL`-terminated list of optional named arguments * * Approximate separable integer convolution. This is a low-level operation, see - * vips_convsep() for something more convenient. + * [method@Image.convsep] for something more convenient. * * The image is convolved twice: once with @mask and then again with @mask * rotated by 90 degrees. @@ -956,9 +952,13 @@ vips_convasep_init(VipsConvasep *convasep) * this value and accuracy will still be good. * * The output image - * always has the same #VipsBandFormat as the input image. + * always has the same [enum@BandFormat] as the input image. + * + * ::: tip "Optional arguments" + * * @layers: `gint`, number of layers for approximation * - * See also: vips_convsep(). + * ::: seealso + * [method@Image.convsep]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/convolution/convf.c b/libvips/convolution/convf.c index 48188122ee..0d19592b5d 100644 --- a/libvips/convolution/convf.c +++ b/libvips/convolution/convf.c @@ -347,7 +347,7 @@ vips_convf_build(VipsObject *object) convolution->out->Xoffset = 0; convolution->out->Yoffset = 0; - /* Prepare output. Consider a 7x7 mask and a 7x7 image --- the output + /* Prepare output. Consider a 7x7 mask and a 7x7 image -- the output * would be 1x1. */ if (vips_band_format_isint(in->BandFmt)) @@ -388,9 +388,9 @@ vips_convf_init(VipsConvf *convf) * @in: input image * @out: (out): output image * @mask: convolve with this mask - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Convolution. This is a low-level operation, see vips_conv() for something + * Convolution. This is a low-level operation, see [method@Image.conv] for something * more convenient. * * Perform a convolution of @in with @mask. @@ -399,10 +399,11 @@ vips_convf_init(VipsConvf *convf) * and offset are part of @mask. * * The convolution is performed with floating-point arithmetic. The output image - * is always #VIPS_FORMAT_FLOAT unless @in is #VIPS_FORMAT_DOUBLE, in which case - * @out is also #VIPS_FORMAT_DOUBLE. + * is always [enum@Vips.BandFormat.FLOAT] unless @in is [enum@Vips.BandFormat.DOUBLE], in which case + * @out is also [enum@Vips.BandFormat.DOUBLE]. * - * See also: vips_conv(). + * ::: seealso + * [method@Image.conv]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/convolution/convi.c b/libvips/convolution/convi.c index 0df48e20ae..d70cb2a9e3 100644 --- a/libvips/convolution/convi.c +++ b/libvips/convolution/convi.c @@ -309,7 +309,7 @@ vips_convi_uchar_vector_gen(VipsRegion *out_region, VipsConvi *convi = (VipsConvi *) b; VipsConvolution *convolution = (VipsConvolution *) convi; VipsImage *M = convolution->M; - int offset = VIPS_RINT(vips_image_get_offset(M)); + int offset = rint(vips_image_get_offset(M)); VipsImage *in = (VipsImage *) a; VipsRegion *ir = seq->ir; const int nnz = convi->nnz; @@ -498,9 +498,9 @@ vips_convi_compile_section(VipsConvi *convi, VipsImage *in, Pass *pass) /* Some orcs seem to be unstable with many compilers active at once. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); result = orc_program_compile(p); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) return -1; @@ -521,7 +521,7 @@ vips_convi_compile_clip(VipsConvi *convi) { VipsConvolution *convolution = (VipsConvolution *) convi; VipsImage *M = convolution->M; - int offset = VIPS_RINT(vips_image_get_offset(M)); + int offset = rint(vips_image_get_offset(M)); OrcProgram *p; OrcCompileResult result; @@ -549,9 +549,9 @@ vips_convi_compile_clip(VipsConvi *convi) /* Some orcs seem to be unstable with many compilers active at once. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); result = orc_program_compile(p); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) return -1; @@ -728,7 +728,7 @@ vips_convi_gen_vector(VipsRegion *out_region, \ sum = 0; \ for (i = 0; i < nnz; i++) \ - sum += t[i] * p[offsets[i]]; \ + sum += (double) t[i] * p[offsets[i]]; \ \ sum = (sum / scale) + offset; \ \ @@ -755,9 +755,9 @@ vips_convi_gen(VipsRegion *out_region, VipsConvi *convi = (VipsConvi *) b; VipsConvolution *convolution = (VipsConvolution *) convi; VipsImage *M = convolution->M; - int scale = VIPS_RINT(vips_image_get_scale(M)); + int scale = rint(vips_image_get_scale(M)); int rounding = scale / 2; - int offset = VIPS_RINT(vips_image_get_offset(M)); + int offset = rint(vips_image_get_offset(M)); VipsImage *in = (VipsImage *) a; VipsRegion *ir = seq->ir; int *restrict t = convi->coeff; @@ -890,12 +890,12 @@ vips__image_intize(VipsImage *in, VipsImage **out) for (y = 0; y < t->Ysize; y++) for (x = 0; x < t->Xsize; x++) *VIPS_MATRIX(*out, x, y) = - VIPS_RINT(*VIPS_MATRIX(t, x, y)); + rint(*VIPS_MATRIX(t, x, y)); - out_scale = VIPS_RINT(vips_image_get_scale(t)); + out_scale = rint(vips_image_get_scale(t)); if (out_scale == 0) out_scale = 1; - out_offset = VIPS_RINT(vips_image_get_offset(t)); + out_offset = rint(vips_image_get_offset(t)); /* Now convolve a 1 everywhere image with the int version we've made, * what do we get? @@ -908,7 +908,7 @@ vips__image_intize(VipsImage *in, VipsImage **out) /* And adjust the scale to get as close to a match as we can. */ - out_scale = VIPS_RINT(out_scale + (int_result - double_result)); + out_scale = rint(out_scale + (int_result - double_result)); if (out_scale == 0) out_scale = 1; @@ -1023,7 +1023,7 @@ vips_convi_intize(VipsConvi *convi, VipsImage *M) for (i = 0; i < convi->n_point; i++) { /* 128 since this is signed. */ - convi->mant[i] = VIPS_RINT(128 * scaled[i] * pow(2, -shift)); + convi->mant[i] = rint(128 * scaled[i] * pow(2, -shift)); if (convi->mant[i] < -128 || convi->mant[i] > 127) { @@ -1106,7 +1106,7 @@ vips_convi_intize(VipsConvi *convi, VipsImage *M) int_value = VIPS_LSHIFT_INT(int_sum, convi->exp); int_value = VIPS_CLIP(0, int_value, 255); - if (VIPS_ABS(true_value - int_value) > 2) { + if (abs(true_value - int_value) > 2) { g_info("vips_convi_intize: too inaccurate"); return -1; } @@ -1213,7 +1213,7 @@ vips_convi_build(VipsObject *object) convolution->out->Xoffset = 0; convolution->out->Yoffset = 0; - /* Prepare output. Consider a 7x7 mask and a 7x7 image --- the output + /* Prepare output. Consider a 7x7 mask and a 7x7 image -- the output * would be 1x1. */ convolution->out->Xsize -= M->Xsize - 1; @@ -1262,26 +1262,27 @@ vips_convi_init(VipsConvi *convi) * @in: input image * @out: (out): output image * @mask: convolve with this mask - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Integer convolution. This is a low-level operation, see vips_conv() for + * Integer convolution. This is a low-level operation, see [method@Image.conv] for * something more convenient. * - * @mask is converted to an integer mask with rint() of each element, rint of + * @mask is converted to an integer mask with `rint()` of each element, rint of * scale and rint of offset. Each output pixel is then calculated as * - * |[ + * ``` * sigma[i]{pixel[i] * mask[i]} / scale + offset - * ]| + * ``` * - * The output image always has the same #VipsBandFormat as the input image. + * The output image always has the same [enum@BandFormat] as the input image. * - * For #VIPS_FORMAT_UCHAR images, vips_convi() uses a fast vector path based on + * For [enum@Vips.BandFormat.UCHAR] images, [method@Image.convi] uses a fast vector path based on * half-float arithmetic. This can produce slightly different results. * Disable the vector path with `--vips-novector` or `VIPS_NOVECTOR` or - * vips_vector_set_enabled(). + * [func@vector_set_enabled]. * - * See also: vips_conv(). + * ::: seealso + * [method@Image.conv]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/convolution/convolution.c b/libvips/convolution/convolution.c index 12478400ac..26c8fa29c4 100644 --- a/libvips/convolution/convolution.c +++ b/libvips/convolution/convolution.c @@ -51,16 +51,6 @@ #include "pconvolution.h" -/** - * SECTION: convolution - * @short_description: convolve and correlate images - * @stability: Stable - * @include: vips/vips.h - * - * These operations convolve an image in some way, or are operations based on - * simple convolution, or are useful with convolution. - */ - /** * VipsPrecision: * @VIPS_PRECISION_INTEGER: int everywhere @@ -76,7 +66,7 @@ * @VIPS_COMBINE_SUM: sum all the values * @VIPS_COMBINE_MIN: take the minimum value * - * How to combine values. See vips_compass(), for example. + * How to combine values. See [method@Image.compass], for example. */ G_DEFINE_ABSTRACT_TYPE(VipsConvolution, vips_convolution, diff --git a/libvips/convolution/convsep.c b/libvips/convolution/convsep.c index 435ab8317f..b34646db44 100644 --- a/libvips/convolution/convsep.c +++ b/libvips/convolution/convsep.c @@ -161,16 +161,10 @@ vips_convsep_init(VipsConvsep *convsep) * @in: input image * @out: (out): output image * @mask: convolution mask - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @precision: calculation accuracy - * * @layers: number of layers for approximation - * * @cluster: cluster lines closer than this distance + * @...: `NULL`-terminated list of optional named arguments * * Perform a separable convolution of @in with @mask. - * See vips_conv() for a detailed description. + * See [method@Image.conv] for a detailed description. * * The mask must be 1xn or nx1 elements. * @@ -178,7 +172,13 @@ vips_convsep_init(VipsConvsep *convsep) * rotated by 90 degrees. This is much faster for certain types of mask * (gaussian blur, for example) than doing a full 2D convolution. * - * See also: vips_conv(), vips_gaussmat(). + * ::: tip "Optional arguments" + * * @precision: [enum@Precision], calculation accuracy + * * @layers: `gint`, number of layers for approximation + * * @cluster: `gint`, cluster lines closer than this distance + * + * ::: seealso + * [method@Image.conv], [ctor@Image.gaussmat]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/convolution/edge.c b/libvips/convolution/edge.c index 5a23502056..f35f1f7c33 100644 --- a/libvips/convolution/edge.c +++ b/libvips/convolution/edge.c @@ -98,7 +98,7 @@ vips_edge_uchar_gen(VipsRegion *out_region, int v2 = 2 * (p2[x] - 128); /* Avoid the sqrt() for uchar. */ - int v = VIPS_ABS(v1) + VIPS_ABS(v2); + int v = abs(v1) + abs(v2); q[x] = v > 255 ? 255 : v; } @@ -334,14 +334,16 @@ vips_prewitt_init(VipsPrewitt *prewitt) * vips_sobel: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Sobel edge detector. * * uchar images are computed using a fast, low-precision path. Cast to float * for a high-precision implementation. * - * See also: vips_canny(), vips_sobel(), vips_prewitt(), vips_scharr(). + * ::: seealso + * [method@Image.canny], [method@Image.sobel], [method@Image.prewitt], + * [method@Image.scharr]. * * Returns: 0 on success, -1 on error. */ @@ -362,14 +364,16 @@ vips_sobel(VipsImage *in, VipsImage **out, ...) * vips_scharr: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Scharr edge detector. * * uchar images are computed using a fast, low-precision path. Cast to float * for a high-precision implementation. * - * See also: vips_canny(), vips_sobel(), vips_prewitt(), vips_scharr(). + * ::: seealso + * [method@Image.canny], [method@Image.sobel], [method@Image.prewitt], + * [method@Image.scharr]. * * Returns: 0 on success, -1 on error. */ @@ -390,14 +394,16 @@ vips_scharr(VipsImage *in, VipsImage **out, ...) * vips_prewitt: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Prewitt edge detector. * * uchar images are computed using a fast, low-precision path. Cast to float * for a high-precision implementation. * - * See also: vips_canny(), vips_sobel(), vips_prewitt(), vips_scharr(). + * ::: seealso + * [method@Image.canny], [method@Image.sobel], [method@Image.prewitt], + * [method@Image.scharr]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/convolution/fastcor.c b/libvips/convolution/fastcor.c index f1b740b5b3..761b05e230 100644 --- a/libvips/convolution/fastcor.c +++ b/libvips/convolution/fastcor.c @@ -231,7 +231,7 @@ vips_fastcor_init(VipsFastcor *fastcor) * @in: input image * @ref: reference image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Calculate a fast correlation surface. * @@ -252,7 +252,8 @@ vips_fastcor_init(VipsFastcor *fastcor) * In other words, the output type is just large enough to hold the whole * range of possible values. * - * See also: vips_spcor(). + * ::: seealso + * [method@Image.spcor]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/convolution/gaussblur.c b/libvips/convolution/gaussblur.c index 40eeda7c20..ffcac665d7 100644 --- a/libvips/convolution/gaussblur.c +++ b/libvips/convolution/gaussblur.c @@ -175,18 +175,20 @@ vips_gaussblur_init(VipsGaussblur *gaussblur) * @in: input image * @out: (out): output image * @sigma: how large a mask to use - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * This operator runs [ctor@Image.gaussmat] and [method@Image.convsep] for + * you on an image. * - * * @precision: #VipsPrecision, precision for blur, default int - * * @min_ampl: minimum amplitude, default 0.2 - * - * This operator runs vips_gaussmat() and vips_convsep() for you on an image. * Set @min_ampl smaller to generate a larger, more accurate mask. Set @sigma * larger to make the blur more blurry. * - * See also: vips_gaussmat(), vips_convsep(). + * ::: tip "Optional arguments" + * * @precision: [enum@Precision], precision for blur, default int + * * @min_ampl: minimum amplitude, default 0.2 + * + * ::: seealso + * [ctor@Image.gaussmat], [method@Image.convsep]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/convolution/sharpen.c b/libvips/convolution/sharpen.c index c5edfef92d..cef99414c7 100644 --- a/libvips/convolution/sharpen.c +++ b/libvips/convolution/sharpen.c @@ -189,7 +189,7 @@ vips_sharpen_build(VipsObject *object) */ if (!vips_object_argument_isset(object, "sigma") && vips_object_argument_isset(object, "radius")) - sharpen->sigma = 1 + sharpen->radius / 2; + sharpen->sigma = 1 + sharpen->radius / 2; // FIXME: Invalidates operation cache in = sharpen->in; @@ -253,7 +253,7 @@ vips_sharpen_build(VipsObject *object) if (y > sharpen->y2) y = sharpen->y2; - sharpen->lut[i] = VIPS_RINT(y * 327.67); + sharpen->lut[i] = rint(y * 327.67); } #ifdef DEBUG @@ -397,19 +397,10 @@ vips_sharpen_init(VipsSharpen *sharpen) * vips_sharpen: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @sigma: sigma of gaussian - * * @x1: flat/jaggy threshold - * * @y2: maximum amount of brightening - * * @y3: maximum amount of darkening - * * @m1: slope for flat areas - * * @m2: slope for jaggy areas + * @...: `NULL`-terminated list of optional named arguments * * Selectively sharpen the L channel of a LAB image. The input image is - * transformed to #VIPS_INTERPRETATION_LABS. + * transformed to [enum@Vips.Interpretation.LABS]. * * The operation performs a gaussian blur and subtracts from @in to generate a * high-frequency signal. This signal is passed through a lookup table formed @@ -417,7 +408,7 @@ vips_sharpen_init(VipsSharpen *sharpen) * * The lookup table is formed like this: * - * |[ + * ``` * . ^ * . y2 |- - - - - ----------- * . | / @@ -435,18 +426,18 @@ vips_sharpen_init(VipsSharpen *sharpen) * . / | * . ______/ _ _ _ _ _ _ | -y3 * . | - * ]| + * ``` * * For screen output, we suggest the following settings (the defaults): * - * |[ + * ``` * sigma == 0.5 * x1 == 2 * y2 == 10 (don't brighten by more than 10 L*) * y3 == 20 (can darken by up to 20 L*) * m1 == 0 (no sharpening in flat areas) * m2 == 3 (some sharpening in jaggy areas) - * ]| + * ``` * * If you want more or less sharpening, we suggest you just change the * m2 parameter. @@ -458,7 +449,16 @@ vips_sharpen_init(VipsSharpen *sharpen) * pixels/mm). These figures refer to the image raster, not the half-tone * resolution. * - * See also: vips_conv(). + * ::: tip "Optional arguments" + * * @sigma: `gdouble`, sigma of gaussian + * * @x1: `gdouble`, flat/jaggy threshold + * * @y2: `gdouble`, maximum amount of brightening + * * @y3: `gdouble`, maximum amount of darkening + * * @m1: `gdouble`, slope for flat areas + * * @m2: `gdouble`, slope for jaggy areas + * + * ::: seealso + * [method@Image.conv]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/convolution/spcor.c b/libvips/convolution/spcor.c index bef10b7aea..73a7b67cea 100644 --- a/libvips/convolution/spcor.c +++ b/libvips/convolution/spcor.c @@ -331,7 +331,7 @@ vips_spcor_init(VipsSpcor *spcor) * @in: input image * @ref: reference image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Calculate a correlation surface. * @@ -345,12 +345,12 @@ vips_spcor_init(VipsSpcor *spcor) * * The correlation coefficient is calculated as: * - * |[ + * ``` * sumij (ref(i,j)-mean(ref))(inkl(i,j)-mean(inkl)) * c(k,l) = ------------------------------------------------ * sqrt(sumij (ref(i,j)-mean(ref))^2) * * sqrt(sumij (inkl(i,j)-mean(inkl))^2) - * ]| + * ``` * * where inkl is the area of @in centred at position (k,l). * @@ -365,7 +365,8 @@ vips_spcor_init(VipsSpcor *spcor) * The output image is always float, unless either of the two inputs is * double, in which case the output is also double. * - * See also: vips_fastcor(). + * ::: seealso + * [method@Image.fastcor]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/black.c b/libvips/create/black.c index 17bc312e75..93d252214c 100644 --- a/libvips/create/black.c +++ b/libvips/create/black.c @@ -169,15 +169,15 @@ vips_black_init(VipsBlack *black) * @out: (out): output image * @width: output width * @height: output height - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @bands: output bands + * @...: `NULL`-terminated list of optional named arguments * * Make a black unsigned char image of a specified size. * - * See also: vips_xyz(), vips_text(), vips_gaussnoise(). + * ::: tip "Optional arguments" + * * @bands: `gint`, output bands + * + * ::: seealso + * [ctor@Image.xyz], [ctor@Image.text], [ctor@Image.gaussnoise]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/buildlut.c b/libvips/create/buildlut.c index d2405d61c2..67b846e8e5 100644 --- a/libvips/create/buildlut.c +++ b/libvips/create/buildlut.c @@ -129,13 +129,13 @@ vips_buildlut_build_init(VipsBuildlut *lut) /* Allow for being a bit off. */ - if (VIPS_FABS(v - VIPS_RINT(v)) > 0.001) { + if (fabs(v - rint(v)) > 0.001) { vips_error(class->nickname, _("x value row %d not an int"), y); return -1; } - v = VIPS_RINT(v); + v = rint(v); if (v < xlow) xlow = v; @@ -197,8 +197,8 @@ vips_buildlut_build_create(VipsBuildlut *lut) */ for (b = 0; b < bands; b++) { for (i = 0; i < ysize - 1; i++) { - const int x1 = VIPS_RINT(lut->data[i][0]); - const int x2 = VIPS_RINT(lut->data[i + 1][0]); + const int x1 = rint(lut->data[i][0]); + const int x2 = rint(lut->data[i + 1][0]); const int dx = x2 - x1; const double y1 = lut->data[i][b + 1]; const double y2 = lut->data[i + 1][b + 1]; @@ -275,57 +275,30 @@ vips_buildlut_init(VipsBuildlut *lut) * vips_buildlut: (method) * @in: input matrix * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation builds a lookup table from a set of points. Intermediate * values are generated by piecewise linear interpolation. The lookup table is - * always of type #VIPS_FORMAT_DOUBLE, use vips_cast() to change it to the - * type you need. + * always of type [enum@Vips.BandFormat.DOUBLE], use [method@Image.cast] to + * change it to the type you need. * * For example, consider this 2 x 2 matrix of (x, y) coordinates: * - * - * - * - * 0 - * 0 - * - * - * 255 - * 100 - * - * - * + * ``` + * 2 2 + * 0 0 + * 255 100 + * ``` * * We then generate a 1 x 256 element LUT like this: * - * - * - * - * Index - * Value - * - * - * - * - * 0 - * 0 - * - * - * 1 - * 0.4 - * - * - * etc. - * 0.4 - * - * - * 255 - * 100 - * - * - * - * + * | Index | Value | + * |-------|-------| + * | 0 | 0 | + * | 1 | 0.4 | + * | etc. | 0.4 | + * | 255 | 100 | + * This is then written as the output image, with the left column giving the * index in the image to place the value. * @@ -333,7 +306,9 @@ vips_buildlut_init(VipsBuildlut *lut) * several Ys, each becomes a band in the output LUT. You don't need to * start at zero, any integer will do, including negatives. * - * See also: vips_identity(), vips_invertlut(), vips_cast(), vips_maplut(). + * ::: seealso + * [ctor@Image.identity], [method@Image.invertlut], [method@Image.cast], + * [method@Image.maplut]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/create.c b/libvips/create/create.c index 2178555a8b..e9e46861a8 100644 --- a/libvips/create/create.c +++ b/libvips/create/create.c @@ -51,16 +51,6 @@ #include "point.h" #include "pmask.h" -/** - * SECTION: create - * @short_description: create images in various ways - * @stability: Stable - * @include: vips/vips.h - * - * These functions generate various images. You can combine them with - * the arithmetic and rotate functions to build more complicated images. - */ - /** * VipsTextWrap: * @VIPS_TEXT_WRAP_WORD: wrap at word boundaries @@ -68,10 +58,11 @@ * @VIPS_TEXT_WRAP_WORD_CHAR: wrap at word boundaries, but fall back to character boundaries if there is not enough space for a full word * @VIPS_TEXT_WRAP_NONE: no wrapping * - * Sets the word wrapping style for vips_text() when used with a maximum + * Sets the word wrapping style for [ctor@Image.text] when used with a maximum * width. * - * See also: vips_text(). + * ::: seealso + * [ctor@Image.text]. */ /** @@ -83,7 +74,8 @@ * * The SDF to generate, * - * See also: vips_sdf(). + * ::: seealso + * [ctor@Image.sdf]. */ G_DEFINE_ABSTRACT_TYPE(VipsCreate, vips_create, VIPS_TYPE_OPERATION); @@ -170,9 +162,11 @@ vips_create_operation_init(void) vips_gaussmat_get_type(); vips_logmat_get_type(); vips_gaussnoise_get_type(); + #ifdef HAVE_PANGOCAIRO vips_text_get_type(); #endif /*HAVE_PANGOCAIRO*/ + vips_xyz_get_type(); vips_sdf_get_type(); vips_eye_get_type(); diff --git a/libvips/create/eye.c b/libvips/create/eye.c index bc67767cad..a872b18bf2 100644 --- a/libvips/create/eye.c +++ b/libvips/create/eye.c @@ -82,10 +82,10 @@ vips_eye_point(VipsPoint *point, int x, int y) int max_x = VIPS_MAX(point->width - 1, 1); int max_y = VIPS_MAX(point->height - 1, 1); - double c = eye->factor * VIPS_PI / (2 * max_x); - double h = max_y * max_y; + float c = eye->factor * VIPS_PI / (2 * max_x); + float h = max_y * max_y; - return y * y * cos(c * x * x) / h; + return y * y * cosf(c * x * x) / h; } static void @@ -123,20 +123,22 @@ vips_eye_init(VipsEye *eye) * @out: (out): output image * @width: image size * @height: image size - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @factor: %gdouble, maximum spatial frequency - * * @uchar: %gboolean, output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Create a test pattern with increasing spatial frequency in X and - * amplitude in Y. @factor should be between 0 and 1 and determines the + * amplitude in Y. + * + * @factor should be between 0 and 1 and determines the * maximum spatial frequency. * * Set @uchar to output a uchar image. * - * See also: vips_zone(). + * ::: tip "Optional arguments" + * * @factor: `gdouble`, maximum spatial frequency + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.zone]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/fractsurf.c b/libvips/create/fractsurf.c index 2d3ad96412..c9fb88f8d3 100644 --- a/libvips/create/fractsurf.c +++ b/libvips/create/fractsurf.c @@ -136,12 +136,13 @@ vips_fractsurf_init(VipsFractsurf *fractsurf) * @width: output width * @height: output height * @fractal_dimension: fractal dimension - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Generate an image of size @width by @height and fractal dimension * @fractal_dimension. The dimension should be between 2 and 3. * - * See also: vips_gaussnoise(), vips_mask_fractal(). + * ::: seealso + * [ctor@Image.gaussnoise], [ctor@Image.mask_fractal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/gaussmat.c b/libvips/create/gaussmat.c index 5f3dbe4017..23804290ae 100644 --- a/libvips/create/gaussmat.c +++ b/libvips/create/gaussmat.c @@ -114,7 +114,7 @@ vips_gaussmat_build(VipsObject *object) if (vips_object_argument_isset(object, "integer") && !vips_object_argument_isset(object, "precision") && !gaussmat->integer) - gaussmat->precision = VIPS_PRECISION_FLOAT; + gaussmat->precision = VIPS_PRECISION_FLOAT; // FIXME: Invalidates operation cache /* Find the size of the mask. Limit the mask size to 10k x 10k for * sanity. We allow x == 0, meaning a 1x1 mask. @@ -150,7 +150,7 @@ vips_gaussmat_build(VipsObject *object) double v = exp(-distance / sig2); if (gaussmat->precision != VIPS_PRECISION_FLOAT) - v = VIPS_RINT(20 * v); + v = rint(20 * v); *VIPS_MATRIX(create->out, x, y) = v; sum += v; @@ -230,34 +230,38 @@ vips_gaussmat_init(VipsGaussmat *gaussmat) * @out: (out): output image * @sigma: standard deviation of mask * @min_ampl: minimum amplitude - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @separable: generate a separable gaussian - * * @precision: #VipsPrecision for @out + * @...: `NULL`-terminated list of optional named arguments * * Creates a circularly symmetric Gaussian image of radius - * @sigma. The size of the mask is determined by the variable @min_ampl; + * @sigma. + * + * The size of the mask is determined by the variable @min_ampl; * if for instance the value .1 is entered this means that the produced mask * is clipped at values less than 10 percent of the maximum amplitude. * * The program uses the following equation: * - * H(r) = exp(-(r * r) / (2 * @sigma * @sigma)) + * ``` + * H(r) = exp(-(r * r) / (2 * @sigma * @sigma)) + * ``` * * The generated image has odd size and its maximum value is normalised to - * 1.0, unless @precision is #VIPS_PRECISION_INTEGER. + * 1.0, unless @precision is [enum@Vips.Precision.INTEGER]. * * If @separable is set, only the centre horizontal is generated. This is * useful for separable convolutions. * - * If @precision is #VIPS_PRECISION_INTEGER, an integer gaussian is generated. - * This is useful for integer convolutions. + * If @precision is [enum@Vips.Precision.INTEGER], an integer gaussian is + * generated. This is useful for integer convolutions. * * "scale" is set to the sum of all the mask elements. * - * See also: vips_logmat(), vips_conv(). + * ::: tip "Optional arguments" + * * @separable: `gboolean`, generate a separable gaussian + * * @precision: [enum@Precision] for @out + * + * ::: seealso + * [ctor@Image.logmat], [method@Image.conv]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/gaussnoise.c b/libvips/create/gaussnoise.c index 733a5b5ed1..7dcf406f52 100644 --- a/libvips/create/gaussnoise.c +++ b/libvips/create/gaussnoise.c @@ -64,6 +64,7 @@ #include #include +#include #include "pcreate.h" @@ -212,18 +213,20 @@ vips_gaussnoise_init(VipsGaussnoise *gaussnoise) * @out: (out): output image * @width: output width * @height: output height - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Make a one band float image of gaussian noise with the specified + * distribution. * - * * @mean: mean of generated pixels - * * @sigma: standard deviation of generated pixels + * The gaussian distribution is created by averaging 12 random numbers from a + * linear generator, then weighting appropriately with @mean and @sigma. * - * Make a one band float image of gaussian noise with the specified - * distribution. The noise distribution is created by averaging 12 random - * numbers with the appropriate weights. + * ::: tip "Optional arguments" + * * @mean: `gdouble`, mean of generated pixels + * * @sigma: `gdouble`, standard deviation of generated pixels * - * See also: vips_black(), vips_xyz(), vips_text(). + * ::: seealso + * [ctor@Image.black], [ctor@Image.xyz], [ctor@Image.text]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/grey.c b/libvips/create/grey.c index 4b9b6b1772..8c26e30c5f 100644 --- a/libvips/create/grey.c +++ b/libvips/create/grey.c @@ -89,8 +89,8 @@ vips_grey_class_init(VipsGreyClass *class) vobject_class->description = _("make a grey ramp image"); point_class->point = vips_grey_point; - point_class->min = 0.0; - point_class->max = 1.0; + point_class->min = 0.0F; + point_class->max = 1.0F; } static void @@ -103,19 +103,21 @@ vips_grey_init(VipsGrey *grey) * @out: (out): output image * @width: image size * @height: image size - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Create a one-band float image with the left-most column zero and the - * right-most 1. Intermediate pixels are a linear ramp. + * right-most 1. + * + * Intermediate pixels are a linear ramp. * * Set @uchar to output a uchar image with the leftmost pixel 0 and the * rightmost 255. * - * See also: vips_xyz(), vips_identity(). + * ::: tip "Optional arguments" + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.xyz], [ctor@Image.identity]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/identity.c b/libvips/create/identity.c index 42e0024c07..5152293336 100644 --- a/libvips/create/identity.c +++ b/libvips/create/identity.c @@ -172,17 +172,11 @@ vips_identity_init(VipsIdentity *identity) /** * vips_identity: * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @bands: number of bands to create - * * @ushort: %TRUE for an unsigned short identity - * * @size: number of LUT elements for a ushort image + * @...: `NULL`-terminated list of optional named arguments * * Creates an identity lookup table, ie. one which will leave an image - * unchanged when applied with vips_maplut(). Each entry in the table has a - * value equal to its position. + * unchanged when applied with [method@Image.maplut]. Each entry in the table + * has a value equal to its position. * * Use the arithmetic operations on these tables to make LUTs representing * arbitrary functions. @@ -192,7 +186,13 @@ vips_identity_init(VipsIdentity *identity) * Normally 16-bit tables have 65536 entries. You can set this smaller with * @size. * - * See also: vips_xyz(), vips_maplut(). + * ::: tip "Optional arguments" + * * @bands: `gint`, number of bands to create + * * @ushort: `gboolean`, `TRUE` for an unsigned short identity + * * @size: `gint`, number of LUT elements for a ushort image + * + * ::: seealso + * [ctor@Image.xyz], [method@Image.maplut]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/invertlut.c b/libvips/create/invertlut.c index ff24aab7eb..db88c5cf89 100644 --- a/libvips/create/invertlut.c +++ b/libvips/create/invertlut.c @@ -212,7 +212,7 @@ vips_invertlut_build_create(VipsInvertlut *lut) /* Interpolate the data sections. */ - for (k = first; k < last; k++) { + for (k = first; k <= last; k++) { /* Where we're at in the [0,1] range. */ double ki = (double) k / (lut->size - 1); @@ -308,45 +308,23 @@ vips_invertlut_init(VipsInvertlut *lut) * vips_invertlut: (method) * @in: input mask * @out: (out): output LUT - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @size: generate this much + * @...: `NULL`-terminated list of optional named arguments * * Given a mask of target values and real values, generate a LUT which - * will map reals to targets. Handy for linearising images from - * measurements of a colour chart. All values in [0,1]. Piecewise linear - * interpolation, extrapolate head and tail to 0 and 1. + * will map reals to targets. + * + * Handy for linearising images from measurements of a colour chart. All + * values in [0,1]. Piecewise linear interpolation, extrapolate head and tail + * to 0 and 1. * * Eg. input like this: * - * - * - * - * 4 - * 3 - * - * - * 0.1 - * 0.2 - * 0.3 - * 0.1 - * - * - * 0.2 - * 0.4 - * 0.4 - * 0.2 - * - * - * 0.7 - * 0.5 - * 0.6 - * 0.3 - * - * - * + * ``` + * 4 3 + * 0.1 0.2 0.3 0.1 + * 0.2 0.4 0.4 0.2 + * 0.7 0.5 0.6 0.3 + * ``` * * Means a patch with 10% reflectance produces an image with 20% in * channel 1, 30% in channel 2, and 10% in channel 3, and so on. @@ -358,7 +336,11 @@ vips_invertlut_init(VipsInvertlut *lut) * (we should fix this). Interpolation is simple piecewise linear; we ought to * do something better really. * - * See also: vips_buildlut(). + * ::: tip "Optional arguments" + * * @size: `gint`, generate this much + * + * ::: seealso + * [method@Image.buildlut]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/logmat.c b/libvips/create/logmat.c index f84ac72ef2..49cc773a42 100644 --- a/libvips/create/logmat.c +++ b/libvips/create/logmat.c @@ -106,7 +106,7 @@ vips_logmat_build(VipsObject *object) if (vips_object_argument_isset(object, "integer") && !vips_object_argument_isset(object, "precision") && !logmat->integer) - logmat->precision = VIPS_PRECISION_FLOAT; + logmat->precision = VIPS_PRECISION_FLOAT; // FIXME: Invalidates operation cache if (vips_check_precision_intfloat(class->nickname, logmat->precision)) @@ -138,7 +138,7 @@ vips_logmat_build(VipsObject *object) * is less than the min. */ if (val - last >= 0 && - VIPS_FABS(val) < logmat->min_ampl) + fabs(val) < logmat->min_ampl) break; last = val; @@ -171,7 +171,7 @@ vips_logmat_build(VipsObject *object) exp(-distance / (2.0 * sig2)); if (logmat->precision == VIPS_PRECISION_INTEGER) - v = VIPS_RINT(20 * v); + v = rint(20 * v); *VIPS_MATRIX(create->out, x, y) = v; sum += v; @@ -246,16 +246,12 @@ vips_logmat_init(VipsLogmat *logmat) * @out: (out): output image * @sigma: standard deviation of mask * @min_ampl: minimum amplitude - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Create a circularly symmetric Laplacian of Gaussian mask of radius + * @sigma. * - * * @separable: generate a separable mask - * * @precision: #VipsPrecision for @out - * - * Creates a circularly symmetric Laplacian of Gaussian mask - * of radius - * @sigma. The size of the mask is determined by the variable @min_ampl; + * The size of the mask is determined by the variable @min_ampl; * if for instance the value .1 is entered this means that the produced mask * is clipped at values within 10 percent of zero, and where the change * between mask elements is less than 10%. @@ -263,24 +259,35 @@ vips_logmat_init(VipsLogmat *logmat) * The program uses the following equation: (from Handbook of Pattern * Recognition and image processing by Young and Fu, AP 1986 pages 220-221): * - * H(r) = (1 / (2 * M_PI * s4)) * - * (2 - (r2 / s2)) * - * exp(-r2 / (2 * s2)) + * ``` + * H(r) = (1 / (2 * M_PI * s4)) * (2 - (r2 / s2)) * exp(-r2 / (2 * s2)) + * ``` + * + * where: * - * where s2 = @sigma * @sigma, s4 = s2 * s2, r2 = r * r. + * ``` + * 2 = @sigma * @sigma, + * s4 = s2 * s2 + * r2 = r * r. + * ``` * * The generated mask has odd size and its maximum value is normalised to - * 1.0, unless @precision is #VIPS_PRECISION_INTEGER. + * 1.0, unless @precision is [enum@Vips.Precision.INTEGER]. * * If @separable is set, only the centre horizontal is generated. This is * useful for separable convolutions. * - * If @precision is #VIPS_PRECISION_INTEGER, an integer mask is generated. + * If @precision is [enum@Vips.Precision.INTEGER], an integer mask is generated. * This is useful for integer convolutions. * * "scale" is set to the sum of all the mask elements. * - * See also: vips_gaussmat(), vips_conv(). + * ::: tip "Optional arguments" + * * @separable: `gboolean`, generate a separable mask + * * @precision: [enum@Precision] for @out + * + * ::: seealso + * [ctor@Image.gaussmat], [method@Image.conv]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask.c b/libvips/create/mask.c index de05b03780..6a75de6f31 100644 --- a/libvips/create/mask.c +++ b/libvips/create/mask.c @@ -114,8 +114,8 @@ vips_mask_class_init(VipsMaskClass *class) vobject_class->description = _("base class for frequency filters"); point_class->point = vips_mask_point; - point_class->min = 0.0; - point_class->max = 1.0; + point_class->min = 0.0F; + point_class->max = 1.0F; point_class->interpretation = VIPS_INTERPRETATION_FOURIER; VIPS_ARG_BOOL(class, "optical", 5, diff --git a/libvips/create/mask_butterworth.c b/libvips/create/mask_butterworth.c index 293e374e52..c1dff6da31 100644 --- a/libvips/create/mask_butterworth.c +++ b/libvips/create/mask_butterworth.c @@ -125,23 +125,25 @@ vips_mask_butterworth_init(VipsMaskButterworth *butterworth) * @order: filter order * @frequency_cutoff: frequency threshold * @amplitude_cutoff: amplitude threshold - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make an butterworth high- or low-pass filter, that is, one with a variable, * smooth transition * positioned at @frequency_cutoff, where @frequency_cutoff is in - * range 0 - 1. The shape of the curve is controlled by - * @order --- higher values give a sharper transition. See Gonzalez and Wintz, + * range 0 - 1. + * + * The shape of the curve is controlled by + * @order -- higher values give a sharper transition. See Gonzalez and Wintz, * Digital Image Processing, 1987. * - * See also: vips_mask_ideal(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_butterworth_band.c b/libvips/create/mask_butterworth_band.c index 80ee78ece8..40bd010b68 100644 --- a/libvips/create/mask_butterworth_band.c +++ b/libvips/create/mask_butterworth_band.c @@ -168,23 +168,24 @@ vips_mask_butterworth_band_init( * @frequency_cutoff_y: band position * @radius: band radius * @amplitude_cutoff: amplitude threshold - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make an butterworth band-pass or band-reject filter, that is, one with a * variable, smooth transition positioned at @frequency_cutoff_x, * @frequency_cutoff_y, of radius @radius. + * * The shape of the curve is controlled by - * @order --- higher values give a sharper transition. See Gonzalez and Wintz, + * @order -- higher values give a sharper transition. See Gonzalez and Wintz, * Digital Image Processing, 1987. * - * See also: vips_mask_ideal(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_butterworth_ring.c b/libvips/create/mask_butterworth_ring.c index 22b3515340..ecca3291ea 100644 --- a/libvips/create/mask_butterworth_ring.c +++ b/libvips/create/mask_butterworth_ring.c @@ -126,24 +126,26 @@ vips_mask_butterworth_ring_init( * @frequency_cutoff: frequency threshold * @amplitude_cutoff: amplitude threshold * @ringwidth: ringwidth - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make a butterworth ring-pass or ring-reject filter, that is, one with a * variable, * smooth transition * positioned at @frequency_cutoff of width @width, where @frequency_cutoff is - * in the range 0 - 1. The shape of the curve is controlled by - * @order --- higher values give a sharper transition. See Gonzalez and Wintz, + * in the range 0 - 1. + * + * The shape of the curve is controlled by + * @order -- higher values give a sharper transition. See Gonzalez and Wintz, * Digital Image Processing, 1987. * - * See also: vips_mask_ideal(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_fractal.c b/libvips/create/mask_fractal.c index 7d0de0a39d..1c0a6711f5 100644 --- a/libvips/create/mask_fractal.c +++ b/libvips/create/mask_fractal.c @@ -109,19 +109,21 @@ vips_mask_fractal_init(VipsMaskFractal *fractal) * @width: image size * @height: image size * @fractal_dimension: fractal dimension - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * This operation should be used to create fractal images by filtering the + * power spectrum of Gaussian white noise. * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * See [ctor@Image.gaussnoise]. * - * This operation should be used to create fractal images by filtering the - * power spectrum of Gaussian white noise. See vips_gaussnoise(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image * - * See also: vips_mask_ideal(). + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_gaussian.c b/libvips/create/mask_gaussian.c index 15a31377e1..520f65c42a 100644 --- a/libvips/create/mask_gaussian.c +++ b/libvips/create/mask_gaussian.c @@ -111,19 +111,19 @@ vips_mask_gaussian_init(VipsMaskGaussian *gaussian) * @height: image size * @frequency_cutoff: frequency threshold * @amplitude_cutoff: amplitude threshold - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make a gaussian high- or low-pass filter, that is, one with a variable, * smooth transition positioned at @frequency_cutoff. * - * See also: vips_mask_ideal(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_gaussian_band.c b/libvips/create/mask_gaussian_band.c index fac2bd5f09..1aa493c737 100644 --- a/libvips/create/mask_gaussian_band.c +++ b/libvips/create/mask_gaussian_band.c @@ -150,20 +150,20 @@ vips_mask_gaussian_band_init(VipsMaskGaussianBand *gaussian_band) * @frequency_cutoff_y: band position * @radius: band radius * @amplitude_cutoff: amplitude threshold - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make a gaussian band-pass or band-reject filter, that is, one with a * variable, smooth transition positioned at @frequency_cutoff_x, * @frequency_cutoff_y, of radius @radius. * - * See also: vips_mask_ideal(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_gaussian_ring.c b/libvips/create/mask_gaussian_ring.c index b037801cf9..0d55060a11 100644 --- a/libvips/create/mask_gaussian_ring.c +++ b/libvips/create/mask_gaussian_ring.c @@ -119,20 +119,20 @@ vips_mask_gaussian_ring_init(VipsMaskGaussianRing *gaussian_ring) * @frequency_cutoff: frequency threshold * @amplitude_cutoff: amplitude threshold * @ringwidth: ringwidth - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make a gaussian ring-pass or ring-reject filter, that is, one with a * variable, smooth transition positioned at @frequency_cutoff of width * @ringwidth. * - * See also: vips_mask_ideal(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_ideal.c b/libvips/create/mask_ideal.c index 0e8453a304..c5dc5e82ce 100644 --- a/libvips/create/mask_ideal.c +++ b/libvips/create/mask_ideal.c @@ -100,14 +100,7 @@ vips_mask_ideal_init(VipsMaskIdeal *ideal) * @width: image size * @height: image size * @frequency_cutoff: threshold at which filter ends - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make an ideal high- or low-pass filter, that is, one with a sharp cutoff * positioned at @frequency_cutoff, where @frequency_cutoff is in @@ -124,7 +117,7 @@ vips_mask_ideal_init(VipsMaskIdeal *ideal) * * Set @optical to position the DC component in the centre of the image. This * makes the mask suitable for multiplying against optical Fourier transforms. - * See vips_wrap(). + * See [method@Image.wrap]. * * Set @reject to invert the sense of * the filter. For example, low-pass becomes low-reject. @@ -132,11 +125,18 @@ vips_mask_ideal_init(VipsMaskIdeal *ideal) * Set @uchar to output an 8-bit unsigned char image rather than a * float image. In this case, pixels are in the range [0 - 255]. * - * See also: vips_mask_ideal(), vips_mask_ideal_ring(), - * vips_mask_ideal_band(), vips_mask_butterworth(), - * vips_mask_butterworth_ring(), vips_mask_butterworth_band(), - * vips_mask_gaussian(), vips_mask_gaussian_ring(), - * vips_mask_gaussian_band(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal], [ctor@Image.mask_ideal_ring], + * [ctor@Image.mask_ideal_band], [ctor@Image.mask_butterworth], + * [ctor@Image.mask_butterworth_ring], [ctor@Image.mask_butterworth_band], + * [ctor@Image.mask_gaussian], [ctor@Image.mask_gaussian_ring], + * [ctor@Image.mask_gaussian_band]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_ideal_band.c b/libvips/create/mask_ideal_band.c index 810275767a..9cd928837a 100644 --- a/libvips/create/mask_ideal_band.c +++ b/libvips/create/mask_ideal_band.c @@ -132,20 +132,20 @@ vips_mask_ideal_band_init(VipsMaskIdealBand *ideal_band) * @frequency_cutoff_x: position of band * @frequency_cutoff_y: position of band * @radius: size of band - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make an ideal band-pass or band-reject filter, that is, one with a * sharp cutoff around the point @frequency_cutoff_x, @frequency_cutoff_y, * of size @radius. * - * See also: vips_mask_ideal(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_ideal_ring.c b/libvips/create/mask_ideal_ring.c index 37ff4cc4c0..0e076b8236 100644 --- a/libvips/create/mask_ideal_ring.c +++ b/libvips/create/mask_ideal_ring.c @@ -115,20 +115,20 @@ vips_mask_ideal_ring_init(VipsMaskIdealRing *ideal_ring) * @height: image size * @frequency_cutoff: threshold at which filter ends * @ringwidth: ring width - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @nodc: don't set the DC pixel - * * @reject: invert the filter sense - * * @optical: coordinates in optical space - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Make an ideal ring-pass or ring-reject filter, that is, one with a sharp * ring positioned at @frequency_cutoff of width @width, where * @frequency_cutoff and @width are expressed as the range 0 - 1. * - * See also: vips_mask_ideal(). + * ::: tip "Optional arguments" + * * @nodc: `gboolean`, don't set the DC pixel + * * @reject: `gboolean`, invert the filter sense + * * @optical: `gboolean`, coordinates in optical space + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/perlin.c b/libvips/create/perlin.c index 0314261928..19ee8a1cad 100644 --- a/libvips/create/perlin.c +++ b/libvips/create/perlin.c @@ -45,6 +45,7 @@ #include #include +#include #include "pcreate.h" @@ -264,10 +265,10 @@ vips_perlin_make_tables(void *client) int i; for (i = 0; i < 256; i++) { - double angle = 2 * VIPS_PI * i / 256.0; + float angle = 2.0F * VIPS_PI * i / 256.0F; - vips_perlin_cos[i] = cos(angle); - vips_perlin_sin[i] = sin(angle); + vips_perlin_cos[i] = cosf(angle); + vips_perlin_sin[i] = sinf(angle); } return NULL; @@ -338,26 +339,25 @@ vips_perlin_init(VipsPerlin *perlin) * @out: (out): output image * @width: horizontal size * @height: vertical size - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @cell_size: %gint, size of Perlin cells - * * @uchar: output a uchar image - * - * Create a one-band float image of Perlin noise. See: - * - * https://en.wikipedia.org/wiki/Perlin_noise + * Create a one-band float image of [Perlin + * noise](https://en.wikipedia.org/wiki/Perlin_noise). * * Use @cell_size to set the size of the cells from which the image is * constructed. The default is 256 x 256. * * If @width and @height are multiples of @cell_size, the image will tessellate. * - * Normally, output pixels are #VIPS_FORMAT_FLOAT in the range [-1, +1]. Set - * @uchar to output a uchar image with pixels in [0, 255]. + * Normally, output pixels are [enum@Vips.BandFormat.FLOAT] in the range + * [-1, +1]. Set @uchar to output a uchar image with pixels in [0, 255]. + * + * ::: tip "Optional arguments" + * * @cell_size: `gint`, size of Perlin cells + * * @uchar: `gboolean`, output a uchar image * - * See also: vips_worley(), vips_fractsurf(), vips_gaussnoise(). + * ::: seealso + * [ctor@Image.worley], [ctor@Image.fractsurf], [ctor@Image.gaussnoise]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/point.c b/libvips/create/point.c index 7ade0d1af9..b052e1b0f0 100644 --- a/libvips/create/point.c +++ b/libvips/create/point.c @@ -133,8 +133,8 @@ vips_point_class_init(VipsPointClass *class) vobject_class->build = vips_point_build; class->point = NULL; - class->min = -1.0; - class->max = 1.0; + class->min = -1.0F; + class->max = 1.0F; class->interpretation = VIPS_INTERPRETATION_MULTIBAND; VIPS_ARG_INT(class, "width", 2, diff --git a/libvips/create/sdf.c b/libvips/create/sdf.c index e659ec5c7e..bbcf4c7535 100644 --- a/libvips/create/sdf.c +++ b/libvips/create/sdf.c @@ -92,7 +92,7 @@ G_DEFINE_TYPE(VipsSdf, vips_sdf, VIPS_TYPE_CREATE); static float vips_sdf_circle(VipsSdf *sdf, int x, int y) { - return hypot(x - sdf->a[0], y - sdf->a[1]) - sdf->r; + return hypotf(x - sdf->a[0], y - sdf->a[1]) - sdf->r; } static float @@ -101,10 +101,10 @@ vips_sdf_box(VipsSdf *sdf, int x, int y) float px = x - sdf->cx; float py = y - sdf->cy; - float dx = fabs(px) - sdf->sx; - float dy = fabs(py) - sdf->sy; + float dx = fabsf(px) - sdf->sx; + float dy = fabsf(py) - sdf->sy; - return hypot(VIPS_MAX(dx, 0), VIPS_MAX(dy, 0)) + + return hypotf(VIPS_MAX(dx, 0), VIPS_MAX(dy, 0)) + VIPS_MIN(VIPS_MAX(dx, dy), 0); } @@ -119,10 +119,10 @@ vips_sdf_rounded_box(VipsSdf *sdf, int x, int y) float r_bottom = px > 0 ? sdf->corners[1] : sdf->corners[3]; float r = py > 0 ? r_top : r_bottom; - float qx = fabs(px) - sdf->sx + r; - float qy = fabs(py) - sdf->sy + r; + float qx = fabsf(px) - sdf->sx + r; + float qy = fabsf(py) - sdf->sy + r; - return hypot(VIPS_MAX(qx, 0), VIPS_MAX(qy, 0)) + + return hypotf(VIPS_MAX(qx, 0), VIPS_MAX(qy, 0)) + VIPS_MIN(VIPS_MAX(qx, qy), 0) - r; } @@ -134,12 +134,12 @@ vips_sdf_line(VipsSdf *sdf, int px, int py) float dot_paba = pax * sdf->dx + pay * sdf->dy; float dot_baba = sdf->dx * sdf->dx + sdf->dy * sdf->dy; - float h = VIPS_CLIP(0, dot_paba / dot_baba, 1); + float h = VIPS_FCLIP(0, dot_paba / dot_baba, 1); float dx = pax - h * sdf->dx; float dy = pay - h * sdf->dy; - return hypot(dx, dy); + return hypotf(dx, dy); } static int @@ -363,31 +363,33 @@ vips_sdf_init(VipsSdf *sdf) * @width: horizontal size * @height: vertical size * @shape: SDF to create - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Create a signed distance field (SDF) image of the given @shape. * - * * @a: #VipsArrayDouble, first point - * * @b: #VipsArrayDouble, second point - * * @r: %gfloat, radius - * * @corners: #VipsArrayDouble, corner radii - * - * Create a signed distance field (SDF) image of the given shape. Different + * Different * shapes use different combinations of the optional arguments, see below. * - * @shape #VIPS_SDF_SHAPE_CIRCLE: create a circle centred on @a, radius @r. + * @shape [enum@Vips.SdfShape.CIRCLE]: create a circle centred on @a, radius @r. * - * @shape #VIPS_SDF_SHAPE_BOX: create a box with top-left corner @a and + * @shape [enum@Vips.SdfShape.BOX]: create a box with top-left corner @a and * bottom-right corner @b. * - * @shape #VIPS_SDF_SHAPE_ROUNDED_BOX: create a box with top-left corner @a + * @shape [enum@Vips.SdfShape.ROUNDED_BOX]: create a box with top-left corner @a * and bottom-right corner @b, whose four corners are * rounded by the four-element float array @corners. @corners will default to * 0.0. * - * @shape #VIPS_SDF_SHAPE_LINE: draw a line from @a to @b. + * @shape [enum@Vips.SdfShape.LINE]: draw a line from @a to @b. + * + * ::: tip "Optional arguments" + * * @a: [struct@ArrayDouble], first point + * * @b: [struct@ArrayDouble], second point + * * @r: `gdouble`, radius + * * @corners: [struct@ArrayDouble], corner radii * - * See also: vips_grey(), vips_grid(), vips_xyz(). + * ::: seealso + * [ctor@Image.grey], [method@Image.grid], [ctor@Image.xyz]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/sines.c b/libvips/create/sines.c index e342577794..a16056324e 100644 --- a/libvips/create/sines.c +++ b/libvips/create/sines.c @@ -81,7 +81,7 @@ vips_sines_point(VipsPoint *point, int x, int y) { VipsSines *sines = (VipsSines *) point; - return cos(sines->c * (x * sines->costheta - y * sines->sintheta)); + return cosf(sines->c * (x * sines->costheta - y * sines->sintheta)); } static int @@ -151,13 +151,7 @@ vips_sines_init(VipsSines *sines) * @out: (out): output image * @width: image size * @height: image size - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @hfreq: horizontal frequency - * * @vreq: vertical frequency - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Creates a float one band image of the a sine waveform in two * dimensions. @@ -172,7 +166,13 @@ vips_sines_init(VipsSines *sines) * * Pixels are normally in [-1, +1], set @uchar to output [0, 255]. * - * See also: vips_grey(), vips_xyz(). + * ::: tip "Optional arguments" + * * @hfreq: `gdouble`, horizontal frequency + * * @vreq: `gdouble`, vertical frequency + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.grey], [ctor@Image.xyz]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/text.c b/libvips/create/text.c index 43ff054f75..b8d5a3cf74 100644 --- a/libvips/create/text.c +++ b/libvips/create/text.c @@ -92,6 +92,11 @@ #include #ifdef HAVE_FONTCONFIG +/* ftconfig.h also appears to define HAVE_UNISTD_H. + */ +#ifdef HAVE_UNISTD_H +#undef HAVE_UNISTD_H +#endif #include #include #endif @@ -131,7 +136,7 @@ static PangoFontMap *vips_text_fontmap = NULL; /* ... single-thread vips_text_fontfiles with this. */ -static GMutex *vips_text_lock = NULL; +static GMutex vips_text_lock; /* All the fontfiles we've loaded. fontconfig lets you add a fontfile * repeatedly, and we obviously don't want that. @@ -314,7 +319,7 @@ vips_text_autofit(VipsText *text) previous_difference = difference; previous_dpi = text->dpi; - text->dpi = difference < 0 ? text->dpi * 2 : text->dpi / 2; + text->dpi = difference < 0 ? text->dpi * 2 : text->dpi / 2; // FIXME: Invalidates operation cache /* This can happen with fixed-size fonts. */ @@ -343,7 +348,7 @@ vips_text_autofit(VipsText *text) */ while (upper_dpi - lower_dpi > 1 && difference != 0) { - text->dpi = (upper_dpi + lower_dpi) / 2; + text->dpi = (upper_dpi + lower_dpi) / 2; // FIXME: Invalidates operation cache if (vips_text_get_extents(text, &extents)) return -1; target.left = extents.left; @@ -361,9 +366,9 @@ vips_text_autofit(VipsText *text) * must take lower. */ if (difference == 0) - text->dpi = upper_dpi; + text->dpi = upper_dpi; // FIXME: Invalidates operation cache else - text->dpi = lower_dpi; + text->dpi = lower_dpi; // FIXME: Invalidates operation cache g_object_set(text, "autofit_dpi", text->dpi, NULL); #ifdef DEBUG @@ -376,8 +381,7 @@ vips_text_autofit(VipsText *text) static void * vips_text_init_once(void *client) { - vips_text_lock = vips_g_mutex_new(); - vips_text_fontmap = pango_cairo_font_map_new(); + vips_text_fontmap = pango_cairo_font_map_new();; vips_text_fontfiles = g_hash_table_new(g_str_hash, g_str_equal); return NULL; @@ -416,7 +420,7 @@ vips_text_build(VipsObject *object) * between all vips_text instances, we must lock all the way to the * end of text rendering. */ - g_mutex_lock(vips_text_lock); + g_mutex_lock(&vips_text_lock); #ifdef HAVE_FONTCONFIG if (text->fontfile && @@ -441,8 +445,7 @@ vips_text_build(VipsObject *object) } #else /*!HAVE_FONTCONFIG*/ if (text->fontfile) - g_warning("%s", - _("ignoring fontfile (no fontconfig support)")); + g_warning("ignoring fontfile (no fontconfig support)"); #endif /*HAVE_FONTCONFIG*/ /* If our caller set height and not dpi, we adjust dpi until @@ -451,7 +454,7 @@ vips_text_build(VipsObject *object) if (vips_object_argument_isset(object, "height") && !vips_object_argument_isset(object, "dpi")) { if (vips_text_autofit(text)) { - g_mutex_unlock(vips_text_lock); + g_mutex_unlock(&vips_text_lock); return -1; } } @@ -459,13 +462,13 @@ vips_text_build(VipsObject *object) /* Layout. Can fail for "", for example. */ if (vips_text_get_extents(text, &extents)) { - g_mutex_unlock(vips_text_lock); + g_mutex_unlock(&vips_text_lock); return -1; } if (extents.width == 0 || extents.height == 0) { - g_mutex_unlock(vips_text_lock); + g_mutex_unlock(&vips_text_lock); vips_error(class->nickname, "%s", _("no text to render")); return -1; } @@ -480,7 +483,7 @@ vips_text_build(VipsObject *object) if (vips_image_pipelinev(t[0], VIPS_DEMAND_STYLE_ANY, NULL) || vips_image_write_prepare(t[0])) { - g_mutex_unlock(vips_text_lock); + g_mutex_unlock(&vips_text_lock); return -1; } in = t[0]; @@ -494,7 +497,7 @@ vips_text_build(VipsObject *object) status = cairo_surface_status(surface); if (status) { cairo_surface_destroy(surface); - g_mutex_unlock(vips_text_lock); + g_mutex_unlock(&vips_text_lock); vips_error(class->nickname, "%s", cairo_status_to_string(status)); return -1; @@ -509,7 +512,7 @@ vips_text_build(VipsObject *object) cairo_destroy(cr); - g_mutex_unlock(vips_text_lock); + g_mutex_unlock(&vips_text_lock); if (text->rgba) { /* Cairo makes pre-multipled BRGA -- we must byteswap and @@ -651,23 +654,11 @@ vips_text_init(VipsText *text) * vips_text: * @out: (out): output image * @text: utf-8 text string to render - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Draw the string @text to an image. * - * * @font: %gchararray, font to render with - * * @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, set justification alignment - * * @justify: %gboolean, justify lines - * * @dpi: %gint, render at this resolution - * * @autofit_dpi: %gint, read out auto-fitted DPI - * * @rgba: %gboolean, enable RGBA output - * * @spacing: %gint, space lines by this in points - * * @wrap: #VipsTextWrap, wrap lines on characters or words - * - * Draw the string @text to an image. @out is normally a one-band 8-bit + * @out is normally a one-band 8-bit * unsigned char image, with 0 for no text and 255 for text. Values between * are used for anti-aliasing. * @@ -697,7 +688,7 @@ vips_text_init(VipsText *text) * * @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. - * In this case, vips_text() will search for a @dpi and set of line breaks + * In this case, [ctor@Image.text] will search for a @dpi and set of line breaks * which will just fit the text into @width and @height. * * You can use @autofit_dpi to read out the DPI selected by auto fit. @@ -710,9 +701,23 @@ vips_text_init(VipsText *text) * * You can read the coordinate of the top edge of the character from `Xoffset` * / `Yoffset`. This can be helpful if you need to line up the output of - * several vips_text(). + * several [ctor@Image.text]. + * + * ::: tip "Optional arguments" + * * @font: `gchararray`, font to render with + * * @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: [enum@Align], set justification alignment + * * @justify: `gboolean`, justify lines + * * @dpi: `gint`, render at this resolution + * * @autofit_dpi: `gint`, read out auto-fitted DPI + * * @rgba: `gboolean`, enable RGBA output + * * @spacing: `gint`, space lines by this in points + * * @wrap: [enum@TextWrap], wrap lines on characters or words * - * See also: vips_bandjoin(), vips_composite(). + * ::: seealso + * [func@Image.bandjoin], [func@Image.composite]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/tonelut.c b/libvips/create/tonelut.c index d8cfd6fc18..d6d4bb6b8d 100644 --- a/libvips/create/tonelut.c +++ b/libvips/create/tonelut.c @@ -310,23 +310,12 @@ vips_tonelut_init(VipsTonelut *lut) /** * vips_tonelut: * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * [ctor@Image.tonelut] generates a tone curve for the adjustment of image + * levels. * - * * @in_max: input range - * * @out_max: output range - * * @Lb: black-point [0-100] - * * @Lw: white-point [0-100] - * * @Ps: shadow point (eg. 0.2) - * * @Pm: mid-tone point (eg. 0.5) - * * @Ph: highlight point (eg. 0.8) - * * @S: shadow adjustment (+/- 30) - * * @M: mid-tone adjustment (+/- 30) - * * @H: highlight adjustment (+/- 30) - * - * vips_tonelut() generates a tone curve for the adjustment of image - * levels. It is mostly designed for adjusting the L* part of a LAB image in + * This is mostly designed for adjusting the L* part of a LAB image in * a way suitable for print work, but you can use it for other things too. * * The curve is an unsigned 16-bit image with (@in_max + 1) entries, @@ -336,6 +325,18 @@ vips_tonelut_init(VipsTonelut *lut) * specify the scaling for the input and output images with the @in_max and * @out_max parameters. * + * ::: tip "Optional arguments" + * * @in_max: `gint`, input range + * * @out_max: `gint`, output range + * * @Lb: `gdouble`, black-point [0-100] + * * @Lw: `gdouble`, white-point [0-100] + * * @Ps: `gdouble`, shadow point (eg. 0.2) + * * @Pm: `gdouble`, mid-tone point (eg. 0.5) + * * @Ph: `gdouble`, highlight point (eg. 0.8) + * * @S: `gdouble`, shadow adjustment (+/- 30) + * * @M: `gdouble`, mid-tone adjustment (+/- 30) + * * @H: `gdouble`, highlight adjustment (+/- 30) + * * Returns: 0 on success, -1 on error */ int diff --git a/libvips/create/worley.c b/libvips/create/worley.c index 4482589c69..a4f7b9d894 100644 --- a/libvips/create/worley.c +++ b/libvips/create/worley.c @@ -48,6 +48,7 @@ #include #include +#include #include "pcreate.h" @@ -197,9 +198,9 @@ vips_worley_start(VipsImage *out, void *a, void *b) static float vips_int_hypot(int x, int y) { - /* Faster than hypot() for int args. + /* Faster than hypotf() for int args. */ - return sqrt(x * x + y * y); + return sqrtf(x * x + y * y); } static float @@ -344,22 +345,21 @@ vips_worley_init(VipsWorley *worley) * @out: (out): output image * @width: horizontal size * @height: vertical size - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @cell_size: %gint, size of Worley cells - * - * Create a one-band float image of Worley noise. See: - * - * https://en.wikipedia.org/wiki/Worley_noise + * Create a one-band float image of [Worley + * noise](https://en.wikipedia.org/wiki/Worley_noise). * * Use @cell_size to set the size of the cells from which the image is * constructed. The default is 256 x 256. * * If @width and @height are multiples of @cell_size, the image will tessellate. * - * See also: vips_perlin(), vips_fractsurf(), vips_gaussnoise(). + * ::: tip "Optional arguments" + * * @cell_size: `gint`, size of Worley cells + * + * ::: seealso + * [ctor@Image.perlin], [ctor@Image.fractsurf], [ctor@Image.gaussnoise]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/xyz.c b/libvips/create/xyz.c index f5046f3053..e5203a50a3 100644 --- a/libvips/create/xyz.c +++ b/libvips/create/xyz.c @@ -239,13 +239,7 @@ vips_xyz_init(VipsXyz *xyz) * @out: (out): output image * @width: horizontal size * @height: vertical size - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @csize: %gint, size for third dimension - * * @dsize: %gint, size for fourth dimension - * * @esize: %gint, size for fifth dimension + * @...: `NULL`-terminated list of optional named arguments * * Create a two-band uint32 image where the elements in the first band have the * value of their x coordinate and elements in the second band have their y @@ -256,9 +250,15 @@ vips_xyz_init(VipsXyz *xyz) * * Set @csize, @dsize, @esize to generate higher dimensions and add more * bands. The extra dimensions are placed down the vertical axis. Use - * vips_grid() to change the layout. + * [method@Image.grid] to change the layout. + * + * ::: tip "Optional arguments" + * * @csize: `gint`, size for third dimension + * * @dsize: `gint`, size for fourth dimension + * * @esize: `gint`, size for fifth dimension * - * See also: vips_grey(), vips_grid(), vips_identity(). + * ::: seealso + * [ctor@Image.grey], [method@Image.grid], [ctor@Image.identity]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/zone.c b/libvips/create/zone.c index 4d881ab397..727d1a355c 100644 --- a/libvips/create/zone.c +++ b/libvips/create/zone.c @@ -75,9 +75,9 @@ vips_zone_point(VipsPoint *point, int x, int y) int hheight = point->height / 2; int h2 = (x - hwidth) * (x - hwidth); int v2 = (y - hheight) * (y - hheight); - double c = VIPS_PI / zone->width; + float c = VIPS_PI / zone->width; - return cos(c * (v2 + h2)); + return cosf(c * (v2 + h2)); } static void @@ -102,17 +102,17 @@ vips_zone_init(VipsZone *zone) * @out: (out): output image * @width: image size * @height: image size - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @uchar: output a uchar image + * @...: `NULL`-terminated list of optional named arguments * * Create a one-band image of a zone plate. * * Pixels are normally in [-1, +1], set @uchar to output [0, 255]. * - * See also: vips_eye(), vips_xyz(). + * ::: tip "Optional arguments" + * * @uchar: `gboolean`, output a uchar image + * + * ::: seealso + * [ctor@Image.eye], [ctor@Image.xyz]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/deprecated/format.c b/libvips/deprecated/format.c index 877848672d..191b12f803 100644 --- a/libvips/deprecated/format.c +++ b/libvips/deprecated/format.c @@ -296,7 +296,7 @@ im__format_init(void) vips_format_fits_get_type(); #endif /*HAVE_CFITSIO*/ vips_format_rad_get_type(); -#ifdef HAVE_MAGICK +#if defined(HAVE_MAGICK6) || defined(HAVE_MAGICK7) extern GType vips_format_magick_get_type(void); vips_format_magick_get_type(); #endif /*HAVE_MAGICK*/ @@ -327,7 +327,7 @@ format_for_file_sub(VipsFormatClass *format, } /** - * vips_format_for_file: + * vips_format_for_file: (skip) * @filename: file to find a format for * * Searches for a format you could use to load a file. @@ -378,7 +378,7 @@ format_for_name_sub(VipsFormatClass *format, const char *name) } /** - * vips_format_for_name: + * vips_format_for_name: (skip) * @filename: name to find a format for * * Searches for a format you could use to save a file. diff --git a/libvips/deprecated/im_exr2vips.c b/libvips/deprecated/im_exr2vips.c index 5b8e0298f1..3bff896312 100644 --- a/libvips/deprecated/im_exr2vips.c +++ b/libvips/deprecated/im_exr2vips.c @@ -46,7 +46,6 @@ #include #include -#include #include #include "../foreign/pforeign.h" diff --git a/libvips/deprecated/im_lab_morph.c b/libvips/deprecated/im_lab_morph.c index 987c9918d6..daa469f6d2 100644 --- a/libvips/deprecated/im_lab_morph.c +++ b/libvips/deprecated/im_lab_morph.c @@ -208,42 +208,18 @@ morph_buffer(float *in, float *out, int width, Params *parm) * * We perform three adjustments: * - * - * - * - * cast + * ## Cast * * Pass in @mask containing CIELAB readings for a neutral greyscale. For * example: * - * - * - * - * 3 - * 4 - * - * - * 14.23 - * 4.8 - * -3.95 - * - * - * 18.74 - * 2.76 - * -2.62 - * - * - * 23.46 - * 1.4 - * -1.95 - * - * - * 27.53 - * 1.76 - * -2.01 - * - * - * + * ``` + * 3 4 + * 14.23 4.8 -3.95 + * 18.74 2.76 -2.62 + * 23.46 1.4 -1.95 + * 27.53 1.76 -2.01 + * ``` * * Interpolation from this makes cast corrector. The top and tail are * interpolated towards [0, 0, 0] and [100, 0, 0], intermediate values are @@ -252,23 +228,14 @@ morph_buffer(float *in, float *out, int width, Params *parm) * * Each pixel is displaced in a/b by the amount specified for that L in the * table. - * - * - * - * - * L* + * + * ## L* * * Pass in scale and offset for L. L' = (L + offset) * scale. - * - * - * - * - * saturation + * + * ## Saturation * * scale a and b by these amounts, eg. 1.5 increases saturation. - * - * - * * * Find the top two by generating and printing a greyscale. Find the bottom * by printing a Macbeth and looking at a/b spread diff --git a/libvips/deprecated/im_magick2vips.c b/libvips/deprecated/im_magick2vips.c index 803d247044..c0a761f58d 100644 --- a/libvips/deprecated/im_magick2vips.c +++ b/libvips/deprecated/im_magick2vips.c @@ -42,21 +42,22 @@ #include -#include "../foreign/pforeign.h" - int im_magick2vips(const char *filename, IMAGE *out) { -#ifdef HAVE_MAGICK + VipsImage *t; + /* Old behaviour was always to read all frames. */ - return vips__magick_read(filename, out, NULL, 0, -1); -#else - vips_error("im_magick2vips", - "%s", _("no libMagick support in your libvips")); + if (vips_magickload(filename, &t, "n", -1, NULL)) + return -1; + if (vips_image_write(t, out)) { + g_object_unref(t); + return -1; + } + g_object_unref(t); - return -1; -#endif /*HAVE_MAGICK*/ + return 0; } static int diff --git a/libvips/deprecated/im_nifti2vips.c b/libvips/deprecated/im_nifti2vips.c index c16146cf7f..895f52b5e4 100644 --- a/libvips/deprecated/im_nifti2vips.c +++ b/libvips/deprecated/im_nifti2vips.c @@ -46,7 +46,6 @@ #include #include -#include #include static int diff --git a/libvips/deprecated/im_openslide2vips.c b/libvips/deprecated/im_openslide2vips.c index 2e582e3a32..295b927eee 100644 --- a/libvips/deprecated/im_openslide2vips.c +++ b/libvips/deprecated/im_openslide2vips.c @@ -50,7 +50,6 @@ #include #include -#include #include static int diff --git a/libvips/deprecated/im_tiff2vips.c b/libvips/deprecated/im_tiff2vips.c index e43b34646e..cb0f4f929b 100644 --- a/libvips/deprecated/im_tiff2vips.c +++ b/libvips/deprecated/im_tiff2vips.c @@ -47,7 +47,6 @@ #include #include -#include #include "../foreign/pforeign.h" @@ -75,7 +74,7 @@ im_tiff_read_header(const char *filename, VipsImage *out, if (!(source = vips_source_new_from_file(filename))) return -1; if (vips__tiff_read_header_source(source, out, - page, n, autorotate, -1, VIPS_FAIL_ON_ERROR)) { + page, n, autorotate, -1, VIPS_FAIL_ON_ERROR, TRUE)) { VIPS_UNREF(source); return -1; } @@ -93,7 +92,7 @@ im_tiff_read(const char *filename, VipsImage *out, if (!(source = vips_source_new_from_file(filename))) return -1; if (vips__tiff_read_source(source, out, - page, n, autorotate, -1, VIPS_FAIL_ON_ERROR)) { + page, n, autorotate, -1, VIPS_FAIL_ON_ERROR, TRUE)) { VIPS_UNREF(source); return -1; } diff --git a/libvips/deprecated/im_vips2dz.c b/libvips/deprecated/im_vips2dz.c index c4c0c648e1..d64bc33a34 100644 --- a/libvips/deprecated/im_vips2dz.c +++ b/libvips/deprecated/im_vips2dz.c @@ -63,7 +63,7 @@ im_vips2dz(IMAGE *in, const char *filename) gboolean centre = FALSE; VipsAngle angle = VIPS_ANGLE_D0; - /* We can't use im_filename_split() --- it assumes that we have a + /* We can't use im_filename_split() -- it assumes that we have a * filename with an extension before the ':', and filename here is * actually a dirname. * diff --git a/libvips/deprecated/im_vips2mask.c b/libvips/deprecated/im_vips2mask.c index a7f4406838..85477457bb 100644 --- a/libvips/deprecated/im_vips2mask.c +++ b/libvips/deprecated/im_vips2mask.c @@ -216,15 +216,15 @@ im_vips2imask(IMAGE *in, const char *filename) * we need RRRGGGBBB. */ out->coeff[x + y * width] = - VIPS_RINT(data[x * height + y]); + rint(data[x * height + y]); else out->coeff[x + y * width] = - VIPS_RINT(data[x + y * width]); + rint(data[x + y * width]); - out->scale = VIPS_RINT(vips_image_get_scale(in)); + out->scale = rint(vips_image_get_scale(in)); if (out->scale == 0) out->scale = 1; - out->offset = VIPS_RINT(vips_image_get_offset(in)); + out->offset = rint(vips_image_get_offset(in)); /* Now convolve a 1 everywhere image with the int version we've made, * what do we get? @@ -237,7 +237,7 @@ im_vips2imask(IMAGE *in, const char *filename) /* And adjust the scale to get as close to a match as we can. */ - out->scale = VIPS_RINT(out->scale + (int_result - double_result)); + out->scale = rint(out->scale + (int_result - double_result)); if (out->scale == 0) out->scale = 1; diff --git a/libvips/deprecated/package.c b/libvips/deprecated/package.c index 9544779d06..68860ccf4c 100644 --- a/libvips/deprecated/package.c +++ b/libvips/deprecated/package.c @@ -645,9 +645,9 @@ plugin_free(Plugin *plug) } VIPS_FREE(plug->name); plug->pack = NULL; - g_free(plug); plugin_list = g_slist_remove(plugin_list, plug); + g_free(plug); return 0; } @@ -745,7 +745,7 @@ im_load_plugins(const char *fmt, ...) return 0; va_start(ap, fmt); - (void) im_vsnprintf(dir_name, VIPS_PATH_MAX - 1, fmt, ap); + (void) im_vsnprintf(dir_name, VIPS_PATH_MAX, fmt, ap); va_end(ap); g_info("im_load_plugins: searching \"%s\"", dir_name); @@ -760,7 +760,7 @@ im_load_plugins(const char *fmt, ...) if (im_ispostfix(name, ".plg")) { char path[VIPS_PATH_MAX]; - im_snprintf(path, VIPS_PATH_MAX - 1, + im_snprintf(path, VIPS_PATH_MAX, "%s" G_DIR_SEPARATOR_S "%s", dir_name, name); if (!im_load_plugin(path)) result = -1; diff --git a/libvips/deprecated/rename.c b/libvips/deprecated/rename.c index 4ac3209b38..9a38453178 100644 --- a/libvips/deprecated/rename.c +++ b/libvips/deprecated/rename.c @@ -1,4 +1,4 @@ -/* rename.c --- wrappers for various renamed functions +/* rename.c -- wrappers for various renamed functions * * 20/9/09 */ @@ -128,6 +128,42 @@ im_warning(const char *fmt, ...) va_end(ap); } +GMutex * +vips_g_mutex_new(void) +{ + GMutex *mutex; + + mutex = g_new(GMutex, 1); + g_mutex_init(mutex); + + return mutex; +} + +void +vips_g_mutex_free(GMutex *mutex) +{ + g_mutex_clear(mutex); + g_free(mutex); +} + +GCond * +vips_g_cond_new(void) +{ + GCond *cond; + + cond = g_new(GCond, 1); + g_cond_init(cond); + + return cond; +} + +void +vips_g_cond_free(GCond *cond) +{ + g_cond_clear(cond); + g_free(cond); +} + void * vips_g_thread_join(GThread *thread) { @@ -431,7 +467,7 @@ vips_rawsave_fd(VipsImage *in, int fd, ...) va_list ap; int result; VipsTarget *target; - + if (!(target = vips_target_new_to_descriptor(fd))) return -1; @@ -774,13 +810,13 @@ void vips_vinfo(const char *domain, const char *fmt, va_list ap) { if (vips__info) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); (void) fprintf(stderr, _("%s: "), _("info")); if (domain) (void) fprintf(stderr, _("%s: "), domain); (void) vfprintf(stderr, fmt, ap); (void) fprintf(stderr, "\n"); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } } @@ -799,13 +835,13 @@ vips_vwarn(const char *domain, const char *fmt, va_list ap) { if (!g_getenv("IM_WARNING") && !g_getenv("VIPS_WARNING")) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); (void) fprintf(stderr, _("%s: "), _("vips warning")); if (domain) (void) fprintf(stderr, _("%s: "), domain); (void) vfprintf(stderr, fmt, ap); (void) fprintf(stderr, "\n"); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } if (vips__fatal) diff --git a/libvips/deprecated/video_dispatch.c b/libvips/deprecated/video_dispatch.c index 18dd57af42..1a22d3529a 100644 --- a/libvips/deprecated/video_dispatch.c +++ b/libvips/deprecated/video_dispatch.c @@ -37,16 +37,6 @@ #include -/** - * SECTION: video - * @short_description: various video grabbers - * @see_also: image - * @stability: Stable - * @include: vips/vips.h - * - * Read an image from a video source. - */ - static int video_v4l1_vec(im_object *argv) { diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index e9c6a7212b..b637bcaa2c 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -765,7 +765,7 @@ im_wrapmany(IMAGE **in, IMAGE *out, im_wrapmany_fn fn, void *a, void *b) bun->a = a; bun->b = b; - /* Check descriptors --- make sure that our caller has done this + /* Check descriptors -- make sure that our caller has done this * correctly. */ for (i = 0; i < n; i++) { @@ -5707,7 +5707,7 @@ im__insert_base(const char *domain, * * The two input images are cast up to the smallest common type (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). * * See also: im_insert(), im_lrjoin(). * diff --git a/libvips/draw/draw.c b/libvips/draw/draw.c index 88e4bb87b1..8dc1127efa 100644 --- a/libvips/draw/draw.c +++ b/libvips/draw/draw.c @@ -45,48 +45,18 @@ #include "pdraw.h" -/** - * SECTION: draw - * @short_description: drawing operations: flood, paste, line, circle - * @stability: Stable - * @include: vips/vips.h - * - * These operations directly modify the image. They do not thread, on 32-bit - * machines they will be limited to 2GB images, and a little care needs to be - * taken if you use them as part of an image pipeline. - * They are mostly supposed to be useful for paintbox-style programs. - * - * libvips operations are all functional: they take zero or more existing input - * images and generate zero or more new output images. Images are - * never altered, you always create new images. This means libvips can cache - * and thread very aggressively. - * - * The downside is that creating entirely fresh images each time can be very - * slow. libvips has a range of tricks to avoid these problems, but there are - * still times when you really have to be able to modify an image. An example - * might be drawing a curved line from a set of straight line segments: if you - * need to draw 1,000 straight lines, a 1,000 operation-deep pipeline is going - * to be a slow way to do it. This is where the draw operations come in. - * - * To use these operations, use vips_image_copy_memory() to make a private - * memory copy of the image you want to modify, 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. - */ - /** * VipsCombineMode: * @VIPS_COMBINE_MODE_SET: set pixels to the new value * @VIPS_COMBINE_MODE_ADD: add pixels * - * See vips_draw_image() and so on. + * See [method@Image.draw_image] and so on. * - * Operations like vips_draw_image() need to be told how to combine images + * Operations like [method@Image.draw_image] need to be told how to combine images * from two sources. * - * See also: vips_join(). + * ::: seealso + * [method@Image.join]. */ G_DEFINE_ABSTRACT_TYPE(VipsDraw, vips_draw, VIPS_TYPE_OPERATION); @@ -122,6 +92,7 @@ vips_draw_class_init(VipsDrawClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(class); + VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class); gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -130,6 +101,9 @@ vips_draw_class_init(VipsDrawClass *class) vobject_class->description = _("draw operations"); vobject_class->build = vips_draw_build; + // no draw operation is cached + operation_class->flags |= VIPS_OPERATION_NOCACHE; + VIPS_ARG_IMAGE(class, "image", 1, _("Image"), _("Image to draw on"), diff --git a/libvips/draw/draw_circle.c b/libvips/draw/draw_circle.c index d319512e33..ed3d43cfe9 100644 --- a/libvips/draw/draw_circle.c +++ b/libvips/draw/draw_circle.c @@ -288,18 +288,20 @@ vips_draw_circlev(VipsImage *image, * @cx: centre of draw_circle * @cy: centre of draw_circle * @radius: draw_circle radius - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Draws a circle on @image. * - * * @fill: fill the draw_circle - * - * Draws a circle on @image. If @fill is %TRUE then the circle is filled, + * If @fill is `TRUE` then the circle is filled, * otherwise a 1-pixel-wide perimeter is drawn. * * @ink is an array of double containing values to draw. * - * See also: vips_draw_circle1(), vips_draw_line(). + * ::: tip "Optional arguments" + * * @fill: `gboolean`, fill the draw_circle + * + * ::: seealso + * [method@Image.draw_circle1], [method@Image.draw_line]. * * Returns: 0 on success, or -1 on error. */ @@ -324,15 +326,15 @@ vips_draw_circle(VipsImage *image, * @cx: centre of draw_circle * @cy: centre of draw_circle * @radius: draw_circle radius - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @fill: fill the draw_circle + * As [method@Image.draw_circle], but just takes a single double for @ink. * - * As vips_draw_circle(), but just takes a single double for @ink. + * ::: tip "Optional arguments" + * * @fill: `gboolean`, fill the draw_circle * - * See also: vips_draw_circle(). + * ::: seealso + * [method@Image.draw_circle]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/draw/draw_flood.c b/libvips/draw/draw_flood.c index 6717635327..36d762cc08 100644 --- a/libvips/draw/draw_flood.c +++ b/libvips/draw/draw_flood.c @@ -694,18 +694,11 @@ vips_draw_floodv(VipsImage *image, * @n: length of ink array * @x: centre of circle * @y: centre of circle - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Flood-fill @image with @ink, starting at position @x, @y. * - * * @test: test this image - * * @equal: fill while equal to edge - * * @left: output left edge of bounding box of modified area - * * @top: output top edge of bounding box of modified area - * * @width: output width of bounding box of modified area - * * @height: output height of bounding box of modified area - * - * Flood-fill @image with @ink, starting at position @x, @y. The filled area is + * The filled area is * bounded by pixels that are equal to the ink colour, in other words, it * searches for pixels enclosed by an edge of @ink. * @@ -719,9 +712,18 @@ vips_draw_floodv(VipsImage *image, * @left, @top, @width, @height output the bounding box of the modified * pixels. * + * ::: tip "Optional arguments" + * * @test: [class@Image], test this image + * * @equal: `gboolean`, fill while equal to edge + * * @left: `gint`, output left edge of bounding box of modified area + * * @top: `gint`, output top edge of bounding box of modified area + * * @width: `gint`, output width of bounding box of modified area + * * @height: `gint`, output height of bounding box of modified area + * * @ink is an array of double containing values to draw. * - * See also: vips_draw_flood1(). + * ::: seealso + * [method@Image.draw_flood1]. * * Returns: 0 on success, or -1 on error. */ @@ -745,20 +747,20 @@ vips_draw_flood(VipsImage *image, * @ink: value to draw * @x: centre of circle * @y: centre of circle - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @test: test this image - * * @equal: fill while equal to edge - * * @left: output left edge of bounding box of modified area - * * @top: output top edge of bounding box of modified area - * * @width: output width of bounding box of modified area - * * @height: output height of bounding box of modified area + * As [method@Image.draw_flood], but just takes a single double for @ink. * - * As vips_draw_flood(), but just takes a single double for @ink. + * ::: tip "Optional arguments" + * * @test: [class@Image], test this image + * * @equal: `gboolean`, fill while equal to edge + * * @left: `gint`, output left edge of bounding box of modified area + * * @top: `gint`, output top edge of bounding box of modified area + * * @width: `gint`, output width of bounding box of modified area + * * @height: `gint`, output height of bounding box of modified area * - * See also: vips_draw_flood(). + * ::: seealso + * [method@Image.draw_flood]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/draw/draw_image.c b/libvips/draw/draw_image.c index 00c73d5668..d76d1c870c 100644 --- a/libvips/draw/draw_image.c +++ b/libvips/draw/draw_image.c @@ -305,21 +305,23 @@ vips_draw_image_init(VipsDrawImage *draw_image) * @sub: image to paint * @x: draw @sub here * @y: draw @sub here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Draw @sub on top of @image at position @x, @y. * - * * @mode: how to combine pixels - * - * Draw @sub on top of @image at position @x, @y. The two images must have the + * The two images must have the * same Coding. If @sub has 1 band, the bands will be duplicated to match the * number of bands in @image. @sub will be converted to @image's format, see - * vips_cast(). + * [method@Image.cast]. * * Use @mode to set how pixels are combined. If you use - * #VIPS_COMBINE_MODE_ADD, both images muct be uncoded. + * [enum@Vips.CombineMode.ADD], both images must be uncoded. + * + * ::: tip "Optional arguments" + * * @mode: [enum@CombineMode], how to combine pixels * - * See also: vips_draw_mask(), vips_insert(). + * ::: seealso + * [method@Image.draw_mask], [method@Image.insert]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/draw/draw_line.c b/libvips/draw/draw_line.c index df1c7a669c..085f75d08f 100644 --- a/libvips/draw/draw_line.c +++ b/libvips/draw/draw_line.c @@ -338,13 +338,14 @@ vips_draw_linev(VipsImage *image, * @y1: start of draw_line * @x2: end of draw_line * @y2: end of draw_line - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Draws a 1-pixel-wide line on an image. * * @ink is an array of double containing values to draw. * - * See also: vips_draw_line1(), vips_draw_circle(), vips_draw_mask(). + * ::: seealso + * [method@Image.draw_line1], [method@Image.draw_circle], [method@Image.draw_mask]. * * Returns: 0 on success, or -1 on error. */ @@ -370,11 +371,12 @@ vips_draw_line(VipsImage *image, * @y1: start of draw_line * @x2: end of draw_line * @y2: end of draw_line - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_draw_line(), but just take a single double for @ink. + * As [method@Image.draw_line], but just take a single double for @ink. * - * See also: vips_draw_line(). + * ::: seealso + * [method@Image.draw_line]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/draw/draw_mask.c b/libvips/draw/draw_mask.c index 98b6e8c81e..b3cceeb226 100644 --- a/libvips/draw/draw_mask.c +++ b/libvips/draw/draw_mask.c @@ -377,16 +377,17 @@ vips_draw_maskv(VipsImage *image, * @mask: mask of 0/255 values showing where to plot * @x: draw mask here * @y: draw mask here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Draw @mask on the image. @mask is a monochrome 8-bit image with 0/255 * for transparent or @ink coloured points. Intermediate values blend the ink - * with the pixel. Use with vips_text() to draw text on an image. Use in a - * vips_draw_line() subclass to draw an object along a line. + * with the pixel. Use with [ctor@Image.text] to draw text on an image. Use in a + * [method@Image.draw_line] subclass to draw an object along a line. * * @ink is an array of double containing values to draw. * - * See also: vips_text(), vips_draw_line(). + * ::: seealso + * [ctor@Image.text], [method@Image.draw_line]. * * Returns: 0 on success, or -1 on error. */ @@ -411,11 +412,12 @@ vips_draw_mask(VipsImage *image, * @mask: mask of 0/255 values showing where to plot * @x: draw mask here * @y: draw mask here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_draw_mask(), but just takes a single double for @ink. + * As [method@Image.draw_mask], but just takes a single double for @ink. * - * See also: vips_draw_mask(). + * ::: seealso + * [method@Image.draw_mask]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/draw/draw_rect.c b/libvips/draw/draw_rect.c index f6af4ac08b..4dc1114b45 100644 --- a/libvips/draw/draw_rect.c +++ b/libvips/draw/draw_rect.c @@ -235,16 +235,17 @@ vips_draw_rectv(VipsImage *image, * @top: area to paint * @width: area to paint * @height: area to paint - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Paint pixels within @left, @top, @width, @height in @image with @ink. * - * * @fill: fill the rect + * If @fill is zero, just paint a 1-pixel-wide outline. * - * Paint pixels within @left, @top, @width, @height in @image with @ink. If - * @fill is zero, just paint a 1-pixel-wide outline. + * ::: tip "Optional arguments" + * * @fill: `gboolean`, fill the rect * - * See also: vips_draw_circle(). + * ::: seealso + * [method@Image.draw_circle]. * * Returns: 0 on success, or -1 on error. */ @@ -271,15 +272,15 @@ vips_draw_rect(VipsImage *image, * @top: area to paint * @width: area to paint * @height: area to paint - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * As [method@Image.draw_rect], but just take a single double for @ink. * - * * @fill: fill the rect + * ::: tip "Optional arguments" + * * @fill: `gboolean`, fill the rect * - * As vips_draw_rect(), but just take a single double for @ink. - * - * See also: vips_draw_rect(). + * ::: seealso + * [method@Image.draw_rect]. * * Returns: 0 on success, or -1 on error. */ @@ -308,11 +309,12 @@ vips_draw_rect1(VipsImage *image, * @n: length of ink array * @x: point to paint * @y: point to paint - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_draw_rect(), but draw a single pixel at @x, @y. + * As [method@Image.draw_rect], but draw a single pixel at @x, @y. * - * See also: vips_draw_rect(). + * ::: seealso + * [method@Image.draw_rect]. * * Returns: 0 on success, or -1 on error. */ @@ -335,11 +337,12 @@ vips_draw_point(VipsImage *image, double *ink, int n, int x, int y, ...) * @ink: value to draw * @x: point to draw * @y: point to draw - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_draw_point(), but just take a single double for @ink. + * As [method@Image.draw_point], but just take a single double for @ink. * - * See also: vips_draw_point(). + * ::: seealso + * [method@Image.draw_point]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/draw/draw_smudge.c b/libvips/draw/draw_smudge.c index fb36269ea5..3038fe2acd 100644 --- a/libvips/draw/draw_smudge.c +++ b/libvips/draw/draw_smudge.c @@ -252,12 +252,13 @@ vips_draw_smudge_init(VipsDrawSmudge *draw_smudge) * @top: point to paint * @width: area to paint * @height: area to paint - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Smudge a section of @image. Each pixel in the area @left, @top, @width, * @height is replaced by the average of the surrounding 3x3 pixels. * - * See also: vips_draw_line(). + * ::: seealso + * [method@Image.draw_line]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/foreign/analyzeload.c b/libvips/foreign/analyzeload.c index baa4b7b587..1644c70c9a 100644 --- a/libvips/foreign/analyzeload.c +++ b/libvips/foreign/analyzeload.c @@ -156,7 +156,7 @@ vips_foreign_load_analyze_init(VipsForeignLoadAnalyze *analyze) * vips_analyzeload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Load an Analyze 6.0 file. If @filename is "fred.img", this will look for * an image header called "fred.hdr" and pixel data in "fred.img". You can @@ -166,7 +166,8 @@ vips_foreign_load_analyze_init(VipsForeignLoadAnalyze *analyze) * loaded lazilly and byte-swapped, if necessary. The Analyze metadata is read * and attached. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/archive.c b/libvips/foreign/archive.c index ad16e114cd..6a2f7bb716 100644 --- a/libvips/foreign/archive.c +++ b/libvips/foreign/archive.c @@ -56,7 +56,7 @@ #include #include -static GMutex *vips_libarchive_mutex = NULL; +static GMutex vips_libarchive_mutex; struct _VipsArchive { // prepend filenames with this for filesystem output @@ -102,30 +102,12 @@ zip_close_target_cb(struct archive *a, void *client_data) return ARCHIVE_OK; } -static void * -vips__archive_once_init(void *client) -{ - vips_libarchive_mutex = vips_g_mutex_new(); - - return NULL; -} - -static void -vips__archive_init(void) -{ - static GOnce once = G_ONCE_INIT; - - VIPS_ONCE(&once, vips__archive_once_init, NULL); -} - // write to a filesystem directory VipsArchive * vips__archive_new_to_dir(const char *base_dirname) { VipsArchive *archive; - vips__archive_init(); - if (!(archive = VIPS_NEW(NULL, VipsArchive))) return NULL; @@ -146,8 +128,6 @@ vips__archive_new_to_target(VipsTarget *target, base_dirname, compression); #endif /*DEBUG*/ - vips__archive_init(); - if (!(archive = VIPS_NEW(NULL, VipsArchive))) return NULL; @@ -254,11 +234,11 @@ vips__archive_mkfile_zip(VipsArchive *archive, { struct archive_entry *entry; - vips__worker_lock(vips_libarchive_mutex); + vips__worker_lock(&vips_libarchive_mutex); if (!(entry = archive_entry_new())) { vips_error("archive", "%s", _("unable to create entry")); - g_mutex_unlock(vips_libarchive_mutex); + g_mutex_unlock(&vips_libarchive_mutex); return -1; } @@ -275,7 +255,7 @@ vips__archive_mkfile_zip(VipsArchive *archive, if (archive_write_header(archive->archive, entry)) { vips_error("archive", "%s", _("unable to write header")); archive_entry_free(entry); - g_mutex_unlock(vips_libarchive_mutex); + g_mutex_unlock(&vips_libarchive_mutex); return -1; } @@ -283,11 +263,11 @@ vips__archive_mkfile_zip(VipsArchive *archive, if (archive_write_data(archive->archive, buf, len) != len) { vips_error("archive", "%s", _("unable to write data")); - g_mutex_unlock(vips_libarchive_mutex); + g_mutex_unlock(&vips_libarchive_mutex); return -1; } - g_mutex_unlock(vips_libarchive_mutex); + g_mutex_unlock(&vips_libarchive_mutex); return 0; } diff --git a/libvips/foreign/cgifsave.c b/libvips/foreign/cgifsave.c index 1ed54da3c5..5ecca78d6c 100644 --- a/libvips/foreign/cgifsave.c +++ b/libvips/foreign/cgifsave.c @@ -48,6 +48,7 @@ #include #include +#include #include "pforeign.h" #include "quantise.h" @@ -498,7 +499,7 @@ vips_foreign_save_cgif_pick_quantiser(VipsForeignSaveCgif *cgif, return 0; } -/* We have a complete frame --- write! +/* We have a complete frame -- write! */ static int vips_foreign_save_cgif_write_frame(VipsForeignSaveCgif *cgif) @@ -590,6 +591,12 @@ vips_foreign_save_cgif_write_frame(VipsForeignSaveCgif *cgif) VIPS_FREEF(vips__quantise_image_destroy, image); + /* Remapping is relatively slow, trigger eval callbacks. + */ + vips_image_eval(cgif->in, n_pels); + if (vips_image_iskilled(cgif->in)) + return -1; + /* Set up cgif on first use. */ if (!cgif->cgif_context) { @@ -659,8 +666,7 @@ vips_foreign_save_cgif_write_frame(VipsForeignSaveCgif *cgif) if (cgif->delay && cgif->page_number < cgif->delay_length) - frame_config.delay = - VIPS_RINT(cgif->delay[cgif->page_number] / 10.0); + frame_config.delay = rint(cgif->delay[cgif->page_number] / 10.0); /* Attach a local palette, if we need one. */ @@ -676,8 +682,7 @@ vips_foreign_save_cgif_write_frame(VipsForeignSaveCgif *cgif) #ifdef HAVE_CGIF_FRAME_ATTR_INTERLACED frame_config.attrFlags |= CGIF_FRAME_ATTR_INTERLACED; #else /*!HAVE_CGIF_FRAME_ATTR_INTERLACED*/ - g_warning("%s: cgif >= v0.3.0 required for interlaced GIF write", - class->nickname); + g_warning("cgif >= v0.3.0 required for interlaced GIF write"); #endif /*HAVE_CGIF_FRAME_ATTR_INTERLACED*/ } @@ -880,7 +885,8 @@ vips_foreign_save_cgif_class_init(VipsForeignSaveCgifClass *class) foreign_class->suffs = vips__save_cgif_suffs; - save_class->saveable = VIPS_SAVEABLE_RGBA_ONLY; + save_class->saveable = + VIPS_FOREIGN_SAVEABLE_RGB | VIPS_FOREIGN_SAVEABLE_ALPHA; save_class->format_table = bandfmt_gif; VIPS_ARG_DOUBLE(class, "dither", 10, @@ -1126,20 +1132,7 @@ vips_foreign_save_cgif_buffer_init(VipsForeignSaveCgifBuffer *buffer) * vips_gifsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @dither: %gdouble, quantisation dithering level - * * @effort: %gint, quantisation CPU effort - * * @bitdepth: %gint, number of bits per pixel - * * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency - * * @reuse: %gboolean, reuse palette from input - * * @interlace: %gboolean, write an interlaced (progressive) GIF - * * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette - * reusage - * * @keep_duplicate_frames: %boolean, keep duplicate frames in the output - * instead of combining them + * @...: `NULL`-terminated list of optional named arguments * * Write to a file in GIF format. * @@ -1171,7 +1164,21 @@ vips_foreign_save_cgif_buffer_init(VipsForeignSaveCgifBuffer *buffer) * If @keep_duplicate_frames is TRUE, duplicate frames in the input will be * kept in the output instead of combining them. * - * See also: vips_image_new_from_file(). + * ::: tip "Optional arguments" + * * @dither: `gdouble`, quantisation dithering level + * * @effort: `gint`, quantisation CPU effort + * * @bitdepth: `gint`, number of bits per pixel + * * @interframe_maxerror: `gdouble`, maximum inter-frame error for + * transparency + * * @reuse: `gboolean`, reuse palette from input + * * @interlace: `gboolean`, write an interlaced (progressive) GIF + * * @interpalette_maxerror: `gdouble`, maximum inter-palette error for + * palette reusage + * * @keep_duplicate_frames: `gboolean`, keep duplicate frames in the output + * instead of combining them + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -1193,28 +1200,29 @@ vips_gifsave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @dither: %gdouble, quantisation dithering level - * * @effort: %gint, quantisation CPU effort - * * @bitdepth: %gint, number of bits per pixel - * * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency - * * @reuse: %gboolean, reuse palette from input - * * @interlace: %gboolean, write an interlaced (progressive) GIF - * * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette - * reusage - * * @keep_duplicate_frames: %boolean, keep duplicate frames in the output - * instead of combining them + * @...: `NULL`-terminated list of optional named arguments * - * As vips_gifsave(), but save to a memory buffer. + * As [method@Image.gifsave], but save to a memory buffer. * * The address of the buffer is returned in @buf, the length of the buffer in - * @len. You are responsible for freeing the buffer with g_free() when you + * @len. You are responsible for freeing the buffer with [func@GLib.free] when you * are done with it. * - * See also: vips_gifsave(), vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @dither: `gdouble`, quantisation dithering level + * * @effort: `gint`, quantisation CPU effort + * * @bitdepth: `gint`, number of bits per pixel + * * @interframe_maxerror: `gdouble`, maximum inter-frame error for + * transparency + * * @reuse: `gboolean`, reuse palette from input + * * @interlace: `gboolean`, write an interlaced (progressive) GIF + * * @interpalette_maxerror: `gdouble`, maximum inter-palette error for + * palette reusage + * * @keep_duplicate_frames: `gboolean`, keep duplicate frames in the output + * instead of combining them + * + * ::: seealso + * [method@Image.gifsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -1250,24 +1258,25 @@ vips_gifsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_gifsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @dither: %gdouble, quantisation dithering level - * * @effort: %gint, quantisation CPU effort - * * @bitdepth: %gint, number of bits per pixel - * * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency - * * @reuse: %gboolean, reuse palette from input - * * @interlace: %gboolean, write an interlaced (progressive) GIF - * * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette - * reusage - * * @keep_duplicate_frames: %boolean, keep duplicate frames in the output - * instead of combining them + * As [method@Image.gifsave], but save to a target. * - * As vips_gifsave(), but save to a target. + * ::: tip "Optional arguments" + * * @dither: `gdouble`, quantisation dithering level + * * @effort: `gint`, quantisation CPU effort + * * @bitdepth: `gint`, number of bits per pixel + * * @interframe_maxerror: `gdouble`, maximum inter-frame error for + * transparency + * * @reuse: `gboolean`, reuse palette from input + * * @interlace: `gboolean`, write an interlaced (progressive) GIF + * * @interpalette_maxerror: `gdouble`, maximum inter-palette error for + * palette reusage + * * @keep_duplicate_frames: `gboolean`, keep duplicate frames in the output + * instead of combining them * - * See also: vips_gifsave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.gifsave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/csvload.c b/libvips/foreign/csvload.c index bb344fb7f6..66acb7abb2 100644 --- a/libvips/foreign/csvload.c +++ b/libvips/foreign/csvload.c @@ -500,7 +500,7 @@ vips_foreign_load_csv_class_init(VipsForeignLoadCsvClass *class) _("Read this many lines from the file"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignLoadCsv, lines), - -1, 10000000, 0); + -1, 10000000, -1); VIPS_ARG_STRING(class, "whitespace", 22, _("Whitespace"), @@ -674,18 +674,12 @@ vips_foreign_load_csv_source_init(VipsForeignLoadCsvSource *source) * vips_csvload: * @filename: file to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Load a CSV (comma-separated values) file. * - * * @skip: skip this many lines at start of file - * * @lines: read this many lines from file - * * @whitespace: set of whitespace characters - * * @separator: set of separator characters - * * @fail_on: #VipsFailOn, types of read error to fail on - * - * Load a CSV (comma-separated values) file. The output image is always 1 - * band (monochrome), #VIPS_FORMAT_DOUBLE. Use vips_bandfold() to turn + * The output image is always 1 band (monochrome), + * [enum@Vips.BandFormat.DOUBLE]. Use [method@Image.bandfold] to turn * RGBRGBRGB mono images into colour images. * * Items in lines can be either floating point numbers in the C locale, or @@ -700,16 +694,24 @@ vips_foreign_load_csv_source_init(VipsForeignLoadCsvSource *source) * meaning read all lines to end of file. * * @whitespace sets the skippable whitespace characters. - * Default space. + * Default *space*. * Whitespace characters are always run together. * * @separator sets the characters that separate fields. - * Default ;,tab. Separators are never run together. + * Default ;,*tab*. Separators are never run together. * * Use @fail_on to set the type of error that will cause load to fail. By - * default, loaders are permissive, that is, #VIPS_FAIL_ON_NONE. + * default, loaders are permissive, that is, [enum@Vips.FailOn.NONE]. + * + * ::: tip "Optional arguments" + * * @skip: `gint`, skip this many lines at start of file + * * @lines: `gint`, read this many lines from file + * * @whitespace: `gchararray`, set of whitespace characters + * * @separator: `gchararray`, set of separator characters + * * @fail_on: [enum@FailOn], types of read error to fail on * - * See also: vips_image_new_from_file(), vips_bandfold(). + * ::: seealso + * [ctor@Image.new_from_file], [method@Image.bandfold]. * * Returns: 0 on success, -1 on error. */ @@ -730,19 +732,19 @@ vips_csvload(const char *filename, VipsImage **out, ...) * vips_csvload_source: * @source: source to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @skip: skip this many lines at start of file - * * @lines: read this many lines from file - * * @whitespace: set of whitespace characters - * * @separator: set of separator characters - * * @fail_on: #VipsFailOn, types of read error to fail on + * Exactly as [ctor@Image.csvload], but read from a source. * - * Exactly as vips_csvload(), but read from a source. + * ::: tip "Optional arguments" + * * @skip: `gint`, skip this many lines at start of file + * * @lines: `gint`, read this many lines from file + * * @whitespace: `gchararray`, set of whitespace characters + * * @separator: `gchararray`, set of separator characters + * * @fail_on: [enum@FailOn], types of read error to fail on * - * See also: vips_csvload(). + * ::: seealso + * [ctor@Image.csvload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/csvsave.c b/libvips/foreign/csvsave.c index 40bf031b56..ec62dac5d1 100644 --- a/libvips/foreign/csvsave.c +++ b/libvips/foreign/csvsave.c @@ -217,7 +217,7 @@ vips_foreign_save_csv_class_init(VipsForeignSaveCsvClass *class) foreign_class->suffs = vips_foreign_save_csv_suffs; - save_class->saveable = VIPS_SAVEABLE_MONO; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_MONO; VIPS_ARG_STRING(class, "separator", 13, _("Separator"), @@ -338,13 +338,10 @@ vips_foreign_save_csv_target_init(VipsForeignSaveCsvTarget *target) * vips_csvsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @separator: separator string + * @...: `NULL`-terminated list of optional named arguments * * Writes the pixels in @in to the @filename as CSV (comma-separated values). + * * The image is written * one line of text per scanline. Complex numbers are written as * "(real,imaginary)" and will need extra parsing I guess. Only the first band @@ -353,7 +350,11 @@ vips_foreign_save_csv_target_init(VipsForeignSaveCsvTarget *target) * @separator gives the string to use to separate numbers in the output. * The default is "\\t" (tab). * - * See also: vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @separator: separator string + * + * ::: seealso + * [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -374,15 +375,15 @@ vips_csvsave(VipsImage *in, const char *filename, ...) * vips_csvsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @separator: separator string + * As [method@Image.csvsave], but save to a target. * - * As vips_csvsave(), but save to a target. + * ::: tip "Optional arguments" + * * @separator: separator string * - * See also: vips_csvsave(). + * ::: seealso + * [method@Image.csvsave]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 922f10776a..33b0f61796 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -776,11 +776,11 @@ write_json(VipsForeignSaveDz *dz) " {\n" " \"scaleFactors\": [\n"); - for (i = 0; i < dz->level->n; i++) { + for (i = 0; i <= dz->level->n; i++) { vips_dbuf_writef(&dbuf, " %d", 1 << i); - if (i != dz->level->n - 1) + if (i != dz->level->n) vips_dbuf_writef(&dbuf, ","); vips_dbuf_writef(&dbuf, "\n"); } @@ -970,7 +970,8 @@ write_associated_images(VipsImage *image, { VipsForeignSaveDz *dz = (VipsForeignSaveDz *) a; - if (vips_isprefix("openslide.associated.", field)) { + if (vips_isprefix("openslide.associated.", field) && + vips_image_get_typeof(image, field) == VIPS_TYPE_IMAGE) { VipsImage *associated; const char *p; const char *q; @@ -1287,7 +1288,7 @@ region_tile_equal(VipsRegion *region, VipsRect *rect, for (x = 0; x < rect->width; x++) { for (b = 0; b < bytes; b++) - if (VIPS_ABS(p[b] - ink[b]) > threshold) + if (abs(p[b] - ink[b]) > threshold) return FALSE; p += bytes; @@ -1955,7 +1956,7 @@ vips_foreign_save_dz_build(VipsObject *object) * or the deprecated "no_strip" turns this off. */ if (!vips_object_argument_isset(object, "keep") && - !vips_object_argument_isset(object, "no_strip")) + !dz->no_strip) save->keep = VIPS_FOREIGN_KEEP_NONE; /* Google, zoomify and iiif default to zero overlap, ".jpg". @@ -2008,21 +2009,6 @@ vips_foreign_save_dz_build(VipsObject *object) return -1; } - /* Default to white background. vips_foreign_save_init() defaults to - * black. - */ - if (!vips_object_argument_isset(object, "background")) { - VipsArrayDouble *background; - - /* Using g_object_set() to set an input param in build will - * change the hash and confuse caching, but we don't cache - * savers, so it's fine. - */ - background = vips_array_double_newv(1, 255.0); - g_object_set(object, "background", background, NULL); - vips_area_unref(VIPS_AREA(background)); - } - /* DeepZoom stops at 1x1 pixels, others when the image fits within a * tile. */ @@ -2068,8 +2054,10 @@ vips_foreign_save_dz_build(VipsObject *object) coding[VIPS_CODING_NONE] = TRUE; if (vips__foreign_convert_saveable(save->ready, &z, - VIPS_SAVEABLE_RGB_CMYK, bandfmt_dzsave, coding, - save->background)) + VIPS_FOREIGN_SAVEABLE_MONO | + VIPS_FOREIGN_SAVEABLE_RGB | + VIPS_FOREIGN_SAVEABLE_CMYK, + bandfmt_dzsave, coding, save->background)) return -1; VIPS_UNREF(save->ready); @@ -2335,7 +2323,7 @@ vips_foreign_save_dz_class_init(VipsForeignSaveDzClass *class) foreign_class->suffs = dz_suffs; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; save_class->format_table = bandfmt_dz; save_class->coding[VIPS_CODING_LABQ] = TRUE; @@ -2498,6 +2486,12 @@ vips_foreign_save_dz_init(VipsForeignSaveDz *dz) dz->region_shrink = VIPS_REGION_SHRINK_MEAN; dz->skip_blanks = -1; dz->Q = 75; + + // we default background to 255 (not 0), see vips_foreign_save_init() + VipsForeignSave *save = (VipsForeignSave *) dz; + if (save->background) + vips_area_unref(VIPS_AREA(save->background)); + save->background = vips_array_double_newv(1, 255.0); } typedef struct _VipsForeignSaveDzTarget { @@ -2684,32 +2678,14 @@ vips_foreign_save_dz_buffer_init(VipsForeignSaveDzBuffer *buffer) * vips_dzsave: (method) * @in: image to save * @name: name to save to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @basename: %gchar base part of name - * * @layout: #VipsForeignDzLayout directory layout convention - * * @suffix: %gchar suffix for tiles - * * @overlap: %gint set tile overlap - * * @tile_size: %gint set tile size - * * @background: #VipsArrayDouble background colour - * * @depth: #VipsForeignDzDepth how deep to make the pyramid - * * @centre: %gboolean centre the tiles - * * @angle: #VipsAngle rotate the image by this much - * * @container: #VipsForeignDzContainer set container type - * * @compression: %gint zip deflate compression level - * * @region_shrink: #VipsRegionShrink how to shrink each 2x2 region - * * @skip_blanks: %gint skip tiles which are nearly equal to the background - * * @id: %gchar id for IIIF properties - * * @Q: %gint, quality factor + * @...: `NULL`-terminated list of optional named arguments * * Save an image as a set of tiles at various resolutions. By default dzsave * uses DeepZoom layout -- use @layout to pick other conventions. * - * vips_dzsave() creates a directory called @name to hold the tiles. If @name - * ends `.zip`, vips_dzsave() will create a zip file called @name to hold the - * tiles. You can use @container to force zip file output. + * [method@Image.dzsave] creates a directory called @name to hold the tiles. + * If @name ends `.zip`, [method@Image.dzsave] will create a zip file called + * @name to hold the tiles. You can use @container to force zip file output. * * Use @basename to set the name of the image we are creating. The * default value is set from @name. @@ -2736,7 +2712,7 @@ vips_foreign_save_dz_buffer_init(VipsForeignSaveDzBuffer *buffer) * You can rotate the image during write with the @angle argument. However, * this will only work for images which support random access, like openslide, * and not for things like JPEG. You'll need to rotate those images - * yourself with vips_rot(). Note that the `autorotate` option to the loader + * yourself with [method@Image.rot]. Note that the `autorotate` option to the loader * may do what you need. * * By default, all tiles are stripped since usually you do not want a copy of @@ -2758,9 +2734,28 @@ vips_foreign_save_dz_buffer_init(VipsForeignSaveDzBuffer *buffer) * In IIIF layout, you can set the base of the `id` property in `info.json` * with @id. The default is `https://example.com/iiif`. * - * Use @layout #VIPS_FOREIGN_DZ_LAYOUT_IIIF3 for IIIF v3 layout. + * Use @layout [enum@Vips.ForeignDzLayout.IIIF3] for IIIF v3 layout. * - * See also: vips_tiffsave(). + * ::: tip "Optional arguments" + * * @basename: `gchararray`, base part of name + * * @layout: [enum@ForeignDzLayout], directory layout convention + * * @suffix: `gchararray`, suffix for tiles + * * @overlap: `gint`, set tile overlap + * * @tile_size: `gint`, set tile size + * * @background: [struct@ArrayDouble], background colour + * * @depth: [enum@ForeignDzDepth], how deep to make the pyramid + * * @centre: `gboolean`, centre the tiles + * * @angle: [enum@Angle], rotate the image by this much + * * @container: [enum@ForeignDzContainer], set container type + * * @compression: `gint`, zip deflate compression level + * * @region_shrink: [enum@RegionShrink], how to shrink each 2x2 region + * * @skip_blanks: `gint`, skip tiles which are nearly equal to the + * background + * * @id: `gchararray`, id for IIIF properties + * * @Q: `gint`, quality factor + * + * ::: seealso + * [method@Image.tiffsave]. * * Returns: 0 on success, -1 on error. */ @@ -2782,36 +2777,37 @@ vips_dzsave(VipsImage *in, const char *name, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @basename: %gchar base part of name - * * @layout: #VipsForeignDzLayout directory layout convention - * * @suffix: %gchar suffix for tiles - * * @overlap: %gint set tile overlap - * * @tile_size: %gint set tile size - * * @background: #VipsArrayDouble background colour - * * @depth: #VipsForeignDzDepth how deep to make the pyramid - * * @centre: %gboolean centre the tiles - * * @angle: #VipsAngle rotate the image by this much - * * @container: #VipsForeignDzContainer set container type - * * @compression: %gint zip deflate compression level - * * @region_shrink: #VipsRegionShrink how to shrink each 2x2 region. - * * @skip_blanks: %gint skip tiles which are nearly equal to the background - * * @id: %gchar id for IIIF properties - * * @Q: %gint, quality factor - * - * As vips_dzsave(), but save to a memory buffer. + * As [method@Image.dzsave], but save to a memory buffer. * * Output is always in a zip container. Use @basename to set the name of the * directory that the zip will create when unzipped. * * The address of the buffer is returned in @buf, the length of the buffer in - * @len. You are responsible for freeing the buffer with g_free() when you + * @len. You are responsible for freeing the buffer with [func@GLib.free] when you * are done with it. * - * See also: vips_dzsave(), vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @basename: `gchararray`, base part of name + * * @layout: [enum@ForeignDzLayout], directory layout convention + * * @suffix: `gchararray`, suffix for tiles + * * @overlap: `gint`, set tile overlap + * * @tile_size: `gint`, set tile size + * * @background: [struct@ArrayDouble], background colour + * * @depth: [enum@ForeignDzDepth], how deep to make the pyramid + * * @centre: `gboolean`, centre the tiles + * * @angle: [enum@Angle], rotate the image by this much + * * @container: [enum@ForeignDzContainer], set container type + * * @compression: `gint`, zip deflate compression level + * * @region_shrink: [enum@RegionShrink], how to shrink each 2x2 region + * * @skip_blanks: `gint`, skip tiles which are nearly equal to the + * background + * * @id: `gchararray`, id for IIIF properties + * * @Q: `gint`, quality factor + * + * ::: seealso + * [method@Image.dzsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -2847,29 +2843,30 @@ vips_dzsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_dzsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @basename: %gchar base part of name - * * @layout: #VipsForeignDzLayout directory layout convention - * * @suffix: %gchar suffix for tiles - * * @overlap: %gint set tile overlap - * * @tile_size: %gint set tile size - * * @background: #VipsArrayDouble background colour - * * @depth: #VipsForeignDzDepth how deep to make the pyramid - * * @centre: %gboolean centre the tiles - * * @angle: #VipsAngle rotate the image by this much - * * @container: #VipsForeignDzContainer set container type - * * @compression: %gint zip deflate compression level - * * @region_shrink: #VipsRegionShrink how to shrink each 2x2 region. - * * @skip_blanks: %gint skip tiles which are nearly equal to the background - * * @id: %gchar id for IIIF properties - * * @Q: %gint, quality factor + * As [method@Image.dzsave], but save to a target. * - * As vips_dzsave(), but save to a target. + * ::: tip "Optional arguments" + * * @basename: `gchararray`, base part of name + * * @layout: [enum@ForeignDzLayout], directory layout convention + * * @suffix: `gchararray`, suffix for tiles + * * @overlap: `gint`, set tile overlap + * * @tile_size: `gint`, set tile size + * * @background: [struct@ArrayDouble], background colour + * * @depth: [enum@ForeignDzDepth], how deep to make the pyramid + * * @centre: `gboolean`, centre the tiles + * * @angle: [enum@Angle], rotate the image by this much + * * @container: [enum@ForeignDzContainer], set container type + * * @compression: `gint`, zip deflate compression level + * * @region_shrink: [enum@RegionShrink], how to shrink each 2x2 region + * * @skip_blanks: `gint`, skip tiles which are nearly equal to the + * background + * * @id: `gchararray`, id for IIIF properties + * * @Q: `gint`, quality factor * - * See also: vips_dzsave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.dzsave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/exif.c b/libvips/foreign/exif.c index 3868583134..c5454ed2d0 100644 --- a/libvips/foreign/exif.c +++ b/libvips/foreign/exif.c @@ -86,7 +86,7 @@ entry_to_s(ExifEntry *entry) * for formats like float. Ban crazy size values. */ int size = VIPS_MIN(entry->size, 10000); - int max_size = size * 5; + int max_size = size * 3 + 32; char *text = VIPS_MALLOC(NULL, max_size + 1); // this renders floats as eg. "12.2345", enums as "Inch", etc. @@ -491,7 +491,7 @@ vips_image_resolution_from_exif(VipsImage *image, ExifData *ed) break; default: - g_warning("%s", _("unknown EXIF resolution unit")); + g_warning("unknown EXIF resolution unit"); return -1; } @@ -748,7 +748,7 @@ vips_exif_set_double(ExifData *ed, else old_value = (double) rv.numerator / rv.denominator; - if (VIPS_FABS(old_value - value) > 0.0001) { + if (fabs(old_value - value) > 0.0001) { vips_exif_double_to_rational(value, &rv); VIPS_DEBUG_MSG("vips_exif_set_double: %u / %u\n", @@ -767,7 +767,7 @@ vips_exif_set_double(ExifData *ed, else old_value = (double) srv.numerator / srv.denominator; - if (VIPS_FABS(old_value - value) > 0.0001) { + if (fabs(old_value - value) > 0.0001) { vips_exif_double_to_srational(value, &srv); VIPS_DEBUG_MSG("vips_exif_set_double: %d / %d\n", @@ -1066,7 +1066,7 @@ vips_exif_resolution_from_image(ExifData *ed, VipsImage *image) break; default: - g_warning("%s", _("unknown EXIF resolution unit")); + g_warning("unknown EXIF resolution unit"); return 0; } diff --git a/libvips/foreign/fits.c b/libvips/foreign/fits.c index 03008c3c30..fb1a444c73 100644 --- a/libvips/foreign/fits.c +++ b/libvips/foreign/fits.c @@ -109,7 +109,7 @@ typedef struct { int naxis; long long int naxes[MAX_DIMENSIONS]; - GMutex *lock; /* Lock fits_*() calls with this */ + GMutex lock; /* Lock fits_*() calls with this */ /* One line of pels ready for scatter/gather. */ @@ -139,7 +139,8 @@ static void vips_fits_close(VipsFits *fits) { VIPS_FREE(fits->filename); - VIPS_FREEF(vips_g_mutex_free, fits->lock); + if (fits->line) + g_mutex_clear(&fits->lock); VIPS_FREEF(vips_slist_free_all, fits->dedupe); if (fits->fptr) { @@ -174,7 +175,7 @@ vips_fits_new_read(const char *filename, VipsImage *out) fits->filename = vips_strdup(NULL, filename); fits->image = out; fits->fptr = NULL; - fits->lock = NULL; + g_mutex_init(&fits->lock); fits->line = NULL; g_signal_connect(out, "close", G_CALLBACK(vips_fits_close_cb), fits); @@ -186,8 +187,6 @@ vips_fits_new_read(const char *filename, VipsImage *out) return NULL; } - fits->lock = vips_g_mutex_new(); - return fits; } @@ -465,7 +464,7 @@ vips_fits_generate(VipsRegion *out, "generating left = %d, top = %d, width = %d, height = %d\n", r->left, r->top, r->width, r->height); - vips__worker_lock(fits->lock); + vips__worker_lock(&fits->lock); for (int w = 0; w < out->im->Bands; w++) { for (int y = r->top; y < VIPS_RECT_BOTTOM(r); y++) { @@ -492,7 +491,7 @@ vips_fits_generate(VipsRegion *out, */ if (vips_fits_read_subset(fits, fpixel, lpixel, inc, fits->line)) { - g_mutex_unlock(fits->lock); + g_mutex_unlock(&fits->lock); return -1; } @@ -502,7 +501,7 @@ vips_fits_generate(VipsRegion *out, } } - g_mutex_unlock(fits->lock); + g_mutex_unlock(&fits->lock); return 0; } @@ -561,7 +560,7 @@ vips_fits_new_write(VipsImage *in, const char *filename) fits->filename = vips_strdup(VIPS_OBJECT(in), filename); fits->image = in; fits->fptr = NULL; - fits->lock = NULL; + g_mutex_init(&fits->lock); fits->line = NULL; g_signal_connect(in, "close", G_CALLBACK(vips_fits_close_cb), fits); @@ -575,7 +574,7 @@ vips_fits_new_write(VipsImage *in, const char *filename) VIPS_IMAGE_SIZEOF_ELEMENT(in) * in->Xsize, VipsPel))) return NULL; - /* fits_create_file() will fail if there's a file of thet name, unless + /* fits_create_file() will fail if there's a file of that name, unless * we put a "!" in front of the filename. This breaks conventions with * the rest of vips, so just unlink explicitly. */ @@ -588,8 +587,6 @@ vips_fits_new_write(VipsImage *in, const char *filename) return NULL; } - fits->lock = vips_g_mutex_new(); - return fits; } diff --git a/libvips/foreign/fitsload.c b/libvips/foreign/fitsload.c index 28472df327..db7d39c12e 100644 --- a/libvips/foreign/fitsload.c +++ b/libvips/foreign/fitsload.c @@ -353,7 +353,7 @@ vips_foreign_load_fits_source_init(VipsForeignLoadFitsSource *fits) * vips_fitsload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Read a FITS image file into a VIPS image. * @@ -365,7 +365,8 @@ vips_foreign_load_fits_source_init(VipsForeignLoadFitsSource *fits) * * FITS metadata is attached with the "fits-" prefix. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -386,9 +387,9 @@ vips_fitsload(const char *filename, VipsImage **out, ...) * vips_fitsload_source: * @source: source to load from * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_fitsload(), but read from a source. + * Exactly as [ctor@Image.fitsload], but read from a source. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/fitssave.c b/libvips/foreign/fitssave.c index 6017bfcfd7..1a039485de 100644 --- a/libvips/foreign/fitssave.c +++ b/libvips/foreign/fitssave.c @@ -136,7 +136,7 @@ vips_foreign_save_fits_class_init(VipsForeignSaveFitsClass *class) foreign_class->suffs = vips__fits_suffs; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; save_class->format_table = bandfmt_fits; VIPS_ARG_STRING(class, "filename", 1, @@ -158,11 +158,12 @@ vips_foreign_save_fits_init(VipsForeignSaveFits *fits) * vips_fitssave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image to a file in FITS format. * - * See also: vips_image_write_to_file(). + * ::: seealso + * [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 7e72610a1d..7c4a07adfd 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -74,94 +74,97 @@ #include "pforeign.h" /** - * SECTION: foreign - * @short_description: load and save images in a variety of formats - * @stability: Stable - * @see_also: image - * @include: vips/vips.h - * @title: VipsForeign + * VipsForeign: * - * This set of operations load and save images in a variety of formats. + * An abstract base class to load and save images in a variety of formats. * - * # Load and save + * ## Load and save * * You can load and save from and to files, memory areas, and the libvips IO - * abstractions, #VipsSource and #VipsTarget. + * abstractions, [class@Source] and [class@Target]. * - * Use vips_foreign_find_load(), vips_foreign_find_load_buffer() and - * vips_foreign_find_load_source() to find a loader for an object. Use - * vips_foreign_find_save(), vips_foreign_find_save_buffer() and - * vips_foreign_find_save_target() to find a saver for a format. You can then - * run these operations using vips_call() and friends to perform the load or + * Use [func@Foreign.find_load] [func@Foreign.find_load_buffer] and + * [func@Foreign.find_load_source] to find a loader for an object. Use + * [func@Foreign.find_save], [func@Foreign.find_save_buffer] and + * [func@Foreign.find_save_target] to find a saver for a format. You can then + * run these operations using [func@call] and friends to perform the load or * save. * - * vips_image_write_to_file() and vips_image_new_from_file() and friends use + * [method@Image.write_to_file] and [ctor@Image.new_from_file] and friends use * these functions to automate file load and save. * * You can also invoke the operations directly, for example: * - * |[ + * ```c * vips_tiffsave(my_image, "frank.anything", * "compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG, * NULL); - * ]| + * ``` * - * # Image metadata + * ## Image metadata * * All loaders attach all image metadata as libvips properties on load. * - * You can change metadata with vips_image_set_int() and friends. + * You can change metadata with [method@Image.set_int] and friends. * - * During save, you can use @keep to specify which metadata to retain, - * defaults to all, see #VipsForeignKeep. Setting @profile will + * During save, you can use `keep` to specify which metadata to retain, + * defaults to all, see [flags@ForeignKeep]. Setting `profile` will * automatically keep the ICC profile. * - * # Many page images + * ## Many page images * * By default, libvips will only load the first page of many page or animated - * images. Use @page and @n to set the start page and the number of pages to - * load. Set @n to -1 to load all pages. + * images. Use `page` and `n` to set the start page and the number of pages to + * load. Set `n` to -1 to load all pages. * * Many page images are loaded as a tall, thin strip of pages. * - * Use vips_image_get_page_height() and vips_image_get_n_pages() to find the - * page height and number of pages of a loaded image. + * Use [method@Image.get_page_height] and [method@Image.get_n_pages] to find + * the page height and number of pages of a loaded image. * - * Use @page_height to set the page height for image save. + * Use `page_height` to set the page height for image save. * - * # Alpha save + * ## Alpha save * * Not all image formats support alpha. If you try to save an image with an * alpha channel to a format that does not support it, the alpha will be - * automatically flattened out. Use @background (default 0) to set the colour + * automatically flattened out. Use `background` (default 0) to set the colour * that alpha should be flattened against. * - * # Adding new formats + * ## Adding new formats * * To add support for a new file format to vips, simply define a new subclass - * of #VipsForeignLoad or #VipsForeignSave. + * of [class@ForeignLoad] or [class@ForeignSave]. * - * If you define a new operation which is a subclass of #VipsForeign, support - * for it automatically appears in all VIPS user-interfaces. It will also be - * transparently supported by vips_image_new_from_file() and friends. + * If you define a new operation which is a subclass of [class@Foreign], + * support for it automatically appears in all libvips user-interfaces. It + * will also be transparently supported by [ctor@Image.new_from_file] and + * friends. + */ + +/** + * VipsForeignLoad: + * + * An abstract base class to load images in a variety of formats. * * ## Writing a new loader * - * Add a new loader to VIPS by subclassing #VipsForeignLoad. Subclasses need to - * implement at least @header(). + * Add a new loader to libvips by subclassing [class@ForeignLoad]. Subclasses + * need to implement at least [vfunc@ForeignLoad.header]. * - * @header() must set at least the header fields of @out. @load(), if defined, - * must load the pixels to @real. + * [vfunc@ForeignLoad.header] must set at least the header fields of `out`. + * [vfunc@ForeignLoad.load], if defined, must load the pixels to `real`. * * The suffix list is used to select a format to save a file in, and to pick a - * loader if you don't define is_a(). + * loader if you don't define [func@Foreign.is_a]. * - * You should also define @nickname and @description in #VipsObject. + * You should also define [property@VipsObject:nickname] and + * [property@VipsObject:description] in [class@Object]. * * As a complete example, here's code for a PNG loader, minus the actual * calls to libpng. * - * |[ + * ```c * typedef struct _VipsForeignLoadPng { * VipsForeignLoad parent_object; * @@ -252,17 +255,23 @@ * vips_foreign_load_png_init(VipsForeignLoadPng *png) * { * } - * ]| + * ``` + */ + +/** + * VipsForeignSave: + * + * An abstract base class to save images in a variety of formats. * * ## Writing a new saver * - * Call your saver in the class' @build() method after chaining up. The - * prepared image should be ready for you to save in @ready. + * Call your saver in the class' [vfunc@Object.build] method after chaining up. + * The prepared image should be ready for you to save in `ready`. * * As a complete example, here's the code for the CSV saver, minus the calls * to the actual save routines. * - * |[ + * ```c * typedef struct _VipsForeignSaveCsv { * VipsForeignSave parent_object; * @@ -308,7 +317,7 @@ * * foreign_class->suffs = vips__foreign_csv_suffs; * - * save_class->saveable = VIPS_SAVEABLE_MONO; + * save_class->saveable = VIPS_FOREIGN_SAVEABLE_MONO; * // no need to define ->format_table, we don't want the input * // cast for us * @@ -332,7 +341,7 @@ * { * csv->separator = g_strdup("\t"); * } - * ]| + * ``` */ /* Use this to link images to the load operation that made them. @@ -348,19 +357,19 @@ static GQuark vips__foreign_load_operation = 0; * * Some hints about the image loader. * - * #VIPS_FOREIGN_PARTIAL means that the image can be read directly from the + * [flags@Vips.ForeignFlags.PARTIAL] means that the image can be read directly from the * file without needing to be unpacked to a temporary image first. * - * #VIPS_FOREIGN_SEQUENTIAL means that the loader supports lazy reading, but + * [flags@Vips.ForeignFlags.SEQUENTIAL] means that the loader supports lazy reading, but * only top-to-bottom (sequential) access. Formats like PNG can read sets of * scanlines, for example, but only in order. * * If neither PARTIAL or SEQUENTIAL is set, the loader only supports whole * image read. Setting both PARTIAL and SEQUENTIAL is an error. * - * #VIPS_FOREIGN_BIGENDIAN means that image pixels are most-significant byte + * [flags@Vips.ForeignFlags.BIGENDIAN] means that image pixels are most-significant byte * first. Depending on the native byte order of the host machine, you may - * need to swap bytes. See vips_copy(). + * need to swap bytes. See [method@Image.copy]. */ G_DEFINE_ABSTRACT_TYPE(VipsForeign, vips_foreign, VIPS_TYPE_OPERATION); @@ -448,18 +457,19 @@ file_compare(VipsForeignClass *a, VipsForeignClass *b, void *user_data) /** * vips_foreign_map: * @base: base class to search below (eg. "VipsForeignLoad") - * @fn: (scope call): function to apply to each #VipsForeignClass + * @fn: (scope call): function to apply to each [class@Foreign]Class * @a: user data * @b: user data * - * Apply a function to every #VipsForeignClass that VIPS knows about. Foreigns + * Apply a function to every [class@Foreign]Class that VIPS knows about. Foreigns * are presented to the function in priority order. * - * Like all VIPS map functions, if @fn returns %NULL, iteration continues. If - * it returns non-%NULL, iteration terminates and that value is returned. The - * map function returns %NULL if all calls return %NULL. + * Like all VIPS map functions, if @fn returns `NULL`, iteration continues. If + * it returns non-`NULL`, iteration terminates and that value is returned. The + * map function returns `NULL` if all calls return `NULL`. * - * See also: vips_slist_map(). + * ::: seealso + * [func@slist_map2]. * * Returns: (transfer none): the result of iteration */ @@ -587,9 +597,10 @@ vips_foreign_find_load_sub(VipsForeignLoadClass *load_class, * Searches for an operation you could use to load @filename. Any trailing * options on @filename are stripped and ignored. * - * See also: vips_foreign_find_load_buffer(), vips_image_new_from_file(). + * ::: seealso + * [func@Foreign.find_load_buffer], [ctor@Image.new_from_file]. * - * Returns: the name of an operation on success, %NULL on error + * Returns: the name of an operation on success, `NULL` on error */ const char * vips_foreign_find_load(const char *name) @@ -690,9 +701,10 @@ vips_foreign_find_load_buffer_sub(VipsForeignLoadClass *load_class, * * vips -l | grep load_buffer * - * See also: vips_image_new_from_buffer(). + * ::: seealso + * [ctor@Image.new_from_buffer]. * - * Returns: (transfer none): the name of an operation on success, %NULL on + * Returns: (transfer none): the name of an operation on success, `NULL` on * error. */ const char * @@ -751,9 +763,10 @@ vips_foreign_find_load_source_sub(void *item, void *a, void *b) * * vips -l | grep load_source * - * See also: vips_image_new_from_source(). + * ::: seealso + * [ctor@Image.new_from_source]. * - * Returns: (transfer none): the name of an operation on success, %NULL on + * Returns: (transfer none): the name of an operation on success, `NULL` on * error. */ const char * @@ -770,11 +783,6 @@ vips_foreign_find_load_source(VipsSource *source) return NULL; } - /* All source loaders should be NOCACHE. - */ - g_assert(VIPS_OPERATION_CLASS(load_class)->flags & - VIPS_OPERATION_NOCACHE); - return G_OBJECT_CLASS_NAME(load_class); } @@ -783,10 +791,10 @@ vips_foreign_find_load_source(VipsSource *source) * @loader: name of loader to use for test * @filename: file to test * - * Return %TRUE if @filename can be loaded by @loader. @loader is something + * Return `TRUE` if @filename can be loaded by @loader. @loader is something * like "tiffload" or "VipsForeignLoadTiff". * - * Returns: %TRUE if @filename can be loaded by @loader. + * Returns: `TRUE` if @filename can be loaded by @loader. */ gboolean vips_foreign_is_a(const char *loader, const char *filename) @@ -810,10 +818,10 @@ vips_foreign_is_a(const char *loader, const char *filename) * @data: (array length=size) (element-type guint8): pointer to the buffer to test * @size: (type gsize): size of the buffer to test * - * Return %TRUE if @data can be loaded by @loader. @loader is something + * Return `TRUE` if @data can be loaded by @loader. @loader is something * like "tiffload_buffer" or "VipsForeignLoadTiffBuffer". * - * Returns: %TRUE if @data can be loaded by @loader. + * Returns: `TRUE` if @data can be loaded by @loader. */ gboolean vips_foreign_is_a_buffer(const char *loader, const void *data, size_t size) @@ -836,10 +844,10 @@ vips_foreign_is_a_buffer(const char *loader, const void *data, size_t size) * @loader: name of loader to use for test * @source: source to test * - * Return %TRUE if @source can be loaded by @loader. @loader is something + * Return `TRUE` if @source can be loaded by @loader. @loader is something * like "tiffload_source" or "VipsForeignLoadTiffSource". * - * Returns: %TRUE if @data can be loaded by @source. + * Returns: `TRUE` if @data can be loaded by @source. */ gboolean vips_foreign_is_a_source(const char *loader, VipsSource *source) @@ -946,7 +954,7 @@ vips_foreign_load_temp(VipsForeignLoad *load) } /* We open via disc if the uncompressed image will be larger than - * vips_get_disc_threshold() + * vips_get_disc_threshold(). */ if (image_size > disc_threshold) { #ifdef DEBUG @@ -1002,7 +1010,7 @@ vips_foreign_load_start(VipsImage *out, void *a, void *b) return NULL; #ifdef DEBUG - printf("vips_foreign_load_start: triggering ->load()\n"); + printf("vips_foreign_load_start: triggering ->load\n"); #endif /*DEBUG*/ /* Read the image in. This may involve a long computation and @@ -1093,9 +1101,8 @@ vips_foreign_load_build(VipsObject *object) if ((flags & VIPS_FOREIGN_PARTIAL) && (flags & VIPS_FOREIGN_SEQUENTIAL)) { - g_warning("%s", - _("VIPS_FOREIGN_PARTIAL and VIPS_FOREIGN_SEQUENTIAL " - "both set -- using SEQUENTIAL")); + g_warning("VIPS_FOREIGN_PARTIAL and VIPS_FOREIGN_SEQUENTIAL " + "both set -- using SEQUENTIAL"); flags ^= VIPS_FOREIGN_PARTIAL; } @@ -1121,9 +1128,8 @@ vips_foreign_load_build(VipsObject *object) return -1; if (load->sequential) - g_warning("%s", - _("ignoring deprecated \"sequential\" mode -- " - "please use \"access\" instead")); + g_warning("ignoring deprecated \"sequential\" mode -- " + "please use \"access\" instead"); g_object_set(object, "out", vips_image_new(), NULL); @@ -1131,7 +1137,7 @@ vips_foreign_load_build(VipsObject *object) VIPS_META_LOADER, class->nickname); #ifdef DEBUG - printf("vips_foreign_load_build: triggering ->header()\n"); + printf("vips_foreign_load_build: triggering ->header\n"); #endif /*DEBUG*/ /* Read the header into @out. @@ -1339,8 +1345,12 @@ vips_foreign_save_summary_class(VipsObjectClass *object_class, VipsBuf *buf) VIPS_OBJECT_CLASS(vips_foreign_save_parent_class) ->summary_class(object_class, buf); - vips_buf_appendf(buf, ", %s", - vips_enum_nick(VIPS_TYPE_SAVEABLE, class->saveable)); + GValue value = { 0 }; + g_value_init(&value, VIPS_TYPE_FOREIGN_SAVEABLE); + g_value_set_flags(&value, class->saveable); + vips_buf_appends(buf, ", "); + vips_buf_appendgv(buf, &value); + g_value_unset(&value); } static VipsObject * @@ -1363,51 +1373,45 @@ vips_foreign_save_new_from_string(const char *string) return VIPS_OBJECT(save); } -/* Convert an image for saving. +/* Apply a set of saveable flags. + * + * - if the saver supports mono and we have a mono-looking image, we are done + * - if the saver supports CMYK and we have a CMYK-looking image, we are done + * - if this is a CMYK-looking image, import to XYZ + * - go to rgb + * - if the saver supports rgb, we are done + * - if the saver supports cmyk, go to cmyk + * - if the saver supports mono, go to mono */ -int -vips__foreign_convert_saveable(VipsImage *in, VipsImage **ready, - VipsSaveable saveable, VipsBandFormat *format, VipsCoding *coding, - VipsArrayDouble *background) +static int +vips_foreign_apply_saveable(VipsImage *in, VipsImage **ready, + VipsForeignSaveable saveable) { + // is this a 16-bit source image + gboolean sixteenbit = in->BandFmt == VIPS_FORMAT_USHORT; + + VipsImage *out; + VipsInterpretation interpretation; + /* in holds a reference to the output of our chain as we build it. */ g_object_ref(in); - /* For coded images, can this class save the coding we are in now? - * Nothing to do. + /* ANY? we are done. */ - if (in->Coding != VIPS_CODING_NONE && - coding[in->Coding]) { + if (saveable & VIPS_FOREIGN_SAVEABLE_ANY) { *ready = in; return 0; } - /* For uncoded images, if this saver supports ANY bands and this - * format we have nothing to do. - */ - if (in->Coding == VIPS_CODING_NONE && - saveable == VIPS_SAVEABLE_ANY && - format[in->BandFmt] == in->BandFmt) { - *ready = in; - return 0; - } - - /* Otherwise ... we need to decode and then (possibly) recode at the - * end. - */ - /* If this is an VIPS_CODING_LABQ, we can go straight to RGB. */ if (in->Coding == VIPS_CODING_LABQ) { - VipsImage *out; - if (vips_LabQ2sRGB(in, &out, NULL)) { g_object_unref(in); return -1; } g_object_unref(in); - in = out; } @@ -1415,43 +1419,34 @@ vips__foreign_convert_saveable(VipsImage *in, VipsImage **ready, * scRGB or XYZ. */ if (in->Coding == VIPS_CODING_RAD) { - VipsImage *out; - if (vips_rad2float(in, &out, NULL)) { g_object_unref(in); return -1; } g_object_unref(in); - in = out; } - /* If the saver supports RAD, we need to go to scRGB or XYZ. + /* If this is a mono-ish looking image and our saver supports mono, we + * are done. We are not too strict about what a mono image is! We need to + * work for things like "extract_band 1" on an RGB Image. */ - if (coding[VIPS_CODING_RAD]) { - if (in->Type != VIPS_INTERPRETATION_scRGB && - in->Type != VIPS_INTERPRETATION_XYZ) { - VipsImage *out; - - if (vips_colourspace(in, &out, VIPS_INTERPRETATION_scRGB, NULL)) { - g_object_unref(in); - return -1; - } - g_object_unref(in); - - in = out; - } + if ((saveable & VIPS_FOREIGN_SAVEABLE_MONO) && + in->Bands < 3) { + *ready = in; + return 0; } - /* If this image is CMYK and the saver is RGB-only, use lcms to try to - * import to XYZ. + /* CMYK image? Use the sanity-checked interpretation value. */ - if (in->Type == VIPS_INTERPRETATION_CMYK && - in->Bands >= 4 && - (saveable == VIPS_SAVEABLE_RGB || - saveable == VIPS_SAVEABLE_RGBA || - saveable == VIPS_SAVEABLE_RGBA_ONLY)) { - VipsImage *out; + if (vips_image_guess_interpretation(in) == VIPS_INTERPRETATION_CMYK && + in->Bands >= 4) { + /* If our saver supports CMYK we are done, otherwise import to XYZ. + */ + if (saveable & VIPS_FOREIGN_SAVEABLE_CMYK) { + *ready = in; + return 0; + } if (vips_icc_import(in, &out, "pcs", VIPS_PCS_XYZ, @@ -1462,251 +1457,228 @@ vips__foreign_convert_saveable(VipsImage *in, VipsImage **ready, return -1; } g_object_unref(in); - in = out; } - /* If this is something other than CMYK or RAD, and it's not already - * an RGB image, eg. maybe a LAB image, we need to transform - * to RGB. + /* If the saver supports RGB, go to RGB, or RGB16 if this is a ushort + * source. */ - if (!coding[VIPS_CODING_RAD] && - in->Bands >= 3 && - in->Type != VIPS_INTERPRETATION_CMYK && - in->Type != VIPS_INTERPRETATION_sRGB && - in->Type != VIPS_INTERPRETATION_RGB16 && - vips_colourspace_issupported(in) && - (saveable == VIPS_SAVEABLE_RGB || - saveable == VIPS_SAVEABLE_RGBA || - saveable == VIPS_SAVEABLE_RGBA_ONLY || - saveable == VIPS_SAVEABLE_RGB_CMYK)) { - VipsImage *out; - VipsInterpretation interpretation; - - /* Do we make RGB or RGB16? We don't want to squash a 16-bit - * RGB down to 8 bits if the saver supports 16. - */ - if (vips_band_format_is8bit(format[in->BandFmt])) - interpretation = VIPS_INTERPRETATION_sRGB; - else - interpretation = VIPS_INTERPRETATION_RGB16; + if (saveable & VIPS_FOREIGN_SAVEABLE_RGB) { + interpretation = sixteenbit ? + VIPS_INTERPRETATION_RGB16 : VIPS_INTERPRETATION_sRGB; if (vips_colourspace(in, &out, interpretation, NULL)) { g_object_unref(in); return -1; } g_object_unref(in); - in = out; + + *ready = in; + return 0; } - /* VIPS_SAVEABLE_RGBA_ONLY does not support mono types ... convert - * to sRGB. + /* If the saver supports CMYK, go to RGB, or RGB16 if this is a ushort + * source. */ - if (!coding[VIPS_CODING_RAD] && - in->Bands < 3 && - saveable == VIPS_SAVEABLE_RGBA_ONLY) { - VipsImage *out; - VipsInterpretation interpretation; - - /* Do we make RGB or RGB16? We don't want to squash a 16-bit - * RGB down to 8 bits if the saver supports 16. - */ - if (vips_band_format_is8bit(format[in->BandFmt])) - interpretation = VIPS_INTERPRETATION_sRGB; - else - interpretation = VIPS_INTERPRETATION_RGB16; - - if (vips_colourspace(in, &out, interpretation, NULL)) { + if (saveable & VIPS_FOREIGN_SAVEABLE_CMYK) { + if (vips_icc_export(in, &out, + "output-profile", "cmyk", + "depth", sixteenbit ? 16 : 8, + NULL)) { g_object_unref(in); return -1; } g_object_unref(in); - in = out; + + *ready = in; + return 0; } - /* Get the bands right. We must do this after all colourspace - * transforms, since they can change the number of bands. + /* If the saver supports mono, go to B_W, or GREY16 if this is a ushort + * source. */ - if (in->Coding == VIPS_CODING_NONE) { - /* Do we need to flatten out an alpha channel? There needs to - * be an alpha there now, and this writer needs to not support - * alpha. - */ - if ((in->Bands == 2 || - (in->Bands == 4 && - in->Type != VIPS_INTERPRETATION_CMYK)) && - (saveable == VIPS_SAVEABLE_MONO || - saveable == VIPS_SAVEABLE_RGB || - saveable == VIPS_SAVEABLE_RGB_CMYK)) { - VipsImage *out; - - if (vips_flatten(in, &out, - "background", background, - NULL)) { - g_object_unref(in); - return -1; - } - g_object_unref(in); + if (saveable & VIPS_FOREIGN_SAVEABLE_MONO) { + interpretation = sixteenbit ? + VIPS_INTERPRETATION_GREY16 : VIPS_INTERPRETATION_B_W; - in = out; + if (vips_colourspace(in, &out, interpretation, NULL)) { + g_object_unref(in); + return -1; } + g_object_unref(in); + in = out; - /* Other alpha removal strategies ... just drop the extra - * bands. - */ - - else if (in->Bands > 3 && - (saveable == VIPS_SAVEABLE_RGB || - (saveable == VIPS_SAVEABLE_RGB_CMYK && - in->Type != VIPS_INTERPRETATION_CMYK))) { - VipsImage *out; - - /* Don't let 4 bands though unless the image really is - * a CMYK. - * - * Consider a RGBA png being saved as JPG. We can - * write CMYK jpg, but we mustn't do that for RGBA - * images. - */ - if (vips_extract_band(in, &out, 0, - "n", 3, - NULL)) { - g_object_unref(in); - return -1; - } - g_object_unref(in); + *ready = in; + return 0; + } - in = out; - } - else if (in->Bands > 4 && - ((saveable == VIPS_SAVEABLE_RGB_CMYK && - in->Type == VIPS_INTERPRETATION_CMYK) || - saveable == VIPS_SAVEABLE_RGBA || - saveable == VIPS_SAVEABLE_RGBA_ONLY)) { - VipsImage *out; + vips_error("VipsForeignSave", _("saver does not support any output type")); + return -1; +} - if (vips_extract_band(in, &out, 0, - "n", 4, - NULL)) { - g_object_unref(in); - return -1; - } - g_object_unref(in); +/* Do all the colourspace conversions to get an image ready for saving. Don't + * finalize alpha or numeric format. + */ +int +vips__foreign_convert_saveable(VipsImage *in, VipsImage **ready, + VipsForeignSaveable saveable, VipsBandFormat *format, VipsCoding *coding, + VipsArrayDouble *background) +{ + VipsBandFormat original_format = in->BandFmt; - in = out; - } - else if (in->Bands > 1 && - saveable == VIPS_SAVEABLE_MONO) { - VipsImage *out; + VipsImage *out; - if (vips_extract_band(in, &out, 0, NULL)) { - g_object_unref(in); - return -1; - } - g_object_unref(in); + /* in holds a reference to the output of our chain as we build it. + */ + g_object_ref(in); - in = out; - } + /* For coded images, can this class save the coding we are in now? + * Nothing to do. + */ + if (in->Coding != VIPS_CODING_NONE && + coding[in->Coding]) { + *ready = in; + return 0; + } - /* Else we have VIPS_SAVEABLE_ANY and we don't chop bands down. - */ + /* For uncoded images, if this saver supports ANY and this + * format, we have nothing to do. + */ + if (in->Coding == VIPS_CODING_NONE && + (saveable & VIPS_FOREIGN_SAVEABLE_ANY) && + format[in->BandFmt] == in->BandFmt) { + *ready = in; + return 0; } - /* Handle the ushort interpretations. - * - * RGB16 and GREY16 use 0-65535 for black-white. If we have an image - * tagged like this, and it has more than 8 bits (we leave crazy uchar - * images tagged as RGB16 alone), we'll need to get it ready for the - * saver. + /* Otherwise ... we need to decode and then (possibly) recode at the + * end. */ - if ((in->Type == VIPS_INTERPRETATION_RGB16 || - in->Type == VIPS_INTERPRETATION_GREY16) && - !vips_band_format_is8bit(in->BandFmt)) { - /* If the saver supports ushort, cast to ushort. It may be - * float at the moment, for example. - * - * If the saver does not support ushort, automatically shift - * it down. This is the behaviour we want for saving an RGB16 - * image as JPG, for example. - */ - if (format[VIPS_FORMAT_USHORT] == VIPS_FORMAT_USHORT) { - VipsImage *out; - if (vips_cast(in, &out, VIPS_FORMAT_USHORT, NULL)) { - g_object_unref(in); - return -1; - } + /* Apply saveable conversions to get mono/rgb/cmyk. + */ + if (vips_foreign_apply_saveable(in, &out, saveable)) { + g_object_unref(in); + return -1; + } + g_object_unref(in); + in = out; + + /* Flatten alpha, if the saver does not support it. + */ + if (in->Coding == VIPS_CODING_NONE && + vips_image_hasalpha(in) && + !(saveable & VIPS_FOREIGN_SAVEABLE_ALPHA)) { + if (vips_flatten(in, &out, + "background", background, + NULL)) { g_object_unref(in); + return -1; + } + g_object_unref(in); + in = out; + } - in = out; + /* There might be more than one alpha ... drop any remaining excess + * bands. + */ + if (in->Coding == VIPS_CODING_NONE) { + int max_bands; + + // use a sanity-checked interpretation + switch (vips_image_guess_interpretation(in)) { + case VIPS_INTERPRETATION_B_W: + case VIPS_INTERPRETATION_GREY16: + max_bands = 1; + break; + + case VIPS_INTERPRETATION_RGB: + case VIPS_INTERPRETATION_CMC: + case VIPS_INTERPRETATION_LCH: + case VIPS_INTERPRETATION_LABS: + case VIPS_INTERPRETATION_sRGB: + case VIPS_INTERPRETATION_YXY: + case VIPS_INTERPRETATION_XYZ: + case VIPS_INTERPRETATION_LAB: + case VIPS_INTERPRETATION_RGB16: + case VIPS_INTERPRETATION_scRGB: + case VIPS_INTERPRETATION_HSV: + max_bands = 3; + break; + + case VIPS_INTERPRETATION_CMYK: + max_bands = 4; + break; + + default: + max_bands = 0; + break; } - else { - VipsImage *out; - if (vips_rshift_const1(in, &out, 8, NULL)) { - g_object_unref(in); - return -1; - } - g_object_unref(in); + if (saveable & VIPS_FOREIGN_SAVEABLE_ALPHA) + max_bands += 1; - in = out; + if (saveable & VIPS_FOREIGN_SAVEABLE_ANY) + max_bands = in->Bands; - /* That could have produced an int image ... make sure - * we are now uchar. - */ - if (vips_cast(in, &out, VIPS_FORMAT_UCHAR, NULL)) { + if (max_bands > 0 && + in->Bands > max_bands) { + if (vips_extract_band(in, &out, 0, + "n", max_bands, + NULL)) { g_object_unref(in); return -1; } g_object_unref(in); - in = out; } } - /* Cast to the output format. + /* Convert to the format the saver likes, based on the original format. */ - { - VipsImage *out; - - if (vips_cast(in, &out, format[in->BandFmt], NULL)) { + if (in->Coding == VIPS_CODING_NONE && + format) { + if (vips_cast(in, &out, format[original_format], + "shift", TRUE, + NULL)) { g_object_unref(in); return -1; } g_object_unref(in); - in = out; } /* Does this class want a coded image? Search the coding table for the * first one. */ - if (coding[VIPS_CODING_NONE]) { - /* Already NONE, nothing to do. + if (coding[in->Coding]) { + /* Already there, nothing to do. */ } else if (coding[VIPS_CODING_LABQ]) { - VipsImage *out; - if (vips_Lab2LabQ(in, &out, NULL)) { g_object_unref(in); return -1; } g_object_unref(in); - in = out; } else if (coding[VIPS_CODING_RAD]) { - VipsImage *out; - if (vips_float2rad(in, &out, NULL)) { g_object_unref(in); return -1; } g_object_unref(in); - + in = out; + } + else if (coding[VIPS_CODING_NONE]) { + if (vips_image_decode(in, &out)) { + g_object_unref(in); + return -1; + } + g_object_unref(in); in = out; } @@ -1956,8 +1928,10 @@ vips_foreign_find_save_sub(VipsForeignSaveClass *save_class, /* All savers needs suffs defined since we use the suff to pick the * saver. */ - if (!class->suffs) + if (!class->suffs) { g_warning("no suffix defined for %s", object_class->nickname); + return NULL; + } /* Skip non-file savers. */ @@ -1982,9 +1956,10 @@ vips_foreign_find_save_sub(VipsForeignSaveClass *save_class, * Searches for an operation you could use to write to @filename. * Any trailing options on @filename are stripped and ignored. * - * See also: vips_foreign_find_save_buffer(), vips_image_write_to_file(). + * ::: seealso + * [func@Foreign.find_save_buffer], [method@Image.write_to_file]. * - * Returns: (nullable): the name of an operation on success, %NULL on error + * Returns: (nullable): the name of an operation on success, `NULL` on error */ const char * vips_foreign_find_save(const char *name) @@ -2045,17 +2020,17 @@ vips_foreign_get_suffixes_add_cb(VipsForeignSaveClass *save_class, /** * vips_foreign_get_suffixes: * - * Get a %NULL-terminated array listing all the supported suffixes. + * Get a `NULL`-terminated array listing all the supported suffixes. * * This is not the same as all the supported file types, since libvips * detects image format for load by testing the first few bytes. * - * Use vips_foreign_find_load() to detect type for a specific file. + * Use [func@Foreign.find_load] to detect type for a specific file. * - * Free the return result with g_strfreev(). + * Free the return result with [func@GLib.strfreev]. * * Returns: (transfer full) (array): all supported file extensions, as a - * %NULL-terminated array. + * `NULL`-terminated array. */ gchar ** vips_foreign_get_suffixes(void) @@ -2137,9 +2112,10 @@ vips_foreign_find_save_target_sub(VipsForeignSaveClass *save_class, * Searches for an operation you could use to write to a target in @suffix * format. * - * See also: vips_image_write_to_buffer(). + * ::: seealso + * [method@Image.write_to_buffer]. * - * Returns: (nullable): the name of an operation on success, %NULL on error + * Returns: (nullable): the name of an operation on success, `NULL` on error */ const char * vips_foreign_find_save_target(const char *name) @@ -2195,9 +2171,10 @@ vips_foreign_find_save_buffer_sub(VipsForeignSaveClass *save_class, * Searches for an operation you could use to write to a buffer in @suffix * format. * - * See also: vips_image_write_to_buffer(). + * ::: seealso + * [method@Image.write_to_buffer]. * - * Returns: (nullable): the name of an operation on success, %NULL on error + * Returns: (nullable): the name of an operation on success, `NULL` on error */ const char * vips_foreign_find_save_buffer(const char *name) @@ -2228,14 +2205,7 @@ vips_foreign_find_save_buffer(const char *name) * vips_heifload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, page (top-level image number) to read - * * @n: %gint, load this many pages - * * @thumbnail: %gboolean, fetch thumbnail instead of image - * * @unlimited: %gboolean, remove all denial of service limits + * @...: `NULL`-terminated list of optional named arguments * * Read a HEIF image file into a VIPS image. * @@ -2244,21 +2214,28 @@ vips_foreign_find_save_buffer(const char *name) * * Use @n to select the number of pages to render. The default is 1. Pages are * rendered in a vertical column. Set to -1 to mean "until the end of the - * document". Use vips_grid() to reorganise pages. + * document". Use [method@Image.grid] to reorganise pages. * * HEIF images have a primary image. The metadata item `heif-primary` gives * the page number of the primary. * - * If @thumbnail is %TRUE, then fetch a stored thumbnail rather than the + * If @thumbnail is `TRUE`, then fetch a stored thumbnail rather than the * image. * * By default, input image dimensions are limited to 16384x16384. - * If @unlimited is %TRUE, this increases to the maximum of 65535x65535. + * If @unlimited is `TRUE`, this increases to the maximum of 65535x65535. * * The bitdepth of the heic image is recorded in the metadata item * `heif-bitdepth`. * - * See also: vips_image_new_from_file(). + * ::: tip "Optional arguments" + * * @page: `gint`, page (top-level image number) to read + * * @n: `gint`, load this many pages + * * @thumbnail: `gboolean`, fetch thumbnail instead of image + * * @unlimited: `gboolean`, remove all denial of service limits + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -2280,22 +2257,22 @@ vips_heifload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, page (top-level image number) to read - * * @n: %gint, load this many pages - * * @thumbnail: %gboolean, fetch thumbnail instead of image - * * @unlimited: %gboolean, remove all denial of service limits + * @...: `NULL`-terminated list of optional named arguments * * Read a HEIF image file into a VIPS image. - * Exactly as vips_heifload(), but read from a memory buffer. + * Exactly as [ctor@Image.heifload], but read from a memory buffer. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. * - * See also: vips_heifload(). + * ::: tip "Optional arguments" + * * @page: `gint`, page (top-level image number) to read + * * @n: `gint`, load this many pages + * * @thumbnail: `gboolean`, fetch thumbnail instead of image + * * @unlimited: `gboolean`, remove all denial of service limits + * + * ::: seealso + * [ctor@Image.heifload]. * * Returns: 0 on success, -1 on error. */ @@ -2323,18 +2300,18 @@ vips_heifload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_heifload_source: * @source: source to load from * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @page: %gint, page (top-level image number) to read - * * @n: %gint, load this many pages - * * @thumbnail: %gboolean, fetch thumbnail instead of image - * * @unlimited: %gboolean, remove all denial of service limits + * Exactly as [ctor@Image.heifload], but read from a source. * - * Exactly as vips_heifload(), but read from a source. + * ::: tip "Optional arguments" + * * @page: `gint`, page (top-level image number) to read + * * @n: `gint`, load this many pages + * * @thumbnail: `gboolean`, fetch thumbnail instead of image + * * @unlimited: `gboolean`, remove all denial of service limits * - * See also: vips_heifload(). + * ::: seealso + * [ctor@Image.heifload]. * * Returns: 0 on success, -1 on error. */ @@ -2355,24 +2332,14 @@ vips_heifload_source(VipsSource *source, VipsImage **out, ...) * vips_heifsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @bitdepth: %gint, set write bit depth to 8, 10, or 12 bits - * * @lossless: %gboolean, enable lossless encoding - * * @compression: #VipsForeignHeifCompression, write with this compression - * * @effort: %gint, encoding effort - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode - * * @encoder: #VipsForeignHeifEncoder, select encoder to use + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image to a file in HEIF format. * * Use @Q to set the compression factor. Default 50, which seems to be roughly * what the iphone uses. Q 30 gives about the same quality as JPEG Q 75. * - * Set @lossless %TRUE to switch to lossless compression. + * Set @lossless `TRUE` to switch to lossless compression. * * Use @compression to set the compression format e.g. HEVC, AVC, AV1 to use. It defaults to AV1 * if the target filename ends with ".avif", otherwise HEVC. @@ -2389,7 +2356,18 @@ vips_heifload_source(VipsSource *source, VipsImage **out, ...) * * Use @encoder to set the encode library to use, e.g. aom, SVT-AV1, rav1e etc. * - * See also: vips_image_write_to_file(), vips_heifload(). + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @bitdepth: `gint`, set write bit depth to 8, 10, or 12 bits + * * @lossless: `gboolean`, enable lossless encoding + * * @compression: [enum@ForeignHeifCompression], write with this + * compression + * * @effort: `gint`, encoding effort + * * @subsample_mode: [class@Foreign]Subsample, chroma subsampling mode + * * @encoder: [class@Foreign]HeifEncoder, select encoder to use + * + * ::: seealso + * [method@Image.write_to_file], [ctor@Image.heifload]. * * Returns: 0 on success, -1 on error. */ @@ -2411,25 +2389,26 @@ vips_heifsave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @bitdepth: %gint, set write bit depth to 8, 10, or 12 bits - * * @lossless: %gboolean, enable lossless encoding - * * @compression: #VipsForeignHeifCompression, write with this compression - * * @effort: %gint, encoding effort - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode - * * @encoder: #VipsForeignHeifEncoder, select encoder to use + * @...: `NULL`-terminated list of optional named arguments * - * As vips_heifsave(), but save to a memory buffer. + * As [method@Image.heifsave], but save to a memory buffer. * * The address of the buffer is returned in @obuf, the length of the buffer in - * @olen. You are responsible for freeing the buffer with g_free() when you - * are done with it. - * - * See also: vips_heifsave(), vips_image_write_to_file(). + * @olen. You are responsible for freeing the buffer with [func@GLib.free] + * when you are done with it. + * + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @bitdepth: `gint`, set write bit depth to 8, 10, or 12 bits + * * @lossless: `gboolean`, enable lossless encoding + * * @compression: [enum@ForeignHeifCompression], write with this + * compression + * * @effort: `gint`, encoding effort + * * @subsample_mode: [class@Foreign]Subsample, chroma subsampling mode + * * @encoder: [class@Foreign]HeifEncoder, select encoder to use + * + * ::: seealso + * [method@Image.heifsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -2465,21 +2444,22 @@ vips_heifsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_heifsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @Q: %gint, quality factor - * * @bitdepth: %gint, set write bit depth to 8, 10, or 12 bits - * * @lossless: %gboolean, enable lossless encoding - * * @compression: #VipsForeignHeifCompression, write with this compression - * * @effort: %gint, encoding effort - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode - * * @encoder: #VipsForeignHeifEncoder, select encoder to use + * As [method@Image.heifsave], but save to a target. * - * As vips_heifsave(), but save to a target. + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @bitdepth: `gint`, set write bit depth to 8, 10, or 12 bits + * * @lossless: `gboolean`, enable lossless encoding + * * @compression: [enum@ForeignHeifCompression], write with this + * compression + * * @effort: `gint`, encoding effort + * * @subsample_mode: [class@Foreign]Subsample, chroma subsampling mode + * * @encoder: [class@Foreign]HeifEncoder, select encoder to use * - * See also: vips_heifsave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.heifsave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ @@ -2500,14 +2480,15 @@ vips_heifsave_target(VipsImage *in, VipsTarget *target, ...) * vips_jxlload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Read a JPEG-XL image. * * The JPEG-XL loader and saver are experimental features and may change * in future libvips versions. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -2529,9 +2510,9 @@ vips_jxlload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_jxlload(), but read from a buffer. + * Exactly as [ctor@Image.jxlload], but read from a buffer. * * Returns: 0 on success, -1 on error. */ @@ -2559,9 +2540,9 @@ vips_jxlload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_jxlload_source: * @source: source to load from * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_jxlload(), but read from a source. + * Exactly as [ctor@Image.jxlload], but read from a source. * * Returns: 0 on success, -1 on error. */ @@ -2582,15 +2563,7 @@ vips_jxlload_source(VipsSource *source, VipsImage **out, ...) * vips_jxlsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @tier: %gint, decode speed tier - * * @distance: %gdouble, maximum encoding error - * * @effort: %gint, encoding effort - * * @lossless: %gboolean, enables lossless compression - * * @Q: %gint, quality setting + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image to a file in JPEG-XL format. * @@ -2609,6 +2582,13 @@ vips_jxlload_source(VipsSource *source, VipsImage **out, ...) * * Set @lossless to enable lossless compression. * + * ::: tip "Optional arguments" + * * @tier: `gint`, decode speed tier + * * @distance: `gdouble`, maximum encoding error + * * @effort: `gint`, encoding effort + * * @lossless: `gboolean`, enables lossless compression + * * @Q: `gint`, quality setting + * * Returns: 0 on success, -1 on error. */ int @@ -2629,19 +2609,19 @@ vips_jxlsave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @tier: %gint, decode speed tier - * * @distance: %gdouble, maximum encoding error - * * @effort: %gint, encoding effort - * * @lossless: %gboolean, enables lossless compression - * * @Q: %gint, quality setting + * As [method@Image.jxlsave], but save to a memory buffer. * - * As vips_jxlsave(), but save to a memory buffer. + * ::: tip "Optional arguments" + * * @tier: `gint`, decode speed tier + * * @distance: `gdouble`, maximum encoding error + * * @effort: `gint`, encoding effort + * * @lossless: `gboolean`, enables lossless compression + * * @Q: `gint`, quality setting * - * See also: vips_jxlsave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.jxlsave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ @@ -2677,19 +2657,19 @@ vips_jxlsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_jxlsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * As [method@Image.jxlsave], but save to a target. * - * * @tier: %gint, decode speed tier - * * @distance: %gdouble, maximum encoding error - * * @effort: %gint, encoding effort - * * @lossless: %gboolean, enables lossless compression - * * @Q: %gint, quality setting + * ::: tip "Optional arguments" + * * @tier: `gint`, decode speed tier + * * @distance: `gdouble`, maximum encoding error + * * @effort: `gint`, encoding effort + * * @lossless: `gboolean`, enables lossless compression + * * @Q: `gint`, quality setting * - * As vips_jxlsave(), but save to a target. - * - * See also: vips_jxlsave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.jxlsave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ @@ -2710,29 +2690,20 @@ vips_jxlsave_target(VipsImage *in, VipsTarget *target, ...) * vips_pdfload: * @filename: file to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, load this page, numbered from zero - * * @n: %gint, load this many pages - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * * @background: #VipsArrayDouble background colour - * * @password: %gchararray PDF password + * @...: `NULL`-terminated list of optional named arguments * * Render a PDF file into a VIPS image. * - * The output image is always RGBA --- CMYK PDFs will be - * converted. If you need CMYK bitmaps, you should use vips_magickload() + * The output image is always RGBA -- CMYK PDFs will be + * converted. If you need CMYK bitmaps, you should use [ctor@Image.magickload] * instead. * * Use @page to select a page to render, numbering from zero. * * Use @n to select the number of pages to render. The default is 1. Pages are * rendered in a vertical column, with each individual page aligned to the - * left. Set to -1 to mean "until the end of the document". Use vips_grid() - * to change page layout. + * left. Set to -1 to mean "until the end of the document". Use + * [method@Image.grid] to change page layout. * * Use @dpi to set the rendering resolution. The default is 72. Additionally, * you can scale by setting @scale. If you set both, they combine. @@ -2748,7 +2719,15 @@ vips_jxlsave_target(VipsImage *in, VipsTarget *target, ...) * This function only reads the image header and does not render any pixel * data. Rendering occurs when pixels are accessed. * - * See also: vips_image_new_from_file(), vips_magickload(). + * ::: tip "Optional arguments" + * * @page: `gint`, load this page, numbered from zero + * * @n: `gint`, load this many pages + * * @dpi: `gdouble`, render at this DPI + * * @scale: `gdouble`, scale render by this factor + * * @background: [struct@ArrayDouble], background colour + * + * ::: seealso + * [ctor@Image.new_from_file], [ctor@Image.magickload]. * * Returns: 0 on success, -1 on error. */ @@ -2770,23 +2749,23 @@ vips_pdfload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, load this page, numbered from zero - * * @n: %gint, load this many pages - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * * @background: #VipsArrayDouble background colour + * @...: `NULL`-terminated list of optional named arguments * * Read a PDF-formatted memory buffer into a VIPS image. Exactly as - * vips_pdfload(), but read from memory. + * [ctor@Image.pdfload], but read from memory. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. * - * See also: vips_pdfload(). + * ::: tip "Optional arguments" + * * @page: `gint`, load this page, numbered from zero + * * @n: `gint`, load this many pages + * * @dpi: `gdouble`, render at this DPI + * * @scale: `gdouble`, scale render by this factor + * * @background: [struct@ArrayDouble], background colour + * + * ::: seealso + * [ctor@Image.pdfload]. * * Returns: 0 on success, -1 on error. */ @@ -2814,19 +2793,19 @@ vips_pdfload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_pdfload_source: * @source: source to load from * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @page: %gint, load this page, numbered from zero - * * @n: %gint, load this many pages - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * * @background: #VipsArrayDouble background colour + * Exactly as [ctor@Image.pdfload], but read from a source. * - * Exactly as vips_pdfload(), but read from a source. + * ::: tip "Optional arguments" + * * @page: `gint`, load this page, numbered from zero + * * @n: `gint`, load this many pages + * * @dpi: `gdouble`, render at this DPI + * * @scale: `gdouble`, scale render by this factor + * * @background: [struct@ArrayDouble], background colour * - * See also: vips_pdfload() + * ::: seealso + * [ctor@Image.pdfload] * * Returns: 0 on success, -1 on error. */ @@ -2847,15 +2826,7 @@ vips_pdfload_source(VipsSource *source, VipsImage **out, ...) * vips_openslideload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @level: %gint, load this level - * * @associated: %gchararray, load this associated image - * * @attach_associated: %gboolean, attach all associated images as metadata - * * @autocrop: %gboolean, crop to image bounds - * * @rgb: %gboolean, output RGB (not RGBA) pixels + * @...: `NULL`-terminated list of optional named arguments * * Read a virtual slide supported by the OpenSlide library into a VIPS image. * OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle, @@ -2863,8 +2834,8 @@ vips_pdfload_source(VipsSource *source, VipsImage **out, ...) * * To facilitate zooming, virtual slide formats include multiple scaled-down * versions of the high-resolution image. These are typically called - * "levels". By default, vips_openslideload() reads the highest-resolution - * level (level 0). Set @level to the level number you want. + * "levels". By default, [ctor@Image.openslideload] reads the + * highest-resolution level (level 0). Set @level to the level number you want. * * In addition to the slide image itself, virtual slide formats sometimes * include additional images, such as a scan of the slide's barcode. @@ -2874,14 +2845,22 @@ vips_pdfload_source(VipsSource *source, VipsImage **out, ...) * "slide-associated-images" metadata item. * * If you set @attach_associated, then all associated images are attached as - * metadata items. Use vips_image_get_image() on @out to retrieve them. Images + * metadata items. Use [method@Image.get_image] on @out to retrieve them. Images * are attached as "openslide-associated-XXXXX", where XXXXX is the name of the * associated image. * * By default, the output of this operator is RGBA. Set @rgb to enable RGB * output. * - * See also: vips_image_new_from_file(). + * ::: tip "Optional arguments" + * * @level: `gint`, load this level + * * @associated: `gchararray`, load this associated image + * * @attach_associated: `gboolean`, attach all associated images as metadata + * * @autocrop: `gboolean`, crop to image bounds + * * @rgb: `gboolean`, output RGB (not RGBA) pixels + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -2902,17 +2881,16 @@ vips_openslideload(const char *filename, VipsImage **out, ...) * vips_openslideload_source: * @source: source to load from * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @level: %gint, load this level - * * @associated: %gchararray, load this associated image - * * @attach_associated: %gboolean, attach all associated images as metadata - * * @autocrop: %gboolean, crop to image bounds - * * @rgb: %gboolean, output RGB (not RGBA) pixels + * Exactly as [ctor@Image.openslideload], but read from a source. * - * Exactly as vips_openslideload(), but read from a source. + * ::: tip "Optional arguments" + * * @level: `gint`, load this level + * * @associated: `gchararray`, load this associated image + * * @attach_associated: `gboolean`, attach all associated images as metadata + * * @autocrop: `gboolean`, crop to image bounds + * * @rgb: `gboolean`, output RGB (not RGBA) pixels * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/heifload.c b/libvips/foreign/heifload.c index d50fa045da..84bc0cccac 100644 --- a/libvips/foreign/heifload.c +++ b/libvips/foreign/heifload.c @@ -351,9 +351,17 @@ vips_foreign_load_heif_build(VipsObject *object) heif->ctx = heif_context_alloc(); #ifdef HAVE_HEIF_SET_MAX_IMAGE_SIZE_LIMIT + /* heifsave is limited to a maximum image size of 16384x16384, + * so align the heifload defaults accordingly. + */ heif_context_set_maximum_image_size_limit(heif->ctx, heif->unlimited ? USHRT_MAX : 0x4000); #endif /* HAVE_HEIF_SET_MAX_IMAGE_SIZE_LIMIT */ +#ifdef HAVE_HEIF_GET_DISABLED_SECURITY_LIMITS + if (heif->unlimited) + heif_context_set_security_limits(heif->ctx, + heif_get_disabled_security_limits()); +#endif /* HAVE_HEIF_GET_DISABLED_SECURITY_LIMITS */ error = heif_context_read_from_reader(heif->ctx, heif->reader, heif, NULL); if (error.code) { @@ -810,10 +818,10 @@ vips_foreign_load_heif_header(VipsForeignLoad *load) */ if (!vips_object_argument_isset(VIPS_OBJECT(load), "page") && !vips_object_argument_isset(VIPS_OBJECT(load), "n")) - heif->page = heif->primary_page; + heif->page = heif->primary_page; // FIXME: Invalidates operation cache if (heif->n == -1) - heif->n = heif->n_top - heif->page; + heif->n = heif->n_top - heif->page; // FIXME: Invalidates operation cache if (heif->page < 0 || heif->n <= 0 || heif->page + heif->n > heif->n_top) { @@ -993,7 +1001,7 @@ vips_foreign_load_heif_generate(VipsRegion *out_region, } memcpy(VIPS_REGION_ADDR(out_region, 0, r->top), - heif->data + heif->stride * line, + heif->data + (size_t) heif->stride * line, VIPS_IMAGE_SIZEOF_LINE(out_region->im)); /* We may need to swap bytes and shift to fill 16 bits. @@ -1107,12 +1115,14 @@ vips_foreign_load_heif_class_init(VipsForeignLoadHeifClass *class) G_STRUCT_OFFSET(VipsForeignLoadHeif, autorotate), FALSE); +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION VIPS_ARG_BOOL(class, "unlimited", 22, _("Unlimited"), _("Remove all denial of service limits"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignLoadHeif, unlimited), FALSE); +#endif } static gint64 @@ -1175,7 +1185,7 @@ vips_foreign_load_heif_wait_for_file_size(gint64 target_size, void *userdata) result = vips_source_seek(heif->source, target_size, SEEK_SET); vips_source_seek(heif->source, old_position, SEEK_SET); - if (result < 0) + if (result < 0 || old_position < 0) /* Unable to seek to this point, so it's beyond EOF. */ status = heif_reader_grow_status_size_beyond_eof; diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index e1040650ac..4c20aad203 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -289,8 +289,7 @@ vips_foreign_save_heif_write_page(VipsForeignSaveHeif *heif, int page) #endif /*HAVE_HEIF_COLOR_PROFILE*/ options = heif_encoding_options_alloc(); - if (vips_image_hasalpha(save->ready)) - options->save_alpha_channel = 1; + options->save_alpha_channel = save->ready->Bands > 3; #ifdef HAVE_HEIF_ENCODING_OPTIONS_OUTPUT_NCLX_PROFILE /* Matrix coefficients have to be identity (CICP x/y/0) in lossless @@ -311,6 +310,14 @@ vips_foreign_save_heif_write_page(VipsForeignSaveHeif *heif, int page) } #endif /*HAVE_HEIF_ENCODING_OPTIONS_OUTPUT_NCLX_PROFILE*/ +#ifdef HAVE_HEIF_ENCODING_OPTIONS_IMAGE_ORIENTATION + /* EXIF orientation is informational in the HEIF specification. + * Orientation is defined using irot and imir transformations. + */ + options->image_orientation = vips_image_get_orientation(save->ready); + vips_autorot_remove_angle(save->ready); +#endif + #ifdef DEBUG { GTimer *timer = g_timer_new(); @@ -322,8 +329,7 @@ vips_foreign_save_heif_write_page(VipsForeignSaveHeif *heif, int page) heif->img, heif->encoder, options, &heif->handle); #ifdef DEBUG - printf("... libheif took %.2g seconds\n", - g_timer_elapsed(timer, NULL)); + printf("... libheif took %.2g seconds\n", g_timer_elapsed(timer, NULL)); g_timer_destroy(timer); } #endif /*DEBUG*/ @@ -397,9 +403,7 @@ vips_foreign_save_heif_pack(VipsForeignSaveHeif *heif, */ int vips_bitdepth = save->ready->Type == VIPS_INTERPRETATION_RGB16 || - save->ready->Type == VIPS_INTERPRETATION_GREY16 - ? 16 - : 8; + save->ready->Type == VIPS_INTERPRETATION_GREY16 ? 16 : 8; int shift = vips_bitdepth - heif->bitdepth; for (i = 0; i < ne; i++) { @@ -416,9 +420,7 @@ vips_foreign_save_heif_pack(VipsForeignSaveHeif *heif, */ int vips_bitdepth = save->ready->Type == VIPS_INTERPRETATION_RGB16 || - save->ready->Type == VIPS_INTERPRETATION_GREY16 - ? 16 - : 8; + save->ready->Type == VIPS_INTERPRETATION_GREY16 ? 16 : 8; int shift = vips_bitdepth - heif->bitdepth; for (i = 0; i < ne; i++) { @@ -463,7 +465,7 @@ vips_foreign_save_heif_write_block(VipsRegion *region, VipsRect *area, int page = (area->top + y) / heif->page_height; int line = (area->top + y) % heif->page_height; VipsPel *p = VIPS_REGION_ADDR(region, 0, area->top + y); - VipsPel *q = heif->data + line * heif->stride; + VipsPel *q = heif->data + (size_t) heif->stride * line; if (vips_foreign_save_heif_pack(heif, q, p, VIPS_REGION_N_ELEMENTS(region))) @@ -514,9 +516,9 @@ vips_foreign_save_heif_build(VipsObject *object) char *chroma; const struct heif_encoder_descriptor *out_encoder; const struct heif_encoder_parameter *const *param; + gboolean has_alpha; - if (VIPS_OBJECT_CLASS(vips_foreign_save_heif_parent_class)-> - build(object)) + if (VIPS_OBJECT_CLASS(vips_foreign_save_heif_parent_class)-> build(object)) return -1; /* If the old, deprecated "speed" param is being used and the new @@ -526,11 +528,9 @@ vips_foreign_save_heif_build(VipsObject *object) !vips_object_argument_isset(object, "effort")) heif->effort = 9 - heif->speed; - /* Disable chroma subsampling by default when the "lossless" param - * is being used. + /* The "lossless" param implies no chroma subsampling. */ - if (vips_object_argument_isset(object, "lossless") && - !vips_object_argument_isset(object, "subsample_mode")) + if (heif->lossless) heif->subsample_mode = VIPS_FOREIGN_SUBSAMPLE_OFF; /* Default 12 bit save for 16-bit images. @@ -659,6 +659,17 @@ vips_foreign_save_heif_build(VipsObject *object) return -1; } + /* Try to prevent the AVIF encoder from using intra block copy, + * helps ensure encoding time is more predictable. + */ + error = heif_encoder_set_parameter_boolean(heif->encoder, + "enable-intrabc", FALSE); + if (error.code && + error.subcode != heif_suberror_Unsupported_parameter) { + vips__heif_error(&error); + return -1; + } + /* TODO .. support extra per-encoder params with * heif_encoder_list_parameters(). */ @@ -666,6 +677,7 @@ vips_foreign_save_heif_build(VipsObject *object) heif->page_width = save->ready->Xsize; heif->page_height = vips_image_get_page_height(save->ready); heif->n_pages = save->ready->Ysize / heif->page_height; + has_alpha = save->ready->Bands > 3; if (heif->page_width > 16384 || heif->page_height > 16384) { vips_error("heifsave", _("image too large")); @@ -679,12 +691,11 @@ vips_foreign_save_heif_build(VipsObject *object) printf("vips_foreign_save_heif_build:\n"); printf("\twidth = %d\n", heif->page_width); printf("\theight = %d\n", heif->page_height); - printf("\talpha = %d\n", vips_image_hasalpha(save->ready)); + printf("\talpha = %d\n", has_alpha); #endif /*DEBUG*/ error = heif_image_create(heif->page_width, heif->page_height, heif_colorspace_RGB, - vips__heif_chroma(heif->bitdepth, - vips_image_hasalpha(save->ready)), + vips__heif_chroma(heif->bitdepth, has_alpha), &heif->img); if (error.code) { vips__heif_error(&error); @@ -708,8 +719,7 @@ vips_foreign_save_heif_build(VipsObject *object) /* Write data. */ - if (vips_sink_disc(save->ready, - vips_foreign_save_heif_write_block, heif)) + if (vips_sink_disc(save->ready, vips_foreign_save_heif_write_block, heif)) return -1; /* This has to come right at the end :-( so there's no support for @@ -757,7 +767,8 @@ vips_foreign_save_heif_class_init(VipsForeignSaveHeifClass *class) object_class->description = _("save image in HEIF format"); object_class->build = vips_foreign_save_heif_build; - save_class->saveable = VIPS_SAVEABLE_RGBA_ONLY; + save_class->saveable = + VIPS_FOREIGN_SAVEABLE_RGB | VIPS_FOREIGN_SAVEABLE_ALPHA; save_class->format_table = vips_heif_bandfmt; VIPS_ARG_INT(class, "Q", 10, @@ -914,8 +925,7 @@ static int vips_foreign_save_heif_buffer_build(VipsObject *object) { VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) object; - VipsForeignSaveHeifBuffer *buffer = - (VipsForeignSaveHeifBuffer *) object; + VipsForeignSaveHeifBuffer *buffer = (VipsForeignSaveHeifBuffer *) object; VipsBlob *blob; @@ -977,8 +987,7 @@ static int vips_foreign_save_heif_target_build(VipsObject *object) { VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) object; - VipsForeignSaveHeifTarget *target = - (VipsForeignSaveHeifTarget *) object; + VipsForeignSaveHeifTarget *target = (VipsForeignSaveHeifTarget *) object; if (target->target) { heif->target = target->target; diff --git a/libvips/foreign/jp2kload.c b/libvips/foreign/jp2kload.c index 05e74427b8..846ab52f78 100644 --- a/libvips/foreign/jp2kload.c +++ b/libvips/foreign/jp2kload.c @@ -80,6 +80,10 @@ typedef struct _VipsForeignLoadJp2k { int page; int shrink; + /* Load images a frame at a time rather than a tile at a time. + */ + gboolean oneshot; + /* Decompress state. */ opj_stream_t *stream; /* Source as an opj stream */ @@ -279,7 +283,12 @@ vips_foreign_load_jp2k_is_a_source(VipsSource *source) static VipsForeignFlags vips_foreign_load_jp2k_get_flags(VipsForeignLoad *load) { - return VIPS_FOREIGN_PARTIAL; + VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) load; + + if (jp2k->oneshot) + return VIPS_FOREIGN_SEQUENTIAL; + else + return VIPS_FOREIGN_PARTIAL; } /* The openjpeg info and warning callbacks are incredibly chatty. @@ -1147,9 +1156,9 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load) VipsImage **t = (VipsImage **) vips_object_local_array(VIPS_OBJECT(load), 3); - int vips_tile_width; - int vips_tile_height; - int vips_tiles_across; + int tile_width; + int tile_height; + int tiles_across; #ifdef DEBUG printf("vips_foreign_load_jp2k_load:\n"); @@ -1161,13 +1170,11 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load) /* Untiled jp2k images need a different read API. */ - if (jp2k->info->tw == 1 && - jp2k->info->th == 1) { - vips_tile_width = 512; - vips_tile_height = 512; - vips_tiles_across = - VIPS_ROUND_UP(t[0]->Xsize, vips_tile_width) / - vips_tile_width; + if (jp2k->oneshot || + (jp2k->info->tw == 1 && jp2k->info->th == 1)) { + tile_width = jp2k->width; + tile_height = jp2k->height; + tiles_across = 1; if (vips_image_generate(t[0], NULL, vips_foreign_load_jp2k_generate_untiled, NULL, @@ -1175,9 +1182,9 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load) return -1; } else { - vips_tile_width = jp2k->info->tdx; - vips_tile_height = jp2k->info->tdy; - vips_tiles_across = jp2k->info->tw; + tile_width = jp2k->info->tdx; + tile_height = jp2k->info->tdy; + tiles_across = jp2k->info->tw; if (vips_image_generate(t[0], NULL, vips_foreign_load_jp2k_generate_tiled, NULL, @@ -1189,9 +1196,9 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load) * rows, plus 50%. */ if (vips_tilecache(t[0], &t[1], - "tile_width", vips_tile_width, - "tile_height", vips_tile_height, - "max_tiles", 3 * vips_tiles_across, + "tile_width", tile_width, + "tile_height", tile_height, + "max_tiles", 3 * tiles_across, NULL)) return -1; @@ -1231,6 +1238,14 @@ vips_foreign_load_jp2k_class_init(VipsForeignLoadJp2kClass *class) VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignLoadJp2k, page), 0, 100000, 0); + + VIPS_ARG_BOOL(class, "oneshot", 21, + _("One-shot"), + _("Load images a frame at a time"), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET(VipsForeignLoadJp2k, oneshot), + FALSE); + } static void @@ -1607,14 +1622,11 @@ vips__foreign_load_jp2k_decompress(VipsImage *out, * vips_jp2kload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @page: %gint, load this page - * * @fail_on: #VipsFailOn, types of read error to fail on + * Read a JPEG2000 image. * - * Read a JPEG2000 image. The loader supports 8, 16 and 32-bit int pixel + * The loader supports 8, 16 and 32-bit int pixel * values, signed and unsigned. It supports greyscale, RGB, YCC, CMYK and * multispectral colour spaces. It will read any ICC profile on the image. * @@ -1624,10 +1636,20 @@ vips__foreign_load_jp2k_decompress(VipsImage *out, * image and higher-numbered pages are x2 reductions. Use the metadata item * "n-pages" to find the number of pyramid layers. * + * Some versions of openjpeg can fail to decode some tiled images correctly. + * Setting @oneshot will force the loader to decode tiled images in a single + * operation and can improve compatibility. + * * Use @fail_on to set the type of error that will cause load to fail. By - * default, loaders are permissive, that is, #VIPS_FAIL_ON_NONE. + * default, loaders are permissive, that is, [enum@Vips.FailOn.NONE]. + * + * ::: tip "Optional arguments" + * * @page: `gint`, load this page + * * @oneshot: `gboolean`, load pages in one-shot mode + * * @fail_on: [enum@FailOn], types of read error to fail on * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -1649,17 +1671,17 @@ vips_jp2kload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @page: %gint, load this page - * * @fail_on: #VipsFailOn, types of read error to fail on - * - * Exactly as vips_jp2kload(), but read from a buffer. + * Exactly as [ctor@Image.jp2kload], but read from a buffer. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. + * + * ::: tip "Optional arguments" + * * @page: `gint`, load this page + * * @oneshot: `gboolean`, load pages in one-shot mode + * * @fail_on: [enum@FailOn], types of read error to fail on * * Returns: 0 on success, -1 on error. */ @@ -1687,14 +1709,14 @@ vips_jp2kload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_jp2kload_source: * @source: source to load from * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @page: %gint, load this page - * * @fail_on: #VipsFailOn, types of read error to fail on + * Exactly as [ctor@Image.jp2kload], but read from a source. * - * Exactly as vips_jp2kload(), but read from a source. + * ::: tip "Optional arguments" + * * @page: `gint`, load this page + * * @oneshot: `gboolean`, load pages in one-shot mode + * * @fail_on: [enum@FailOn], types of read error to fail on * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/jp2ksave.c b/libvips/foreign/jp2ksave.c index e23fd14ff3..b92b4b58c8 100644 --- a/libvips/foreign/jp2ksave.c +++ b/libvips/foreign/jp2ksave.c @@ -482,7 +482,7 @@ vips_foreign_save_jp2k_sizeof_tile(VipsForeignSaveJp2k *jp2k, VipsRect *tile) (double) tile->height / comp->dy); ; - size += output_width * output_height * sizeof_element; + size += (size_t) output_width * output_height * sizeof_element; } return size; @@ -819,11 +819,14 @@ vips_foreign_save_jp2k_build(VipsObject *object) return -1; } + /* The "lossless" param implies no chroma subsampling. + */ + if (jp2k->lossless) + jp2k->subsample_mode = VIPS_FOREIGN_SUBSAMPLE_OFF; + switch (jp2k->subsample_mode) { case VIPS_FOREIGN_SUBSAMPLE_AUTO: - jp2k->subsample = - !jp2k->lossless && - jp2k->Q < 90 && + jp2k->subsample = jp2k->Q < 90 && (save->ready->Type == VIPS_INTERPRETATION_sRGB || save->ready->Type == VIPS_INTERPRETATION_RGB16) && save->ready->Bands == 3; @@ -962,7 +965,7 @@ vips_foreign_save_jp2k_class_init(VipsForeignSaveJp2kClass *class) foreign_class->suffs = vips__jp2k_suffs; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; VIPS_ARG_INT(class, "tile_width", 11, _("Tile width"), @@ -1438,17 +1441,10 @@ vips__foreign_save_jp2k_compress(VipsRegion *region, * vips_jp2ksave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @lossless: %gboolean, enables lossless compression - * * @tile_width: %gint for tile size - * * @tile_height: %gint for tile size - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image to a file in JPEG2000 format. + * * The saver supports 8, 16 and 32-bit int pixel * values, signed and unsigned. It supports greyscale, RGB, CMYK and * multispectral images. @@ -1467,7 +1463,15 @@ vips__foreign_save_jp2k_compress(VipsRegion *region, * * This operation always writes a pyramid. * - * See also: vips_image_write_to_file(), vips_jp2kload(). + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @lossless: `gboolean`, enables lossless compression + * * @tile_width: `gint`, tile width + * * @tile_height: `gint`, tile width + * * @subsample_mode: [enum@ForeignSubsample], chroma subsampling mode + * + * ::: seealso + * [method@Image.write_to_file], [ctor@Image.jp2kload]. * * Returns: 0 on success, -1 on error. */ @@ -1489,19 +1493,19 @@ vips_jp2ksave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * As [method@Image.jp2ksave], but save to a target. * - * * @Q: %gint, quality factor - * * @lossless: %gboolean, enables lossless compression - * * @tile_width: %gint for tile size - * * @tile_height: %gint for tile size - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @lossless: `gboolean`, enables lossless compression + * * @tile_width: `gint`, tile width + * * @tile_height: `gint`, tile width + * * @subsample_mode: [enum@ForeignSubsample], chroma subsampling mode * - * As vips_jp2ksave(), but save to a target. - * - * See also: vips_jp2ksave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.jp2ksave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ @@ -1537,19 +1541,19 @@ vips_jp2ksave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_jp2ksave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @Q: %gint, quality factor - * * @lossless: %gboolean, enables lossless compression - * * @tile_width: %gint for tile size - * * @tile_height: %gint for tile size - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode + * As [method@Image.jp2ksave], but save to a target. * - * As vips_jp2ksave(), but save to a target. + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @lossless: `gboolean`, enables lossless compression + * * @tile_width: `gint`, tile width + * * @tile_height: `gint`, tile width + * * @subsample_mode: [enum@ForeignSubsample], chroma subsampling mode * - * See also: vips_jp2ksave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.jp2ksave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/jpeg.h b/libvips/foreign/jpeg.h index 3eb654c237..097bc46d57 100644 --- a/libvips/foreign/jpeg.h +++ b/libvips/foreign/jpeg.h @@ -35,13 +35,6 @@ extern "C" { #endif /*__cplusplus*/ -/* jpeglib includes jconfig.h, which can define HAVE_STDLIB_H ... which we - * also define. Make sure it's turned off. - */ -#ifdef HAVE_STDLIB_H -#undef HAVE_STDLIB_H -#endif /*HAVE_STDLIB_H*/ - /* jpeglib defines its own boolean type as an enum which then clashes with * everyone elses. Rename it as jboolean. */ diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 2a4c28d60d..d6c77624fd 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -230,7 +230,7 @@ source_init_source(j_decompress_ptr cinfo) */ } -/* Fill the input buffer --- called whenever buffer is emptied. +/* Fill the input buffer -- called whenever buffer is emptied. */ static boolean source_fill_input_buffer(j_decompress_ptr cinfo) @@ -654,7 +654,7 @@ read_jpeg_header(ReadJpeg *jpeg, VipsImage *out) break; default: - g_warning("%s", _("unknown JFIF resolution unit")); + g_warning("unknown JFIF resolution unit"); break; } @@ -896,7 +896,7 @@ read_jpeg_generate(VipsRegion *out_region, VIPS_GATE_STOP("read_jpeg_generate: work"); #ifdef DEBUG - printf("read_jpeg_generate: longjmp() exit\n"); + printf("read_jpeg_generate() exit\n"); #endif /*DEBUG*/ return -1; diff --git a/libvips/foreign/jpegload.c b/libvips/foreign/jpegload.c index bb448a778f..6a73aa5282 100644 --- a/libvips/foreign/jpegload.c +++ b/libvips/foreign/jpegload.c @@ -201,12 +201,14 @@ vips_foreign_load_jpeg_class_init(VipsForeignLoadJpegClass *class) G_STRUCT_OFFSET(VipsForeignLoadJpeg, autorotate), FALSE); +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION VIPS_ARG_BOOL(class, "unlimited", 22, _("Unlimited"), _("Remove all denial of service limits"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignLoadJpeg, unlimited), FALSE); +#endif } static void @@ -443,13 +445,7 @@ vips_foreign_load_jpeg_buffer_init(VipsForeignLoadJpegBuffer *buffer) * vips_jpegload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @shrink: %gint, shrink by this much on load - * * @fail_on: #VipsFailOn, types of read error to fail on - * * @autorotate: %gboolean, rotate image upright during load + * @...: `NULL`-terminated list of optional named arguments * * Read a JPEG file into a VIPS image. It can read most 8-bit JPEG images, * including CMYK and YCbCr. @@ -459,38 +455,38 @@ vips_foreign_load_jpeg_buffer_init(VipsForeignLoadJpegBuffer *buffer) * decompressing the whole image and then shrinking later. * * Use @fail_on to set the type of error that will cause load to fail. By - * default, loaders are permissive, that is, #VIPS_FAIL_ON_NONE. + * default, loaders are permissive, that is, [enum@Vips.FailOn.NONE]. * - * Setting @autorotate to %TRUE will make the loader interpret the + * Setting @autorotate to `TRUE` will make the loader interpret the * orientation tag and automatically rotate the image appropriately during * load. * - * If @autorotate is %FALSE, the metadata field #VIPS_META_ORIENTATION is set + * If @autorotate is `FALSE`, the metadata field [const@META_ORIENTATION] is set * to the value of the orientation tag. Applications may read and interpret * this field - * as they wish later in processing. See vips_autorot(). Save - * operations will use #VIPS_META_ORIENTATION, if present, to set the + * as they wish later in processing. See [method@Image.autorot]. Save + * operations will use [const@META_ORIENTATION], if present, to set the * orientation of output images. * * Example: * - * |[ - * vips_jpegload("fred.jpg", &out, + * ```c + * vips_jpegload("fred.jpg", &out, * "shrink", 8, * "fail_on", VIPS_FAIL_ON_TRUNCATED, * NULL); - * ]| + * ``` * * Any embedded ICC profiles are ignored: you always just get the RGB from * the file. Instead, the embedded profile will be attached to the image as - * #VIPS_META_ICC_NAME. You need to use something like - * vips_icc_import() to get CIE values from the file. + * [const@META_ICC_NAME]. You need to use something like + * [method@Image.icc_import] to get CIE values from the file. * - * EXIF metadata is attached as #VIPS_META_EXIF_NAME, IPTC as - * #VIPS_META_IPTC_NAME, and XMP as #VIPS_META_XMP_NAME. + * EXIF metadata is attached as [const@META_EXIF_NAME], IPTC as + * [const@META_IPTC_NAME], and XMP as [const@META_XMP_NAME]. * * The int metadata item "jpeg-multiscan" is set to the result of - * jpeg_has_multiple_scans(). Interlaced jpeg images need a large amount of + * `jpeg_has_multiple_scans()`. Interlaced jpeg images need a large amount of * memory to load, so this field gives callers a chance to handle these * images differently. * @@ -500,9 +496,16 @@ vips_foreign_load_jpeg_buffer_init(VipsForeignLoadJpegBuffer *buffer) * image with no subsampling. * * The EXIF thumbnail, if present, is attached to the image as - * "jpeg-thumbnail-data". See vips_image_get_blob(). + * "jpeg-thumbnail-data". See [method@Image.get_blob]. + * + * ::: tip "Optional arguments" + * * @shrink: `gint`, shrink by this much on load + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @autorotate: `gboolean`, use exif Orientation tag to rotate the image + * during load * - * See also: vips_jpegload_buffer(), vips_image_new_from_file(), vips_autorot(). + * ::: seealso + * [ctor@Image.jpegload_buffer], [method@Image.autorot]. * * Returns: 0 on success, -1 on error. */ @@ -524,22 +527,22 @@ vips_jpegload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @shrink: %gint, shrink by this much on load - * * @fail_on: #VipsFailOn, types of read error to fail on - * * @autorotate: %gboolean, use exif Orientation tag to rotate the image - * during load + * @...: `NULL`-terminated list of optional named arguments * * Read a JPEG-formatted memory block into a VIPS image. Exactly as - * vips_jpegload(), but read from a memory buffer. + * [ctor@Image.jpegload], but read from a memory buffer. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. * - * See also: vips_jpegload(). + * ::: tip "Optional arguments" + * * @shrink: `gint`, shrink by this much on load + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @autorotate: `gboolean`, use exif Orientation tag to rotate the image + * during load + * + * ::: seealso + * [ctor@Image.jpegload]. * * Returns: 0 on success, -1 on error. */ @@ -567,19 +570,19 @@ vips_jpegload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_jpegload_source: * @source: source to load * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @shrink: %gint, shrink by this much on load - * * @fail_on: #VipsFailOn, types of read error to fail on - * * @autorotate: %gboolean, use exif Orientation tag to rotate the image - * during load + * @...: `NULL`-terminated list of optional named arguments * * Read a JPEG-formatted memory block into a VIPS image. Exactly as - * vips_jpegload(), but read from a source. + * [ctor@Image.jpegload], but read from a source. + * + * ::: tip "Optional arguments" + * * @shrink: `gint`, shrink by this much on load + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @autorotate: `gboolean`, use exif Orientation tag to rotate the image + * during load * - * See also: vips_jpegload(). + * ::: seealso + * [ctor@Image.jpegload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/jpegsave.c b/libvips/foreign/jpegsave.c index 6446c79034..8349cdafee 100644 --- a/libvips/foreign/jpegsave.c +++ b/libvips/foreign/jpegsave.c @@ -157,7 +157,10 @@ vips_foreign_save_jpeg_class_init(VipsForeignSaveJpegClass *class) /* See also vips_foreign_save_tiff_build() when saving JPEG in TIFF. */ - save_class->saveable = VIPS_SAVEABLE_RGB_CMYK; + save_class->saveable = + VIPS_FOREIGN_SAVEABLE_MONO | + VIPS_FOREIGN_SAVEABLE_RGB | + VIPS_FOREIGN_SAVEABLE_CMYK; save_class->format_table = bandfmt_jpeg; VIPS_ARG_INT(class, "Q", 10, @@ -523,19 +526,7 @@ vips_foreign_save_jpeg_mime_init(VipsForeignSaveJpegMime *mime) * vips_jpegsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @optimize_coding: %gboolean, compute optimal Huffman coding tables - * * @interlace: %gboolean, write an interlaced (progressive) jpeg - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode - * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * * @optimize_scans: %gboolean, split DCT coefficients into separate scans - * * @quant_table: %gint, quantization table index - * * @restart_interval: %gint, restart interval in mcu + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image to a file as JPEG. * @@ -604,15 +595,27 @@ vips_foreign_save_jpeg_mime_init(VipsForeignSaveJpegMime *mime) * The image is automatically converted to RGB, Monochrome or CMYK before * saving. * - * EXIF data is constructed from #VIPS_META_EXIF_NAME, then + * EXIF data is constructed from [const@META_EXIF_NAME], then * modified with any other related tags on the image before being written to - * the file. #VIPS_META_RESOLUTION_UNIT is used to set the EXIF resolution - * unit. #VIPS_META_ORIENTATION is used to set the EXIF orientation tag. + * the file. [const@META_RESOLUTION_UNIT] is used to set the EXIF resolution + * unit. [const@META_ORIENTATION] is used to set the EXIF orientation tag. * - * IPTC as #VIPS_META_IPTC_NAME and XMP as #VIPS_META_XMP_NAME + * IPTC as [const@META_IPTC_NAME] and XMP as [const@META_XMP_NAME] * are coded and attached. * - * See also: vips_jpegsave_buffer(), vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @optimize_coding: `gboolean`, compute optimal Huffman coding tables + * * @interlace: `gboolean`, write an interlaced (progressive) jpeg + * * @subsample_mode: [enum@ForeignSubsample], chroma subsampling mode + * * @trellis_quant: `gboolean`, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: `gboolean`, overshoot samples with extreme values + * * @optimize_scans: `gboolean`, split DCT coefficients into separate scans + * * @quant_table: `gint`, quantization table index + * * @restart_interval: `gint`, restart interval in mcu + * + * ::: seealso + * [method@Image.jpegsave_buffer], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -633,23 +636,23 @@ vips_jpegsave(VipsImage *in, const char *filename, ...) * vips_jpegsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * As [method@Image.jpegsave], but save to a target. * - * * @Q: %gint, quality factor - * * @optimize_coding: %gboolean, compute optimal Huffman coding tables - * * @interlace: %gboolean, write an interlaced (progressive) jpeg - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode - * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * * @optimize_scans: %gboolean, split DCT coefficients into separate scans - * * @quant_table: %gint, quantization table index - * * @restart_interval: %gint, restart interval in mcu + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @optimize_coding: `gboolean`, compute optimal Huffman coding tables + * * @interlace: `gboolean`, write an interlaced (progressive) jpeg + * * @subsample_mode: [enum@ForeignSubsample], chroma subsampling mode + * * @trellis_quant: `gboolean`, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: `gboolean`, overshoot samples with extreme values + * * @optimize_scans: `gboolean`, split DCT coefficients into separate scans + * * @quant_table: `gint`, quantization table index + * * @restart_interval: `gint`, restart interval in mcu * - * As vips_jpegsave(), but save to a target. - * - * See also: vips_jpegsave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.jpegsave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ @@ -671,27 +674,27 @@ vips_jpegsave_target(VipsImage *in, VipsTarget *target, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @optimize_coding: %gboolean, compute optimal Huffman coding tables - * * @interlace: %gboolean, write an interlaced (progressive) jpeg - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode - * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * * @optimize_scans: %gboolean, split DCT coefficients into separate scans - * * @quant_table: %gint, quantization table index - * * @restart_interval: %gint, restart interval in mcu + * @...: `NULL`-terminated list of optional named arguments * - * As vips_jpegsave(), but save to a memory buffer. + * As [method@Image.jpegsave], but save to a memory buffer. * * The address of the buffer is returned in @obuf, the length of the buffer in - * @olen. You are responsible for freeing the buffer with g_free() when you - * are done with it. - * - * See also: vips_jpegsave(), vips_image_write_to_file(). + * @olen. You are responsible for freeing the buffer with [func@GLib.free] + * when you are done with it. + * + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @optimize_coding: `gboolean`, compute optimal Huffman coding tables + * * @interlace: `gboolean`, write an interlaced (progressive) jpeg + * * @subsample_mode: [enum@ForeignSubsample], chroma subsampling mode + * * @trellis_quant: `gboolean`, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: `gboolean`, overshoot samples with extreme values + * * @optimize_scans: `gboolean`, split DCT coefficients into separate scans + * * @quant_table: `gint`, quantization table index + * * @restart_interval: `gint`, restart interval in mcu + * + * ::: seealso + * [method@Image.jpegsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -726,23 +729,23 @@ vips_jpegsave_buffer(VipsImage *in, void **buf, size_t *len, ...) /** * vips_jpegsave_mime: (method) * @in: image to save - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @optimize_coding: %gboolean, compute optimal Huffman coding tables - * * @interlace: %gboolean, write an interlaced (progressive) jpeg - * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode - * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * * @optimize_scans: %gboolean, split DCT coefficients into separate scans - * * @quant_table: %gint, quantization table index - * * @restart_interval: %gint, restart interval in mcu - * - * As vips_jpegsave(), but save as a mime jpeg on stdout. - * - * See also: vips_jpegsave(), vips_image_write_to_file(). + * @...: `NULL`-terminated list of optional named arguments + * + * As [method@Image.jpegsave], but save as a mime jpeg on stdout. + * + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @optimize_coding: `gboolean`, compute optimal Huffman coding tables + * * @interlace: `gboolean`, write an interlaced (progressive) jpeg + * * @subsample_mode: [enum@ForeignSubsample], chroma subsampling mode + * * @trellis_quant: `gboolean`, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: `gboolean`, overshoot samples with extreme values + * * @optimize_scans: `gboolean`, split DCT coefficients into separate scans + * * @quant_table: `gint`, quantization table index + * * @restart_interval: `gint`, restart interval in mcu + * + * ::: seealso + * [method@Image.jpegsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/jxlload.c b/libvips/foreign/jxlload.c index c53e8f5ab2..1993057496 100644 --- a/libvips/foreign/jxlload.c +++ b/libvips/foreign/jxlload.c @@ -196,14 +196,12 @@ vips_foreign_load_jxl_build(VipsObject *object) printf("vips_foreign_load_jxl_build:\n"); #endif /*DEBUG*/ - jxl->runner = JxlThreadParallelRunnerCreate(NULL, - vips_concurrency_get()); + jxl->runner = JxlThreadParallelRunnerCreate(NULL, vips_concurrency_get()); jxl->decoder = JxlDecoderCreate(NULL); if (JxlDecoderSetParallelRunner(jxl->decoder, JxlThreadParallelRunner, jxl->runner)) { - vips_foreign_load_jxl_error(jxl, - "JxlDecoderSetParallelRunner"); + vips_foreign_load_jxl_error(jxl, "JxlDecoderSetParallelRunner"); return -1; } @@ -636,14 +634,12 @@ vips_foreign_load_jxl_generate(VipsRegion *out_region, static int vips_foreign_load_jxl_fix_exif(VipsForeignLoadJxl *jxl) { - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(jxl); - if (!jxl->exif_data || vips_isprefix("Exif", (char *) jxl->exif_data)) return 0; if (jxl->exif_size < 4) { - g_warning("%s: invalid data in EXIF box", class->nickname); + g_warning("invalid data in EXIF box"); return -1; } @@ -651,7 +647,7 @@ vips_foreign_load_jxl_fix_exif(VipsForeignLoadJxl *jxl) */ size_t offset = GUINT32_FROM_BE(*((guint32 *) jxl->exif_data)); if (offset > jxl->exif_size - 4) { - g_warning("%s: invalid data in EXIF box", class->nickname); + g_warning("invalid data in EXIF box"); return -1; } @@ -745,7 +741,7 @@ vips_foreign_load_jxl_set_header(VipsForeignLoadJxl *jxl, VipsImage *out) if (jxl->frame_count > 1) { if (jxl->n == -1) - jxl->n = jxl->frame_count - jxl->page; + jxl->n = jxl->frame_count - jxl->page; // FIXME: Invalidates operation cache if (jxl->page < 0 || jxl->n <= 0 || @@ -766,14 +762,14 @@ vips_foreign_load_jxl_set_header(VipsForeignLoadJxl *jxl, VipsImage *out) /* gif uses centiseconds for delays */ - vips_image_set_int(out, "gif-delay", VIPS_RINT(delay[0] / 10.0)); + vips_image_set_int(out, "gif-delay", rint(delay[0] / 10.0)); vips_image_set_int(out, "loop", jxl->info.animation.num_loops); } } else { - jxl->n = 1; - jxl->page = 0; + jxl->n = 1; // FIXME: Invalidates operation cache + jxl->page = 0; // FIXME: Invalidates operation cache } /* Init jxl->frame only when we need to decode multiple frames. @@ -953,9 +949,6 @@ vips_foreign_load_jxl_header(VipsForeignLoad *load) case JXL_DEC_COLOR_ENCODING: if (JxlDecoderGetICCProfileSize(jxl->decoder, -#ifndef HAVE_LIBJXL_0_9 - &jxl->format, -#endif JXL_COLOR_PROFILE_TARGET_DATA, &jxl->icc_size)) { vips_foreign_load_jxl_error(jxl, "JxlDecoderGetICCProfileSize"); return -1; @@ -969,9 +962,6 @@ vips_foreign_load_jxl_header(VipsForeignLoad *load) return -1; if (JxlDecoderGetColorAsICCProfile(jxl->decoder, -#ifndef HAVE_LIBJXL_0_9 - &jxl->format, -#endif JXL_COLOR_PROFILE_TARGET_DATA, jxl->icc_data, jxl->icc_size)) { vips_foreign_load_jxl_error(jxl, @@ -995,7 +985,7 @@ vips_foreign_load_jxl_header(VipsForeignLoad *load) double tick = (double) jxl->info.animation.tps_denominator / jxl->info.animation.tps_numerator; // this duration in ms - int ms = VIPS_RINT(1000.0 * h.duration * tick); + int ms = rint(1000.0 * h.duration * tick); // h.duration of 0xffffffff is used for multipage JXL ... map // this to -1 in delay int duration = h.duration == 0xffffffff ? -1 : ms; diff --git a/libvips/foreign/jxlsave.c b/libvips/foreign/jxlsave.c index 83011cbd67..ac68fef793 100644 --- a/libvips/foreign/jxlsave.c +++ b/libvips/foreign/jxlsave.c @@ -4,6 +4,8 @@ * - from heifload.c * 21/5/22 * - add ICC profile support + * 8/5/25 + * - write with JxlEncoderAddChunkedFrame() for lower memory use */ /* @@ -57,17 +59,12 @@ #include "pforeign.h" /* TODO: - * - * - libjxl encode only works in one shot mode, so there's no way to write in - * chunks - * - * - add metadata support EXIF, XMP, etc. api for this is on the way - * - * - add animation support * * - libjxl is currently missing error messages (I think) * * - add support encoding images with > 4 bands. + * + * see FIXME note in _build() */ #define OUTPUT_BUFFER_SIZE (4096) @@ -87,6 +84,8 @@ typedef struct _VipsForeignSaveJxl { gboolean lossless; int Q; + gboolean error; + /* JXL multipage and animated images are the same, but multipage has * all the frame delays set to -1 (duration 0xffffffff). */ @@ -98,10 +97,11 @@ typedef struct _VipsForeignSaveJxl { int *delay; int delay_length; - /* The image we save. This is a copy of save->ready since we need to - * be able to update the metadata. + /* Image geometry. */ - VipsImage *image; + int page_height; + int page_count; + int page_number; /* Base image properties. */ @@ -114,23 +114,27 @@ typedef struct _VipsForeignSaveJxl { void *runner; JxlEncoder *encoder; - /* The current y position in the frame, page height, - * total number of pages, and the current page index. + /* Write buffer. */ - int write_y; - int page_height; - int page_count; - int page_number; + uint8_t output_buffer[OUTPUT_BUFFER_SIZE]; - /* VipsRegion is not always contiguous, but we need contiguous RGB(A) - * for libjxl. We need to copy each frame to a local buffer. + /* Chunk reader. */ - VipsPel *frame_bytes; - size_t frame_size; + struct JxlChunkedFrameInputSource input_source; - /* Write buffer. + /* Map thread ids to regions with this hash table, gate access to it with + * the mutex. */ - uint8_t output_buffer[OUTPUT_BUFFER_SIZE]; + GHashTable *tile_hash; + GMutex tile_lock; + + /* Current page we are saving. + */ + VipsImage *page; + + /* Track number of pixels saved here for eval reporting. + */ + guint64 processed; } VipsForeignSaveJxl; @@ -139,30 +143,179 @@ typedef VipsForeignSaveClass VipsForeignSaveJxlClass; G_DEFINE_ABSTRACT_TYPE(VipsForeignSaveJxl, vips_foreign_save_jxl, VIPS_TYPE_FOREIGN_SAVE); -/* String-based metadata fields we add. - */ -typedef struct _VipsForeignSaveJxlMetadata { - const char *name; /* as understood by libvips */ - JxlBoxType box_type; /* as understood by libjxl */ -} VipsForeignSaveJxlMetadata; +static void * +vips_foreign_save_jxl_get_buffer(void *opaque, size_t *size) +{ + VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) opaque; -static VipsForeignSaveJxlMetadata libjxl_metadata[] = { - { VIPS_META_EXIF_NAME, "Exif" }, - { VIPS_META_XMP_NAME, "xml " } -}; + *size = OUTPUT_BUFFER_SIZE; + return jxl->output_buffer; +} static void -vips_foreign_save_jxl_dispose(GObject *gobject) +vips_foreign_save_jxl_output_release_buffer(void *opaque, size_t written_bytes) { - VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) gobject; + VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) opaque; - VIPS_FREEF(JxlThreadParallelRunnerDestroy, jxl->runner); - VIPS_FREEF(JxlEncoderDestroy, jxl->encoder); - VIPS_FREE(jxl->frame_bytes); + if (vips_target_write(jxl->target, jxl->output_buffer, written_bytes)) + jxl->error = TRUE; +} - VIPS_UNREF(jxl->target); +static void +vips_foreign_save_jxl_seek(void *opaque, uint64_t position) +{ + VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) opaque; - G_OBJECT_CLASS(vips_foreign_save_jxl_parent_class)->dispose(gobject); + if (vips_target_seek(jxl->target, position, SEEK_SET) < 0) + jxl->error = TRUE; +} + +static void +vips_foreign_save_jxl_set_finalized_position(void *opaque, uint64_t position) +{ + // don't need this +} + +static void +vips_foreign_save_jxl_set_output_processor(VipsForeignSaveJxl *jxl) +{ + JxlEncoderSetOutputProcessor(jxl->encoder, + (struct JxlEncoderOutputProcessor) { + .opaque = jxl, + .get_buffer = vips_foreign_save_jxl_get_buffer, + .release_buffer = vips_foreign_save_jxl_output_release_buffer, + .seek = vips_foreign_save_jxl_seek, + .set_finalized_position = vips_foreign_save_jxl_set_finalized_position, + }); +} + +static void +vips_foreign_save_jxl_pixel_format(void *opaque, JxlPixelFormat *format) +{ +#ifdef DEBUG + printf("vips_foreign_save_jxl_pixel_format:\n"); +#endif /*DEBUG*/ + + VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) opaque; + + *format = jxl->format; +} + +static void +vips_foreign_save_jxl_extra_pixel_format(void *opaque, + size_t ec_index, JxlPixelFormat *format) +{ +#ifdef DEBUG + printf("vips_foreign_save_jxl_extra_pixel_format:\n"); +#endif /*DEBUG*/ + + return vips_foreign_save_jxl_pixel_format(opaque, format); +} + +static const void * +vips_foreign_save_jxl_data_at(void *opaque, + size_t xpos, size_t ypos, size_t xsize, size_t ysize, + size_t *row_offset) +{ + VipsForeignSave *save = (VipsForeignSave *) opaque; + VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) opaque; + +#ifdef DEBUG + printf("vips_foreign_save_jxl_data_at: " + "left = %zd, top = %zd, width = %zd, height = %zd\n", + xpos, ypos, xsize, ysize); +#endif /*DEBUG*/ + + /* Handy for testing. + if (ypos > 1000) { + jxl->error = TRUE; + vips_error("jxlsave", "%s", _("experimental early exit")); + return NULL; + } + */ + + VipsImage *tile; + if (vips_crop(jxl->page, &tile, xpos, ypos, xsize, ysize, NULL)) { + jxl->error = TRUE; + /* Returning NULL from data_at won't crash, but will cause a lot of + * messy libjxl diagnostic output. At least it stops save. + */ + return NULL; + } + + // disable progress reporting from this copy_memory() + vips_image_set_int(tile, "hide-progress", 1); + + VipsImage *memory; + if (!(memory = vips_image_copy_memory(tile))) { + VIPS_UNREF(tile); + jxl->error = TRUE; + return NULL; + } + VIPS_UNREF(tile); + + VipsPel *pels = VIPS_IMAGE_ADDR(memory, 0, 0); + *row_offset = VIPS_IMAGE_SIZEOF_LINE(memory); + + g_mutex_lock(&jxl->tile_lock); + + g_assert(!g_hash_table_lookup(jxl->tile_hash, pels)); + g_hash_table_insert(jxl->tile_hash, pels, memory); + +#ifdef DEBUG + printf("\tgenerated pels = %p\n", pels); +#endif /*DEBUG*/ + + g_mutex_unlock(&jxl->tile_lock); + + /* Trigger any eval callbacks on our source image and + * check for cancel. + */ + jxl->processed += xsize * ysize; + vips_image_eval(save->ready, jxl->processed); + if (vips_image_iskilled(save->ready)) + return NULL; + + return pels; +} + +static const void * +vips_foreign_save_jxl_extra_data_at(void* opaque, size_t ec_index, + size_t xpos, size_t ypos, size_t xsize, size_t ysize, size_t* row_offset) +{ +#ifdef DEBUG + printf("vips_foreign_save_jxl_extra_data_at:\n"); +#endif /*DEBUG*/ + + return vips_foreign_save_jxl_data_at(opaque, + xpos, ypos, xsize, ysize, row_offset); +} + +static void +vips_foreign_save_jxl_input_release_buffer(void *opaque, const void *pels) +{ + VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) opaque; + +#ifdef DEBUG + printf("vips_foreign_save_jxl_input_release_buffer: pels = %p\n", pels); +#endif /*DEBUG*/ + + g_assert(g_hash_table_lookup(jxl->tile_hash, pels)); + g_hash_table_remove(jxl->tile_hash, pels); +} + +static void +vips_foreign_save_jxl_set_input_source(VipsForeignSaveJxl *jxl) +{ + jxl->input_source = (struct JxlChunkedFrameInputSource) { + .opaque = jxl, + .get_color_channels_pixel_format = vips_foreign_save_jxl_pixel_format, + .get_color_channel_data_at = vips_foreign_save_jxl_data_at, + .get_extra_channel_pixel_format = + vips_foreign_save_jxl_extra_pixel_format, + .get_extra_channel_data_at = vips_foreign_save_jxl_extra_data_at, + .release_buffer = vips_foreign_save_jxl_input_release_buffer + }; } static void @@ -170,9 +323,10 @@ vips_foreign_save_jxl_error(VipsForeignSaveJxl *jxl, const char *details) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(jxl); - /* TODO ... jxl has no way to get error messages at the moment. + /* TODO ... libjxl seems to have no way to get error messages at the + * moment. */ - vips_error(class->nickname, "error %s", details); + vips_error(class->nickname, "%s error", details); } #ifdef DEBUG @@ -256,10 +410,6 @@ vips_foreign_save_jxl_print_status(JxlEncoderStatus status) printf("JXL_ENC_NEED_MORE_OUTPUT\n"); break; - case JXL_ENC_NOT_SUPPORTED: - printf("JXL_ENC_NOT_SUPPORTED\n"); - break; - default: printf("JXL_ENC_\n"); break; @@ -267,138 +417,182 @@ vips_foreign_save_jxl_print_status(JxlEncoderStatus status) } #endif /*DEBUG*/ -static int -vips_foreign_save_jxl_process_output(VipsForeignSaveJxl *jxl) +/* String-based metadata fields we add. + */ +typedef struct _VipsForeignSaveJxlMetadata { + const char *name; /* as understood by libvips */ + JxlBoxType box_type; /* as understood by libjxl */ +} VipsForeignSaveJxlMetadata; + +static VipsForeignSaveJxlMetadata libjxl_metadata[] = { + { VIPS_META_EXIF_NAME, "Exif" }, + { VIPS_META_XMP_NAME, "xml " } +}; + +static void +vips_foreign_save_jxl_finalize(GObject *gobject) { - JxlEncoderStatus status; - uint8_t *out; - size_t avail_out; - - do { - out = jxl->output_buffer; - avail_out = OUTPUT_BUFFER_SIZE; - status = JxlEncoderProcessOutput(jxl->encoder, - &out, &avail_out); - switch (status) { - case JXL_ENC_SUCCESS: - case JXL_ENC_NEED_MORE_OUTPUT: - if (OUTPUT_BUFFER_SIZE > avail_out && - vips_target_write(jxl->target, - jxl->output_buffer, - OUTPUT_BUFFER_SIZE - avail_out)) - return -1; - break; + VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) gobject; - default: - vips_foreign_save_jxl_error(jxl, - "JxlEncoderProcessOutput"); -#ifdef DEBUG - vips_foreign_save_jxl_print_status(status); -#endif /*DEBUG*/ - return -1; - } - } while (status != JXL_ENC_SUCCESS); + VIPS_FREEF(JxlThreadParallelRunnerDestroy, jxl->runner); + VIPS_FREEF(JxlEncoderDestroy, jxl->encoder); - return 0; + g_mutex_clear(&jxl->tile_lock); + + G_OBJECT_CLASS(vips_foreign_save_jxl_parent_class)->finalize(gobject); +} + +static void +vips_foreign_save_jxl_dispose(GObject *gobject) +{ + VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) gobject; + + VIPS_UNREF(jxl->target); + VIPS_FREEF(g_hash_table_destroy, jxl->tile_hash); + + G_OBJECT_CLASS(vips_foreign_save_jxl_parent_class)->dispose(gobject); } static int -vips_foreign_save_jxl_add_frame(VipsForeignSaveJxl *jxl) +vips_foreign_save_jxl_set_header(VipsForeignSaveJxl *jxl, VipsImage *in) { -#ifdef HAVE_LIBJXL_0_7 - JxlEncoderFrameSettings *frame_settings; -#else - JxlEncoderOptions *frame_settings; -#endif - -#ifdef HAVE_LIBJXL_0_7 - frame_settings = JxlEncoderFrameSettingsCreate(jxl->encoder, NULL); - JxlEncoderFrameSettingsSetOption(frame_settings, - JXL_ENC_FRAME_SETTING_DECODING_SPEED, jxl->tier); - JxlEncoderSetFrameDistance(frame_settings, jxl->distance); - JxlEncoderFrameSettingsSetOption(frame_settings, - JXL_ENC_FRAME_SETTING_EFFORT, jxl->effort); - JxlEncoderSetFrameLossless(frame_settings, jxl->lossless); + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(jxl); - if (jxl->info.have_animation) { - JxlFrameHeader header; - memset(&header, 0, sizeof(JxlFrameHeader)); + JxlEncoderInitBasicInfo(&jxl->info); - if (!jxl->is_animated) - header.duration = 0xffffffff; - else if (jxl->delay && jxl->page_number < jxl->delay_length) - header.duration = jxl->delay[jxl->page_number]; - else - header.duration = jxl->gif_delay * 10; + switch (in->BandFmt) { + case VIPS_FORMAT_UCHAR: + jxl->info.bits_per_sample = 8; + jxl->info.exponent_bits_per_sample = 0; + jxl->format.data_type = JXL_TYPE_UINT8; + break; - JxlEncoderSetFrameHeader(frame_settings, &header); + case VIPS_FORMAT_USHORT: + jxl->info.bits_per_sample = 16; + jxl->info.exponent_bits_per_sample = 0; + jxl->format.data_type = JXL_TYPE_UINT16; + break; + + case VIPS_FORMAT_FLOAT: + jxl->info.bits_per_sample = 32; + jxl->info.exponent_bits_per_sample = 8; + jxl->format.data_type = JXL_TYPE_FLOAT; + break; + + default: + g_assert_not_reached(); + break; } -#else - frame_settings = JxlEncoderOptionsCreate(jxl->encoder, NULL); - JxlEncoderOptionsSetDecodingSpeed(frame_settings, jxl->tier); - JxlEncoderOptionsSetDistance(frame_settings, jxl->distance); - JxlEncoderOptionsSetEffort(frame_settings, jxl->effort); - JxlEncoderOptionsSetLossless(frame_settings, jxl->lossless); -#endif - - if (JxlEncoderAddImageFrame(frame_settings, &jxl->format, - jxl->frame_bytes, jxl->frame_size)) { - vips_foreign_save_jxl_error(jxl, "JxlEncoderAddImageFrame"); - return -1; + + switch (in->Type) { + case VIPS_INTERPRETATION_B_W: + case VIPS_INTERPRETATION_GREY16: + jxl->info.num_color_channels = VIPS_MIN(1, in->Bands); + break; + + case VIPS_INTERPRETATION_sRGB: + case VIPS_INTERPRETATION_scRGB: + case VIPS_INTERPRETATION_RGB16: + jxl->info.num_color_channels = VIPS_MIN(3, in->Bands); + break; + + default: + jxl->info.num_color_channels = in->Bands; } + jxl->info.num_extra_channels = VIPS_MAX(0, + in->Bands - jxl->info.num_color_channels); - jxl->page_number += 1; + jxl->info.xsize = in->Xsize; + jxl->info.ysize = jxl->page_height; + jxl->format.num_channels = in->Bands; + jxl->format.endianness = JXL_NATIVE_ENDIAN; + jxl->format.align = 0; - /* We should close frames before processing the output - * if we have written the last frame - */ - if (jxl->page_number == jxl->page_count) - JxlEncoderCloseFrames(jxl->encoder); + if (jxl->page_count > 1) { + int num_loops = 0; - return vips_foreign_save_jxl_process_output(jxl); -} + if (vips_image_get_typeof(in, "loop")) + vips_image_get_int(in, "loop", &num_loops); -/* Another chunk of pixels have arrived from the pipeline. Add to frame, and - * if the frame completes, compress and write to the target. - */ -static int -vips_foreign_save_jxl_sink_disc(VipsRegion *region, VipsRect *area, void *a) -{ - VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) a; - size_t sz = VIPS_IMAGE_SIZEOF_PEL(region->im) * area->width; + jxl->info.have_animation = TRUE; + jxl->info.animation.tps_numerator = 1000; + jxl->info.animation.tps_denominator = 1; + jxl->info.animation.num_loops = num_loops; + jxl->info.animation.have_timecodes = FALSE; + } - int i; + if (vips_image_hasalpha(in)) { + jxl->info.alpha_bits = jxl->info.bits_per_sample; + jxl->info.alpha_exponent_bits = jxl->info.exponent_bits_per_sample; + } + else { + jxl->info.alpha_exponent_bits = 0; + jxl->info.alpha_bits = 0; + } + + if (vips_image_get_typeof(in, "stonits")) { + double stonits; - /* Write the new pixels into the frame. + if (vips_image_get_double(in, "stonits", &stonits)) + return -1; + jxl->info.intensity_target = stonits; + } + + /* uses_original_profile forces libjxl to not use lossy XYB + * colourspace. The name is very confusing. */ - for (i = 0; i < area->height; i++) { - memcpy(jxl->frame_bytes + sz * jxl->write_y, - VIPS_REGION_ADDR(region, 0, area->top + i), - sz); + jxl->info.uses_original_profile = jxl->lossless; - jxl->write_y += 1; + if (JxlEncoderSetBasicInfo(jxl->encoder, &jxl->info)) { + vips_foreign_save_jxl_error(jxl, "JxlEncoderSetBasicInfo"); + return -1; + } - /* If we've filled the frame, add it to the encoder. - */ - if (jxl->write_y == jxl->page_height) { - if (vips_foreign_save_jxl_add_frame(jxl)) - return -1; + /* Set any ICC profile. + */ + if (vips_image_get_typeof(in, VIPS_META_ICC_NAME)) { + const void *data; + size_t length; + + if (vips_image_get_blob(in, VIPS_META_ICC_NAME, &data, &length)) + return -1; - jxl->write_y = 0; +#ifdef DEBUG + printf("attaching %zd bytes of ICC\n", length); +#endif /*DEBUG*/ + if (JxlEncoderSetICCProfile(jxl->encoder, (guint8 *) data, length)) { + vips_foreign_save_jxl_error(jxl, "JxlEncoderSetColorEncoding"); + return -1; } } + else { + /* If there's no ICC profile, we must set the colour encoding + * ourselves. + */ + if (in->Type == VIPS_INTERPRETATION_scRGB) { +#ifdef DEBUG + printf("setting scRGB colourspace\n"); +#endif /*DEBUG*/ - return 0; -} + JxlColorEncodingSetToLinearSRGB(&jxl->color_encoding, + jxl->format.num_channels < 3); + } + else { +#ifdef DEBUG + printf("setting sRGB colourspace\n"); +#endif /*DEBUG*/ -static int -vips_foreign_save_jxl_add_metadata(VipsForeignSaveJxl *jxl, VipsImage *in) -{ -#ifdef HAVE_LIBJXL_0_7 - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(jxl); - int i; + JxlColorEncodingSetToSRGB(&jxl->color_encoding, + jxl->format.num_channels < 3); + } - for (i = 0; i < VIPS_NUMBER(libjxl_metadata); i++) + if (JxlEncoderSetColorEncoding(jxl->encoder, &jxl->color_encoding)) { + vips_foreign_save_jxl_error(jxl, "JxlEncoderSetColorEncoding"); + return -1; + } + } + + for (int i = 0; i < VIPS_NUMBER(libjxl_metadata); i++) if (vips_image_get_typeof(in, libjxl_metadata[i].name)) { uint8_t *data; size_t length; @@ -458,7 +652,98 @@ vips_foreign_save_jxl_add_metadata(VipsForeignSaveJxl *jxl, VipsImage *in) /* It's safe to call JxlEncoderCloseBoxes even if we don't use boxes */ JxlEncoderCloseBoxes(jxl->encoder); -#endif /*HAVE_LIBJXL_0_7*/ + + return 0; +} + +static int +vips_foreign_save_jxl_get_delay(VipsForeignSaveJxl *jxl, int page_number) +{ + int delay; + + if (jxl->delay && + page_number < jxl->delay_length) + delay = jxl->delay[page_number]; + else + // the old gif delay field was in centiseconds, so convert to ms + delay = jxl->gif_delay * 10; + + /* Force frames with a small or no duration to 100ms for consistency + * with web browsers and other transcoding tools. + */ + return delay <= 10 ? 100 : delay; +} + +static int +vips_foreign_save_jxl_save_page(VipsForeignSaveJxl *jxl, + int n, VipsImage *page) +{ + jxl->page = page; + jxl->tile_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) g_object_unref); + + JxlEncoderFrameSettings *frame_settings = + JxlEncoderFrameSettingsCreate(jxl->encoder, NULL); + JxlEncoderFrameSettingsSetOption(frame_settings, + JXL_ENC_FRAME_SETTING_DECODING_SPEED, jxl->tier); + JxlEncoderSetFrameDistance(frame_settings, + jxl->distance); + JxlEncoderFrameSettingsSetOption(frame_settings, + JXL_ENC_FRAME_SETTING_EFFORT, jxl->effort); + JxlEncoderSetFrameLossless(frame_settings, + jxl->lossless); + + if (jxl->info.have_animation) { + JxlFrameHeader header = { 0 }; + + if (!jxl->is_animated) + header.duration = 0xffffffff; + else + header.duration = vips_foreign_save_jxl_get_delay(jxl, n); + + JxlEncoderSetFrameHeader(frame_settings, &header); + } + + if (JxlEncoderAddChunkedFrame(frame_settings, + n == jxl->page_count - 1, jxl->input_source)) { + VIPS_FREEF(g_hash_table_destroy, jxl->tile_hash); + vips_foreign_save_jxl_error(jxl, "JxlEncoderAddImageFrame"); + return -1; + } + +#ifdef DEBUG + printf("end of frame encode, %d regions\n", + g_hash_table_size(jxl->tile_hash)); +#endif /*DEBUG*/ + + VIPS_FREEF(g_hash_table_destroy, jxl->tile_hash); + + return 0; +} + +static int +vips_foreign_save_jxl_save(VipsForeignSaveJxl *jxl, VipsImage *in) +{ + vips_foreign_save_jxl_set_output_processor(jxl); + vips_foreign_save_jxl_set_input_source(jxl); + + for (int n = 0; n < jxl->page_count; n++) { + VipsImage *page; + + if (vips_crop(in, &page, + 0, n * jxl->page_height, in->Xsize, jxl->page_height, NULL)) + return -1; + + if (vips_foreign_save_jxl_save_page(jxl, n, page)) { + VIPS_UNREF(page); + return -1; + } + + VIPS_UNREF(page); + + if (jxl->error) + return -1; + } return 0; } @@ -468,50 +753,34 @@ vips_foreign_save_jxl_build(VipsObject *object) { VipsForeignSave *save = (VipsForeignSave *) object; VipsForeignSaveJxl *jxl = (VipsForeignSaveJxl *) object; - VipsImage **t = (VipsImage **) vips_object_local_array(object, 2); + VipsImage **t = (VipsImage **) vips_object_local_array(object, 4); VipsImage *in; VipsBandFormat format; - int i; if (VIPS_OBJECT_CLASS(vips_foreign_save_jxl_parent_class)->build(object)) return -1; -#ifdef HAVE_LIBJXL_0_7 jxl->page_height = vips_image_get_page_height(save->ready); -#else - /* libjxl prior to 0.7 doesn't seem to have API for saving animations - */ - jxl->page_height = save->ready->Ysize; -#endif /*HAVE_LIBJXL_0_7*/ - jxl->page_count = save->ready->Ysize / jxl->page_height; /* If Q is set and distance is not, use Q to set a rough distance * value. */ if (!vips_object_argument_isset(object, "distance")) -#ifdef HAVE_LIBJXL_0_9 jxl->distance = JxlEncoderDistanceFromQuality((float) jxl->Q); -#else - jxl->distance = jxl->Q >= 30 - ? 0.1 + (100 - jxl->Q) * 0.09 - : 53.0 / 3000.0 * jxl->Q * jxl->Q - 23.0 / 20.0 * jxl->Q + 25.0; -#endif /* Distance 0 is lossless. libjxl will fail for lossy distance 0. */ if (jxl->distance == 0) jxl->lossless = TRUE; - jxl->runner = JxlThreadParallelRunnerCreate(NULL, - vips_concurrency_get()); + jxl->runner = JxlThreadParallelRunnerCreate(NULL, vips_concurrency_get()); jxl->encoder = JxlEncoderCreate(NULL); if (JxlEncoderSetParallelRunner(jxl->encoder, JxlThreadParallelRunner, jxl->runner)) { - vips_foreign_save_jxl_error(jxl, - "JxlDecoderSetParallelRunner"); + vips_foreign_save_jxl_error(jxl, "JxlDecoderSetParallelRunner"); return -1; } @@ -532,7 +801,7 @@ vips_foreign_save_jxl_build(VipsObject *object) return -1; in = t[0]; - /* Mimics VIPS_SAVEABLE_RGBA. + /* Mimics VIPS_FOREIGN_SAVEABLE_RGB | VIPS_FOREIGN_SAVEABLE_ALPHA. * FIXME: add support encoding images with > 4 bands. */ if (in->Bands > 4) { @@ -543,152 +812,19 @@ vips_foreign_save_jxl_build(VipsObject *object) in = t[1]; } - JxlEncoderInitBasicInfo(&jxl->info); - - switch (in->BandFmt) { - case VIPS_FORMAT_UCHAR: - jxl->info.bits_per_sample = 8; - jxl->info.exponent_bits_per_sample = 0; - jxl->format.data_type = JXL_TYPE_UINT8; - break; - - case VIPS_FORMAT_USHORT: - jxl->info.bits_per_sample = 16; - jxl->info.exponent_bits_per_sample = 0; - jxl->format.data_type = JXL_TYPE_UINT16; - break; - - case VIPS_FORMAT_FLOAT: - jxl->info.bits_per_sample = 32; - jxl->info.exponent_bits_per_sample = 8; - jxl->format.data_type = JXL_TYPE_FLOAT; - break; - - default: - g_assert_not_reached(); - break; - } - - switch (in->Type) { - case VIPS_INTERPRETATION_B_W: - case VIPS_INTERPRETATION_GREY16: - jxl->info.num_color_channels = VIPS_MIN(1, in->Bands); - break; - - case VIPS_INTERPRETATION_sRGB: - case VIPS_INTERPRETATION_scRGB: - case VIPS_INTERPRETATION_RGB16: - jxl->info.num_color_channels = VIPS_MIN(3, in->Bands); - break; - - default: - jxl->info.num_color_channels = in->Bands; - } - jxl->info.num_extra_channels = VIPS_MAX(0, - in->Bands - jxl->info.num_color_channels); - - jxl->info.xsize = in->Xsize; - jxl->info.ysize = jxl->page_height; - jxl->format.num_channels = in->Bands; - jxl->format.endianness = JXL_NATIVE_ENDIAN; - jxl->format.align = 0; - -#ifdef HAVE_LIBJXL_0_7 - if (jxl->page_count > 1) { - int num_loops = 0; - - if (vips_image_get_typeof(in, "loop")) - vips_image_get_int(in, "loop", &num_loops); - - // libjxl uses "have_animation" for multipage images too, but sets - // duration to 0xffffffff - jxl->info.have_animation = TRUE; - jxl->info.animation.tps_numerator = 1000; - jxl->info.animation.tps_denominator = 1; - jxl->info.animation.num_loops = num_loops; - jxl->info.animation.have_timecodes = FALSE; - } -#endif /*HAVE_LIBJXL_0_7*/ - - if (vips_image_hasalpha(in)) { - jxl->info.alpha_bits = jxl->info.bits_per_sample; - jxl->info.alpha_exponent_bits = - jxl->info.exponent_bits_per_sample; - } - else { - jxl->info.alpha_exponent_bits = 0; - jxl->info.alpha_bits = 0; - } - - if (vips_image_get_typeof(in, "stonits")) { - double stonits; - - if (vips_image_get_double(in, "stonits", &stonits)) - return -1; - jxl->info.intensity_target = stonits; - } - - /* uses_original_profile forces libjxl to not use lossy XYB - * colourspace. The name is very confusing. + /* We need to cache a complete line of jxl 2k x 2k tiles, plus a bit. + * We don't need to allow threaded access -- libjxl will never try to + * encode tiles in parallel (sadly). */ - jxl->info.uses_original_profile = jxl->lossless; - - if (JxlEncoderSetBasicInfo(jxl->encoder, &jxl->info)) { - vips_foreign_save_jxl_error(jxl, "JxlEncoderSetBasicInfo"); - return -1; - } - - /* Set any ICC profile. - */ - if (vips_image_get_typeof(in, VIPS_META_ICC_NAME)) { - const void *data; - size_t length; - - if (vips_image_get_blob(in, - VIPS_META_ICC_NAME, &data, &length)) - return -1; - -#ifdef DEBUG - printf("attaching %zd bytes of ICC\n", length); -#endif /*DEBUG*/ - if (JxlEncoderSetICCProfile(jxl->encoder, - (guint8 *) data, length)) { - vips_foreign_save_jxl_error(jxl, - "JxlEncoderSetColorEncoding"); - return -1; - } - } - else { - /* If there's no ICC profile, we must set the colour encoding - * ourselves. - */ - if (in->Type == VIPS_INTERPRETATION_scRGB) { -#ifdef DEBUG - printf("setting scRGB colourspace\n"); -#endif /*DEBUG*/ - - JxlColorEncodingSetToLinearSRGB(&jxl->color_encoding, - jxl->format.num_channels < 3); - } - else { -#ifdef DEBUG - printf("setting sRGB colourspace\n"); -#endif /*DEBUG*/ - - JxlColorEncodingSetToSRGB(&jxl->color_encoding, - jxl->format.num_channels < 3); - } - - if (JxlEncoderSetColorEncoding(jxl->encoder, &jxl->color_encoding)) { - vips_foreign_save_jxl_error(jxl, "JxlEncoderSetColorEncoding"); - return -1; - } - } - - if (vips_foreign_save_jxl_add_metadata(jxl, in)) + if (vips_tilecache(in, &t[2], + "tile-width", in->Xsize, + "tile-height", 512, + "max_tiles", 3500 / 512, + NULL)) return -1; + in = t[2]; - if (vips_foreign_save_jxl_process_output(jxl)) + if (vips_foreign_save_jxl_set_header(jxl, in)) return -1; if (jxl->info.have_animation) { @@ -697,16 +833,15 @@ vips_foreign_save_jxl_build(VipsObject *object) * There might just be the old gif-delay field. This is centiseconds. */ jxl->gif_delay = 10; - if (vips_image_get_typeof(save->ready, "gif-delay") && - vips_image_get_int(save->ready, "gif-delay", - &jxl->gif_delay)) + if (vips_image_get_typeof(in, "gif-delay") && + vips_image_get_int(in, "gif-delay", &jxl->gif_delay)) return -1; /* New images have an array of ints instead. */ jxl->delay = NULL; - if (vips_image_get_typeof(save->ready, "delay") && - vips_image_get_array_int(save->ready, "delay", + if (vips_image_get_typeof(in, "delay") && + vips_image_get_array_int(in, "delay", &jxl->delay, &jxl->delay_length)) return -1; @@ -716,17 +851,6 @@ vips_foreign_save_jxl_build(VipsObject *object) if (vips_image_get_typeof(save->ready, "delay") || vips_image_get_typeof(save->ready, "gif-delay")) jxl->is_animated = TRUE; - - /* Force frames with a small or no duration to 100ms - * to be consistent with web browsers and other - * transcoding tools. - */ - if (jxl->gif_delay <= 1) - jxl->gif_delay = 10; - - for (i = 0; i < jxl->delay_length; i++) - if (jxl->delay[i] <= 10) - jxl->delay[i] = 100; } #ifdef DEBUG @@ -739,31 +863,24 @@ vips_foreign_save_jxl_build(VipsObject *object) printf(" lossless = %d\n", jxl->lossless); #endif /*DEBUG*/ - /* RGB(A) frame as a contiguous buffer. + /* _save() is not a vips_sink_*() iterator, so we must emit + * the various signals by hand. */ - jxl->frame_size = VIPS_IMAGE_SIZEOF_LINE(in) * jxl->page_height; - jxl->frame_bytes = g_try_malloc(jxl->frame_size); - if (jxl->frame_bytes == NULL) { - vips_error("jxlsave", - _("failed to allocate %zu bytes"), jxl->frame_size); - return -1; - } + vips_image_preeval(save->ready); - if (vips_sink_disc(in, vips_foreign_save_jxl_sink_disc, jxl)) - return -1; + int result = vips_foreign_save_jxl_save(jxl, in); - /* This function must be called after the final frame and/or box, - * otherwise the codestream will not be encoded correctly. - */ - JxlEncoderCloseInput(jxl->encoder); + vips_image_posteval(save->ready); + + vips_image_minimise_all(save->ready); - if (vips_foreign_save_jxl_process_output(jxl)) + if (jxl->error) return -1; if (vips_target_end(jxl->target)) return -1; - return 0; + return result; } /* Save a bit of typing. @@ -788,6 +905,7 @@ vips_foreign_save_jxl_class_init(VipsForeignSaveJxlClass *class) VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class; + gobject_class->finalize = vips_foreign_save_jxl_finalize; gobject_class->dispose = vips_foreign_save_jxl_dispose; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -803,7 +921,7 @@ vips_foreign_save_jxl_class_init(VipsForeignSaveJxlClass *class) foreign_class->suffs = vips__jxl_suffs; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; save_class->format_table = bandfmt_jxl; VIPS_ARG_INT(class, "tier", 10, @@ -845,11 +963,10 @@ vips_foreign_save_jxl_class_init(VipsForeignSaveJxlClass *class) static void vips_foreign_save_jxl_init(VipsForeignSaveJxl *jxl) { - jxl->tier = 0; jxl->distance = 1.0; jxl->effort = 7; - jxl->lossless = FALSE; jxl->Q = 75; + g_mutex_init(&jxl->tile_lock); } typedef struct _VipsForeignSaveJxlFile { diff --git a/libvips/foreign/magick.c b/libvips/foreign/magick.c index f4e39ce3b4..1cf7ef1ce9 100644 --- a/libvips/foreign/magick.c +++ b/libvips/foreign/magick.c @@ -52,7 +52,7 @@ #if defined(HAVE_MAGICK6) || defined(HAVE_MAGICK7) -/* Imagemagick has weak support for some formats --- for example, AVI is +/* Imagemagick has weak support for some formats -- for example, AVI is * delegated to ffmpeg, and just getting the header can take many seconds and * many GB of memory. * @@ -654,8 +654,8 @@ magick_optimize_image_layers(Image **images, ExceptionInfo *exception) return MagickTrue; #else /*!HAVE_OPTIMIZEPLUSIMAGELAYERS*/ - g_warning("%s", _("layer optimization is not supported by " - "your version of libMagick")); + g_warning("layer optimization is not supported by " + "your version of libMagick"); return MagickTrue; #endif /*HAVE_OPTIMIZEPLUSIMAGELAYERS*/ @@ -670,8 +670,8 @@ magick_optimize_image_transparency(const Image *images, return exception->severity == UndefinedException; #else /*!HAVE_OPTIMIZEIMAGETRANSPARENCY*/ - g_warning("%s", _("transparency optimization is not supported by " - "your version of libMagick")); + g_warning("transparency optimization is not supported by " + "your version of libMagick"); return MagickTrue; #endif /*HAVE_OPTIMIZEIMAGETRANSPARENCY*/ diff --git a/libvips/foreign/magick2vips.c b/libvips/foreign/magick2vips.c deleted file mode 100644 index cb1146d5bd..0000000000 --- a/libvips/foreign/magick2vips.c +++ /dev/null @@ -1,958 +0,0 @@ -/* Read a file using libMagick - * - * 7/1/03 JC - * - from im_tiff2vips - * 3/2/03 JC - * - some InitializeMagick() fail with NULL arg - * 2/11/04 - * - im_magick2vips_header() also checks sensible width/height - * 28/10/05 - * - copy attributes to meta - * - write many-frame images as a big column if all frames have identical - * width/height/bands/depth - * 31/3/06 - * - test for magick attr support - * 8/5/06 - * - set RGB16/GREY16 if appropriate - * 10/8/07 - * - support 32/64 bit imagemagick too - * 21/2/08 - * - use MaxRGB if QuantumRange is missing (thanks Bob) - * - look for MAGICKCORE_HDRI_SUPPORT (thanks Marcel) - * - use image->attributes if GetNextImageAttribute() is missing - * 3/3/09 - * - allow funky bit depths, like 14 (thanks Mikkel) - * 17/3/09 - * - reset dcm:display-range to help DICOM read - * 20/4/09 - * - argh libMagick uses 255 == transparent ... we must invert all - * alpha channels - * 12/5/09 - * - fix signed/unsigned warnings - * 23/7/09 - * - SetImageOption() is optional (to help GM) - * 4/2/10 - * - gtkdoc - * 30/4/10 - * - better number of bands detection with GetImageType() - * - use new API stuff, argh - * 17/12/11 - * - turn into a set of read fns ready to be called from a class - * 11/6/13 - * - add @all_frames option, off by default - * 4/12/14 Lovell - * - add @density option - * 16/2/15 mcuelenaere - * - add blob read - * 26/2/15 - * - close the read down early for a header read ... this saves an - * fd during file read, handy for large numbers of input images - * 14/2/16 - * - add @page option, 0 by default - * 18/4/16 - * - fix @page with graphicsmagick - * 25/11/16 - * - remove @all_frames, add @n - * 23/2/17 - * - try using GetImageChannelDepth() instead of ->depth - * 25/5/18 - * - don't use Ping, it's too unreliable - * 24/7/18 - * - sniff extra filetypes - * 4/1/19 kleisauke - * - we did not chain exceptions correctly, causing a memory leak - * - added wrapper funcs for exception handling - * 4/2/19 - * - add profile (xmp, ipct, etc.) read - * 12/11/21 - * - set "orientation" - * 26/8/22 - * - set "magick-format" - * 13/3/23 MathemanFlo - * - add bits per sample metadata - */ - -/* - - 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 - - */ - -/* Turn on debugging output. -#define DEBUG - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ -#include - -#ifdef ENABLE_MAGICKLOAD - -#ifdef HAVE_MAGICK6 - -#include -#include -#include -#include - -#include -#include - -#include - -#include "pforeign.h" -#include "magick.h" - -/* pre-float Magick used to call this MaxRGB. - */ -#if !defined(QuantumRange) -#define QuantumRange MaxRGB -#endif - -/* And this used to be UseHDRI. - */ -#if MAGICKCORE_HDRI_SUPPORT -#define UseHDRI 1 -#endif - -/* What we track during a read call. - */ -typedef struct _Read { - char *filename; - VipsImage *im; - const void *buf; - size_t len; - int page; - int n; - - Image *image; - ImageInfo *image_info; - ExceptionInfo *exception; - - /* Number of pages in image. - */ - int n_pages; - - /* Number of pages we will read. - */ - int n_frames; - - Image **frames; - int frame_height; - - /* Mutex to serialise calls to libMagick during threaded read. - */ - GMutex *lock; -} Read; - -/* Can be called many times. - */ -static void -read_free(Read *read) -{ -#ifdef DEBUG - printf("magick2vips: read_free: %s\n", read->filename); -#endif /*DEBUG*/ - - VIPS_FREE(read->filename); - VIPS_FREEF(DestroyImageList, read->image); - VIPS_FREEF(DestroyImageInfo, read->image_info); - VIPS_FREE(read->frames); - VIPS_FREEF(magick_destroy_exception, read->exception); - VIPS_FREEF(vips_g_mutex_free, read->lock); -} - -/* Can be called many times. - */ -static int -read_close(VipsImage *im, Read *read) -{ - read_free(read); - - return 0; -} - -static Read * -read_new(const char *filename, VipsImage *im, - const void *buf, const size_t len, - const char *density, int page, int n) -{ - Read *read; - - magick_genesis(); - - /* IM doesn't use the -1 means end-of-file convention, change it to a - * very large number. - */ - if (n == -1) - n = 10000000; - - if (!(read = VIPS_NEW(im, Read))) - return NULL; - read->filename = filename ? g_strdup(filename) : NULL; - read->buf = buf; - read->len = len; - read->page = page; - read->n = n; - read->im = im; - read->image = NULL; - read->image_info = CloneImageInfo(NULL); - read->exception = magick_acquire_exception(); - read->n_pages = 0; - read->n_frames = 0; - read->frames = NULL; - read->frame_height = 0; - read->lock = vips_g_mutex_new(); - - g_signal_connect(im, "close", G_CALLBACK(read_close), read); - - if (!read->image_info) - return NULL; - - if (filename) - g_strlcpy(read->image_info->filename, - filename, MaxTextExtent); - - /* Any extra file format detection. - */ - if (filename) - magick_sniff_file(read->image_info, filename); - if (buf) - magick_sniff_bytes(read->image_info, buf, len); - - /* Canvas resolution for rendering vector formats like SVG. - */ - VIPS_SETSTR(read->image_info->density, density); - - /* When reading DICOM images, we want to ignore any - * window_center/_width setting, since it may put pixels outside the - * 0-65535 range and lose data. - * - * These window settings are attached as vips metadata, so our caller - * can interpret them if it wants. - */ - magick_set_image_option(read->image_info, - "dcm:display-range", "reset"); - - if (read->page > 0) - magick_set_number_scenes(read->image_info, - read->page, read->n); - -#ifdef DEBUG - printf("magick2vips: read_new: %s\n", read->filename); -#endif /*DEBUG*/ - - return read; -} - -static int -get_bands(Image *image) -{ - int bands; - ImageType type = GetImageType(image, &image->exception); - - switch (type) { - case BilevelType: - case GrayscaleType: - bands = 1; - break; - - case GrayscaleMatteType: - /* ImageMagick also has PaletteBilevelMatteType, but GraphicsMagick - * does not. Skip for portability. - */ - bands = 2; - break; - - case PaletteType: - case TrueColorType: - bands = 3; - break; - - case PaletteMatteType: - case TrueColorMatteType: - case ColorSeparationType: - bands = 4; - break; - - case ColorSeparationMatteType: - bands = 5; - break; - - default: - vips_error("magick2vips", _("unsupported image type %d"), - (int) type); - return -1; - } - - return bands; -} - -static int -parse_header(Read *read) -{ - VipsImage *im = read->im; - Image *image = read->image; - - int depth; - Image *p; - int i; - -#ifdef DEBUG - printf("parse_header: filename = %s\n", read->filename); - printf("GetImageChannelDepth(AllChannels) = %zd\n", - GetImageChannelDepth(image, AllChannels, &image->exception)); - printf("GetImageDepth() = %zd\n", - GetImageDepth(image, &image->exception)); - printf("image->depth = %zd\n", image->depth); - printf("GetImageType() = %d\n", - GetImageType(image, &image->exception)); - printf("IsGrayImage() = %d\n", - IsGrayImage(image, &image->exception)); - printf("IsMonochromeImage() = %d\n", - IsMonochromeImage(image, &image->exception)); - printf("IsOpaqueImage() = %d\n", - IsOpaqueImage(image, &image->exception)); - printf("image->columns = %zd\n", image->columns); - printf("image->rows = %zd\n", image->rows); -#endif /*DEBUG*/ - - im->Coding = VIPS_CODING_NONE; - im->Xsize = image->columns; - im->Ysize = image->rows; - read->frame_height = image->rows; - im->Bands = get_bands(image); - if (im->Xsize <= 0 || - im->Ysize <= 0 || - im->Bands <= 0 || - im->Xsize >= VIPS_MAX_COORD || - im->Ysize >= VIPS_MAX_COORD || - im->Bands >= VIPS_MAX_COORD) { - vips_error("magick2vips", - _("bad image dimensions %d x %d pixels, %d bands"), - im->Xsize, im->Ysize, im->Bands); - return -1; - } - - /* Depth can be 'fractional'. - * - * You'd think we should use - * GetImageDepth() but that seems unreliable. 16-bit mono DICOM images - * are reported as depth 1, for example. - * - * Try GetImageChannelDepth(), maybe that works. - */ - depth = GetImageChannelDepth(image, AllChannels, &image->exception); - im->BandFmt = -1; - if (depth >= 1 && depth <= 8) - im->BandFmt = VIPS_FORMAT_UCHAR; - if (depth >= 9 && depth <= 16) - im->BandFmt = VIPS_FORMAT_USHORT; -#ifdef UseHDRI - if (depth == 32) - im->BandFmt = VIPS_FORMAT_FLOAT; - if (depth == 64) - im->BandFmt = VIPS_FORMAT_DOUBLE; -#else /*!UseHDRI*/ - if (depth == 32) - im->BandFmt = VIPS_FORMAT_UINT; -#endif /*UseHDRI*/ - - if (im->BandFmt == -1) { - vips_error("magick2vips", _("unsupported bit depth %d"), - (int) depth); - return -1; - } - - switch (image->units) { - case PixelsPerInchResolution: - im->Xres = image->x_resolution / 25.4; - im->Yres = image->y_resolution / 25.4; - break; - - case PixelsPerCentimeterResolution: - im->Xres = image->x_resolution / 10.0; - im->Yres = image->y_resolution / 10.0; - break; - - default: - im->Xres = 1.0; - im->Yres = 1.0; - break; - } - - // this can be wrong for some GM versions and must be sanity checked (see - // below) - switch (image->colorspace) { - case GRAYColorspace: - if (im->BandFmt == VIPS_FORMAT_USHORT) - im->Type = VIPS_INTERPRETATION_GREY16; - else - im->Type = VIPS_INTERPRETATION_B_W; - break; - - case sRGBColorspace: - case RGBColorspace: - if (im->BandFmt == VIPS_FORMAT_USHORT) - im->Type = VIPS_INTERPRETATION_RGB16; - else - im->Type = VIPS_INTERPRETATION_sRGB; - break; - - case CMYKColorspace: - im->Type = VIPS_INTERPRETATION_CMYK; - break; - - default: - im->Type = VIPS_INTERPRETATION_ERROR; - break; - } - - // revise the interpretation if it seems crazy - im->Type = vips_image_guess_interpretation(im); - - if (vips_image_pipelinev(im, VIPS_DEMAND_STYLE_SMALLTILE, NULL)) - return -1; - - /* Set vips metadata from ImageMagick profiles. - */ - if (magick_set_vips_profile(im, image)) - return -1; - -#ifdef HAVE_RESETIMAGEPROPERTYITERATOR - { - char *key; - - /* This is the most recent imagemagick API, test for this first. - */ - ResetImagePropertyIterator(image); - while ((key = GetNextImageProperty(image))) { - char name_text[256]; - VipsBuf name = VIPS_BUF_STATIC(name_text); - - vips_buf_appendf(&name, "magick-%s", key); - vips_image_set_string(im, - vips_buf_all(&name), GetImageProperty(image, key)); - } - } -#elif defined(HAVE_RESETIMAGEATTRIBUTEITERATOR) - { - const ImageAttribute *attr; - - /* magick6.1-ish and later, deprecated in 6.5ish. - */ - ResetImageAttributeIterator(image); - while ((attr = GetNextImageAttribute(image))) { - char name_text[256]; - VipsBuf name = VIPS_BUF_STATIC(name_text); - - vips_buf_appendf(&name, "magick-%s", attr->key); - vips_image_set_string(im, vips_buf_all(&name), attr->value); - } - } -#else - { - const ImageAttribute *attr; - - /* GraphicsMagick is missing the iterator: we have to loop ourselves. - * ->attributes is marked as private in the header, but there's no - * getter so we have to access it directly. - */ - for (attr = image->attributes; attr; attr = attr->next) { - char name_text[256]; - VipsBuf name = VIPS_BUF_STATIC(name_text); - - vips_buf_appendf(&name, "magick-%s", attr->key); - vips_image_set_string(im, vips_buf_all(&name), attr->value); - } - } -#endif - - /* Something like "BMP". - */ - if (strlen(read->image->magick) > 0) - vips_image_set_string(im, "magick-format", - read->image->magick); - - /* Do we have a set of equal-sized frames? Append them. - - FIXME ... there must be an attribute somewhere from dicom read - which says this is a volumetric image - - */ - read->n_pages = GetImageListLength(image); - read->n_frames = 0; - for (p = image; p; (p = GetNextImageInList(p))) { - int p_depth = - GetImageChannelDepth(p, AllChannels, &p->exception); - - if (p->columns != (unsigned int) im->Xsize || - p->rows != (unsigned int) im->Ysize || - get_bands(p) != im->Bands || - p_depth != depth) { -#ifdef DEBUG - printf("frame %d differs\n", read->n_frames); - printf("%zdx%zd, %d bands\n", - p->columns, p->rows, get_bands(p)); - printf("first frame is %dx%d, %d bands\n", - im->Xsize, im->Ysize, im->Bands); -#endif /*DEBUG*/ - - break; - } - - read->n_frames += 1; - } - if (p) - /* Nope ... just do the first image in the list. - */ - read->n_frames = 1; - -#ifdef DEBUG - printf("will read %d frames\n", read->n_frames); -#endif /*DEBUG*/ - - if (read->n != -1) - read->n_frames = VIPS_MIN(read->n_frames, read->n); - - /* Record frame pointers. - */ - if (!(read->frames = VIPS_ARRAY(NULL, read->n_frames, Image *))) - return -1; - p = image; - for (i = 0; i < read->n_frames; i++) { - read->frames[i] = p; - p = GetNextImageInList(p); - } - - if (read->n_frames > 1) { - vips_image_set_int(im, VIPS_META_PAGE_HEIGHT, im->Ysize); - im->Ysize *= read->n_frames; - } - - vips_image_set_int(im, VIPS_META_N_PAGES, read->n_pages); - - vips_image_set_int(im, VIPS_META_ORIENTATION, - VIPS_CLIP(1, image->orientation, 8)); - - vips_image_set_int(im, VIPS_META_BITS_PER_SAMPLE, depth); - - return 0; -} - -/* Divide by this to get 0 - MAX from a Quantum. Eg. consider QuantumRange == - * 65535, MAX == 255 (a Q16 ImageMagic representing an 8-bit image). Make sure - * this can't be zero (if QuantumRange < MAX) .. can happen if we have a Q8 - * ImageMagick trying to represent a 16-bit image. - */ -#define SCALE(MAX) \ - (QuantumRange < (MAX) \ - ? 1 \ - : ((QuantumRange + 1) / ((MAX) + 1))) - -#define GRAY_LOOP(TYPE, MAX) \ - { \ - TYPE *q = (TYPE *) q8; \ -\ - for (x = 0; x < n; x++) \ - q[x] = pixels[x].green / SCALE(MAX); \ - } - -#define GRAYA_LOOP(TYPE, MAX) \ - { \ - TYPE *q = (TYPE *) q8; \ -\ - for (x = 0; x < n; x++) { \ - q[0] = pixels[x].green / SCALE(MAX); \ - q[1] = MAX - pixels[x].opacity / SCALE(MAX); \ -\ - q += 2; \ - } \ - } - -#define RGB_LOOP(TYPE, MAX) \ - { \ - TYPE *q = (TYPE *) q8; \ -\ - for (x = 0; x < n; x++) { \ - q[0] = pixels[x].red / SCALE(MAX); \ - q[1] = pixels[x].green / SCALE(MAX); \ - q[2] = pixels[x].blue / SCALE(MAX); \ -\ - q += 3; \ - } \ - } - -#define RGBA_LOOP(TYPE, MAX) \ - { \ - TYPE *q = (TYPE *) q8; \ -\ - for (x = 0; x < n; x++) { \ - q[0] = pixels[x].red / SCALE(MAX); \ - q[1] = pixels[x].green / SCALE(MAX); \ - q[2] = pixels[x].blue / SCALE(MAX); \ - q[3] = MAX - pixels[x].opacity / SCALE(MAX); \ -\ - q += 4; \ - } \ - } - -static void -unpack_pixels(VipsImage *im, VipsPel *q8, PixelPacket *pixels, int n) -{ - int x; - - switch (im->Bands) { - case 1: - /* Gray. - */ - switch (im->BandFmt) { - case VIPS_FORMAT_UCHAR: - GRAY_LOOP(unsigned char, 255); - break; - case VIPS_FORMAT_USHORT: - GRAY_LOOP(unsigned short, 65535); - break; - case VIPS_FORMAT_UINT: - GRAY_LOOP(unsigned int, 4294967295UL); - break; - case VIPS_FORMAT_DOUBLE: - GRAY_LOOP(double, QuantumRange); - break; - - default: - g_assert_not_reached(); - } - break; - - case 2: - /* Gray plus alpha. - */ - switch (im->BandFmt) { - case VIPS_FORMAT_UCHAR: - GRAYA_LOOP(unsigned char, 255); - break; - case VIPS_FORMAT_USHORT: - GRAYA_LOOP(unsigned short, 65535); - break; - case VIPS_FORMAT_UINT: - GRAYA_LOOP(unsigned int, 4294967295UL); - break; - case VIPS_FORMAT_DOUBLE: - GRAYA_LOOP(double, QuantumRange); - break; - - default: - g_assert_not_reached(); - } - break; - - case 3: - /* RGB. - */ - switch (im->BandFmt) { - case VIPS_FORMAT_UCHAR: - RGB_LOOP(unsigned char, 255); - break; - case VIPS_FORMAT_USHORT: - RGB_LOOP(unsigned short, 65535); - break; - case VIPS_FORMAT_UINT: - RGB_LOOP(unsigned int, 4294967295UL); - break; - case VIPS_FORMAT_DOUBLE: - RGB_LOOP(double, QuantumRange); - break; - - default: - g_assert_not_reached(); - } - break; - - case 4: - /* RGBA or CMYK. - */ - switch (im->BandFmt) { - case VIPS_FORMAT_UCHAR: - RGBA_LOOP(unsigned char, 255); - break; - case VIPS_FORMAT_USHORT: - RGBA_LOOP(unsigned short, 65535); - break; - case VIPS_FORMAT_UINT: - RGBA_LOOP(unsigned int, 4294967295UL); - break; - case VIPS_FORMAT_DOUBLE: - RGBA_LOOP(double, QuantumRange); - break; - - default: - g_assert_not_reached(); - } - break; - - default: - g_assert_not_reached(); - } -} - -static PixelPacket * -get_pixels(Image *image, int left, int top, int width, int height) -{ - PixelPacket *pixels; - -#ifdef HAVE_GETVIRTUALPIXELS - if (!(pixels = (PixelPacket *) GetVirtualPixels(image, - left, top, width, height, &image->exception))) -#else - if (!(pixels = GetImagePixels(image, left, top, width, height))) -#endif - return NULL; - -/* Can't happen if red/green/blue are doubles. - */ -#ifndef UseHDRI - /* Unpack palette. - */ - if (image->storage_class == PseudoClass) { -#ifdef HAVE_GETVIRTUALPIXELS - IndexPacket *indexes = (IndexPacket *) - GetVirtualIndexQueue(image); -#else - /* Was GetIndexes(), but that's now deprecated. - */ - IndexPacket *indexes = AccessMutableIndexes(image); -#endif - - int i; - - for (i = 0; i < width * height; i++) { - IndexPacket x = indexes[i]; - - if (x < image->colors) { - pixels[i].red = image->colormap[x].red; - pixels[i].green = image->colormap[x].green; - pixels[i].blue = image->colormap[x].blue; - } - } - } -#endif /*UseHDRI*/ - - return pixels; -} - -static int -magick_fill_region(VipsRegion *out, - void *seq, void *a, void *b, gboolean *stop) -{ - Read *read = (Read *) a; - VipsRect *r = &out->valid; - int y; - - for (y = 0; y < r->height; y++) { - int top = r->top + y; - int frame = top / read->frame_height; - int line = top % read->frame_height; - - PixelPacket *pixels; - - vips__worker_lock(read->lock); - - pixels = get_pixels(read->frames[frame], - r->left, line, r->width, 1); - - g_mutex_unlock(read->lock); - - if (!pixels) { - vips_foreign_load_invalidate(read->im); - vips_error("magick2vips", - "%s", _("unable to read pixels")); - return -1; - } - - unpack_pixels(read->im, VIPS_REGION_ADDR(out, r->left, top), - pixels, r->width); - } - - return 0; -} - -int -vips__magick_read(const char *filename, - VipsImage *out, const char *density, int page, int n) -{ - Read *read; - -#ifdef DEBUG - printf("magick2vips: vips__magick_read: %s\n", filename); -#endif /*DEBUG*/ - - if (!(read = read_new(filename, out, NULL, n, density, page, n))) - return -1; - -#ifdef DEBUG - printf("magick2vips: calling ReadImage() ...\n"); -#endif /*DEBUG*/ - - read->image = ReadImage(read->image_info, read->exception); - if (!read->image) { - magick_vips_error("magick2vips", read->exception); - vips_error("magick2vips", - _("unable to read file \"%s\""), filename); - return -1; - } - - if (parse_header(read)) - return -1; - if (vips_image_generate(out, - NULL, magick_fill_region, NULL, read, NULL)) - return -1; - - return 0; -} - -int -vips__magick_read_header(const char *filename, - VipsImage *out, const char *density, int page, int n) -{ - Read *read; - -#ifdef DEBUG - printf("vips__magick_read_header: %s\n", filename); -#endif /*DEBUG*/ - - if (!(read = read_new(filename, out, NULL, 0, density, page, n))) - return -1; - -#ifdef DEBUG - printf("vips__magick_read_header: reading image ...\n"); -#endif /*DEBUG*/ - - /* It would be great if we could PingImage and just read the header, - * but sadly many IM coders do not support ping. The critical one for - * us is DICOM. TGA also has issues. - */ - read->image = ReadImage(read->image_info, read->exception); - if (!read->image) { - magick_vips_error("magick2vips", read->exception); - vips_error("magick2vips", - _("unable to read file \"%s\""), filename); - return -1; - } - - if (parse_header(read)) - return -1; - - if (out->Xsize <= 0 || - out->Ysize <= 0) { - vips_error("magick2vips", "%s", _("bad image size")); - return -1; - } - - /* Just a header read: we can free the read early and save an fd. - */ - read_free(read); - - return 0; -} - -int -vips__magick_read_buffer(const void *buf, const size_t len, - VipsImage *out, const char *density, int page, int n) -{ - Read *read; - -#ifdef DEBUG - printf("magick2vips: vips__magick_read_buffer: %p %zu\n", buf, len); -#endif /*DEBUG*/ - - if (!(read = read_new(NULL, out, buf, len, density, page, n))) - return -1; - -#ifdef DEBUG - printf("magick2vips: calling BlobToImage() ...\n"); -#endif /*DEBUG*/ - - read->image = BlobToImage(read->image_info, - buf, len, read->exception); - if (!read->image) { - magick_vips_error("magick2vips", read->exception); - vips_error("magick2vips", "%s", _("unable to read buffer")); - return -1; - } - - if (parse_header(read)) - return -1; - if (vips_image_generate(out, - NULL, magick_fill_region, NULL, read, NULL)) - return -1; - - return 0; -} - -int -vips__magick_read_buffer_header(const void *buf, const size_t len, - VipsImage *out, const char *density, int page, int n) -{ - Read *read; - -#ifdef DEBUG - printf("vips__magick_read_buffer_header: %p %zu\n", buf, len); -#endif /*DEBUG*/ - - if (!(read = read_new(NULL, out, buf, len, density, page, n))) - return -1; - -#ifdef DEBUG - printf("vips__magick_read_buffer_header: pinging blob ...\n"); -#endif /*DEBUG*/ - - /* It would be great if we could PingBlob and just read the header, - * but sadly many IM coders do not support ping well. The critical one - * for us is DICOM. TGA also has issues. - */ - read->image = BlobToImage(read->image_info, - buf, len, read->exception); - if (!read->image) { - magick_vips_error("magick2vips", read->exception); - vips_error("magick2vips", "%s", _("unable to ping blob")); - return -1; - } - - if (parse_header(read)) - return -1; - - if (out->Xsize <= 0 || - out->Ysize <= 0) { - vips_error("magick2vips", "%s", _("bad image size")); - return -1; - } - - return 0; -} - -#endif /*HAVE_MAGICK6*/ - -#endif /*ENABLE_MAGICKLOAD*/ diff --git a/libvips/foreign/magick6load.c b/libvips/foreign/magick6load.c index 98177d4eb5..cd3ac4eba1 100644 --- a/libvips/foreign/magick6load.c +++ b/libvips/foreign/magick6load.c @@ -1,19 +1,83 @@ /* load with libMagick * - * 5/12/11 - * - from openslideload.c + * 7/1/03 JC + * - from im_tiff2vips + * 3/2/03 JC + * - some InitializeMagick() fail with NULL arg + * 2/11/04 + * - im_magick2vips_header() also checks sensible width/height + * 28/10/05 + * - copy attributes to meta + * - write many-frame images as a big column if all frames have identical + * width/height/bands/depth + * 31/3/06 + * - test for magick attr support + * 8/5/06 + * - set RGB16/GREY16 if appropriate + * 10/8/07 + * - support 32/64 bit imagemagick too + * 21/2/08 + * - use MaxRGB if QuantumRange is missing (thanks Bob) + * - look for MAGICKCORE_HDRI_SUPPORT (thanks Marcel) + * - use image->attributes if GetNextImageAttribute() is missing + * 3/3/09 + * - allow funky bit depths, like 14 (thanks Mikkel) + * 17/3/09 + * - reset dcm:display-range to help DICOM read + * 20/4/09 + * - argh libMagick uses 255 == transparent ... we must invert all + * alpha channels + * 12/5/09 + * - fix signed/unsigned warnings + * 23/7/09 + * - SetImageOption() is optional (to help GM) + * 4/2/10 + * - gtkdoc + * 30/4/10 + * - better number of bands detection with GetImageType() + * - use new API stuff, argh + * 17/12/11 + * - turn into a set of read fns ready to be called from a class * 17/1/12 * - remove header-only loads * 11/6/13 * - add @all_frames option, off by default + * 4/12/14 Lovell + * - add @density option + * 16/2/15 mcuelenaere + * - add blob read + * 26/2/15 + * - close the read down early for a header read ... this saves an + * fd during file read, handy for large numbers of input images * 14/2/16 * - add @page option, 0 by default + * 18/4/16 + * - fix @page with graphicsmagick * 25/11/16 * - add @n, deprecate @all_frames (just sets n = -1) + * 23/2/17 + * - try using GetImageChannelDepth() instead of ->depth * 8/9/17 * - don't cache magickload + * 25/5/18 + * - don't use Ping, it's too unreliable + * 24/7/18 + * - sniff extra filetypes + * 4/1/19 kleisauke + * - we did not chain exceptions correctly, causing a memory leak + * - added wrapper funcs for exception handling + * 4/2/19 + * - add profile (xmp, ipct, etc.) read * 21/4/21 kleisauke * - include GObject part from magickload.c + * 12/11/21 + * - set "orientation" + * 26/8/22 + * - set "magick-format" + * 13/3/23 MathemanFlo + * - add bits per sample metadata + * 08/11/24 kleisauke + * - merge with magick2vips.c */ /* @@ -55,6 +119,7 @@ #include #include #include +#include #include #include @@ -64,9 +129,23 @@ #ifdef HAVE_MAGICK6 +#include + #include "pforeign.h" #include "magick.h" +/* pre-float Magick used to call this MaxRGB. + */ +#if !defined(QuantumRange) +#define QuantumRange MaxRGB +#endif + +/* And this used to be UseHDRI. + */ +#if MAGICKCORE_HDRI_SUPPORT +#define UseHDRI 1 +#endif + typedef struct _VipsForeignLoadMagick { VipsForeignLoad parent_object; @@ -78,6 +157,22 @@ typedef struct _VipsForeignLoadMagick { int page; /* Load this page (frame) */ int n; /* Load this many pages */ + Image *image; + ImageInfo *image_info; + ExceptionInfo *exception; + + /* Number of pages in image. + */ + int n_pages; + + int n_frames; /* Number of frames we will read */ + Image **frames; /* An Image* for each frame */ + int frame_height; + + /* Mutex to serialise calls to libMagick during threaded read. + */ + GMutex lock; + } VipsForeignLoadMagick; typedef VipsForeignLoadClass VipsForeignLoadMagickClass; @@ -97,6 +192,72 @@ vips_foreign_load_magick_get_flags(VipsForeignLoad *load) return VIPS_FOREIGN_PARTIAL; } +static void +vips_foreign_load_magick_finalize(GObject *gobject) +{ + VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) gobject; + +#ifdef DEBUG + printf("vips_foreign_load_magick_finalize: %p\n", gobject); +#endif /*DEBUG*/ + + VIPS_FREEF(DestroyImageList, magick->image); + VIPS_FREEF(DestroyImageInfo, magick->image_info); + VIPS_FREE(magick->frames); + VIPS_FREEF(magick_destroy_exception, magick->exception); + g_mutex_clear(&magick->lock); + + G_OBJECT_CLASS(vips_foreign_load_magick_parent_class)->finalize(gobject); +} + +static int +vips_foreign_load_magick_build(VipsObject *object) +{ + VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) object; + +#ifdef DEBUG + printf("vips_foreign_load_magick_build: %p\n", object); +#endif /*DEBUG*/ + + magick_genesis(); + + magick->image_info = CloneImageInfo(NULL); + magick->exception = magick_acquire_exception(); + + if (!magick->image_info) + return -1; + + if (magick->all_frames) + magick->n = -1; + + /* IM doesn't use the -1 means end-of-file convention, change it to a + * very large number. + */ + if (magick->n == -1) + magick->n = 10000000; + + /* Canvas resolution for rendering vector formats like SVG. + */ + VIPS_SETSTR(magick->image_info->density, magick->density); + + /* When reading DICOM images, we want to ignore any + * window_center/_width setting, since it may put pixels outside the + * 0-65535 range and lose data. + * + * These window settings are attached as vips metadata, so our caller + * can interpret them if it wants. + */ + magick_set_image_option(magick->image_info, "dcm:display-range", "reset"); + + if (magick->page > 0) + magick_set_number_scenes(magick->image_info, magick->page, magick->n); + + if (VIPS_OBJECT_CLASS(vips_foreign_load_magick_parent_class)->build(object)) + return -1; + + return 0; +} + static void vips_foreign_load_magick_class_init(VipsForeignLoadMagickClass *class) { @@ -106,11 +267,13 @@ vips_foreign_load_magick_class_init(VipsForeignLoadMagickClass *class) VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; + gobject_class->finalize = vips_foreign_load_magick_finalize; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; object_class->nickname = "magickload_base"; object_class->description = _("load with ImageMagick"); + object_class->build = vips_foreign_load_magick_build; /* Don't cache magickload: it can gobble up memory and disc. */ @@ -163,6 +326,573 @@ static void vips_foreign_load_magick_init(VipsForeignLoadMagick *magick) { magick->n = 1; + g_mutex_init(&magick->lock); +} + +static int +magick_get_bands(Image *image) +{ + int bands; + ImageType type = GetImageType(image, &image->exception); + + switch (type) { + case BilevelType: + case GrayscaleType: + bands = 1; + break; + + case GrayscaleMatteType: + /* ImageMagick also has PaletteBilevelMatteType, but GraphicsMagick + * does not. Skip for portability. + */ + bands = 2; + break; + + case PaletteType: + case TrueColorType: + bands = 3; + break; + + case PaletteMatteType: + case TrueColorMatteType: + case ColorSeparationType: + bands = 4; + break; + + case ColorSeparationMatteType: + bands = 5; + break; + + default: + vips_error("magick2vips", _("unsupported image type %d"), + (int) type); + return -1; + } + + return bands; +} + +static int +vips_foreign_load_magick_parse(VipsForeignLoadMagick *magick, + Image *image, VipsImage *out) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(magick); + + int depth; + Image *p; + +#ifdef DEBUG + printf("GetImageChannelDepth(AllChannels) = %zd\n", + GetImageChannelDepth(image, AllChannels, &image->exception)); + printf("GetImageDepth() = %zd\n", + GetImageDepth(image, &image->exception)); + printf("image->depth = %zd\n", image->depth); + printf("GetImageType() = %d\n", + GetImageType(image, &image->exception)); + printf("IsGrayImage() = %d\n", + IsGrayImage(image, &image->exception)); + printf("IsMonochromeImage() = %d\n", + IsMonochromeImage(image, &image->exception)); + printf("IsOpaqueImage() = %d\n", + IsOpaqueImage(image, &image->exception)); + printf("image->columns = %zd\n", image->columns); + printf("image->rows = %zd\n", image->rows); +#endif /*DEBUG*/ + + /* Ysize updated below once we have worked out how many frames to load. + */ + out->Coding = VIPS_CODING_NONE; + out->Xsize = image->columns; + out->Ysize = image->rows; + magick->frame_height = image->rows; + out->Bands = magick_get_bands(image); + if (out->Xsize <= 0 || + out->Ysize <= 0 || + out->Bands <= 0 || + out->Xsize >= VIPS_MAX_COORD || + out->Ysize >= VIPS_MAX_COORD || + out->Bands >= VIPS_MAX_COORD) { + vips_error(class->nickname, + _("bad image dimensions %d x %d pixels, %d bands"), + out->Xsize, out->Ysize, out->Bands); + return -1; + } + + /* Depth can be 'fractional'. You'd think we should use + * GetImageDepth() but that seems unreliable. 16-bit mono DICOM images + * are reported as depth 1, for example. + * + * Try GetImageChannelDepth(), maybe that works. + */ + depth = GetImageChannelDepth(image, AllChannels, &image->exception); + + out->BandFmt = -1; + if (depth >= 1 && depth <= 8) + out->BandFmt = VIPS_FORMAT_UCHAR; + if (depth >= 9 && depth <= 16) + out->BandFmt = VIPS_FORMAT_USHORT; +#ifdef UseHDRI + if (depth == 32) + out->BandFmt = VIPS_FORMAT_FLOAT; + if (depth == 64) + out->BandFmt = VIPS_FORMAT_DOUBLE; +#else /*!UseHDRI*/ + if (depth == 32) + out->BandFmt = VIPS_FORMAT_UINT; +#endif /*UseHDRI*/ + + if (out->BandFmt == -1) { + vips_error(class->nickname, + _("unsupported bit depth %d"), depth); + return -1; + } + + switch (image->units) { + case PixelsPerInchResolution: + out->Xres = image->x_resolution / 25.4; + out->Yres = image->y_resolution / 25.4; + vips_image_set_string(out, VIPS_META_RESOLUTION_UNIT, "in"); + break; + + case PixelsPerCentimeterResolution: + out->Xres = image->x_resolution / 10.0; + out->Yres = image->y_resolution / 10.0; + vips_image_set_string(out, VIPS_META_RESOLUTION_UNIT, "cm"); + break; + + default: + /* Things like GIF have no resolution info. + */ + out->Xres = 1.0; + out->Yres = 1.0; + break; + } + + // this can be wrong for some GM versions and must be sanity checked (see + // below) + switch (image->colorspace) { + case GRAYColorspace: + if (out->BandFmt == VIPS_FORMAT_USHORT) + out->Type = VIPS_INTERPRETATION_GREY16; + else + out->Type = VIPS_INTERPRETATION_B_W; + break; + + case sRGBColorspace: + case RGBColorspace: + if (out->BandFmt == VIPS_FORMAT_USHORT) + out->Type = VIPS_INTERPRETATION_RGB16; + else + out->Type = VIPS_INTERPRETATION_sRGB; + break; + + case CMYKColorspace: + out->Type = VIPS_INTERPRETATION_CMYK; + break; + + default: + out->Type = VIPS_INTERPRETATION_ERROR; + break; + } + + // revise the interpretation if it seems crazy + out->Type = vips_image_guess_interpretation(out); + + if (vips_image_pipelinev(out, VIPS_DEMAND_STYLE_SMALLTILE, NULL)) + return -1; + +#ifdef HAVE_RESETIMAGEPROPERTYITERATOR + { + char *key; + + /* This is the most recent imagemagick API, test for this first. + */ + ResetImagePropertyIterator(image); + while ((key = GetNextImageProperty(image))) { + char name_text[256]; + VipsBuf name = VIPS_BUF_STATIC(name_text); + + vips_buf_appendf(&name, "magick-%s", key); + vips_image_set_string(out, + vips_buf_all(&name), GetImageProperty(image, key)); + } + } +#elif defined(HAVE_RESETIMAGEATTRIBUTEITERATOR) + { + const ImageAttribute *attr; + + /* magick6.1-ish and later, deprecated in 6.5ish. + */ + ResetImageAttributeIterator(image); + while ((attr = GetNextImageAttribute(image))) { + char name_text[256]; + VipsBuf name = VIPS_BUF_STATIC(name_text); + + vips_buf_appendf(&name, "magick-%s", attr->key); + vips_image_set_string(out, vips_buf_all(&name), attr->value); + } + } +#else + { + const ImageAttribute *attr; + + /* GraphicsMagick is missing the iterator: we have to loop ourselves. + * ->attributes is marked as private in the header, but there's no + * getter so we have to access it directly. + */ + for (attr = image->attributes; attr; attr = attr->next) { + char name_text[256]; + VipsBuf name = VIPS_BUF_STATIC(name_text); + + vips_buf_appendf(&name, "magick-%s", attr->key); + vips_image_set_string(out, vips_buf_all(&name), attr->value); + } + } +#endif + + /* Set vips metadata from ImageMagick profiles. + */ + if (magick_set_vips_profile(out, image)) + return -1; + + /* Something like "BMP". + */ + if (strlen(magick->image->magick) > 0) + vips_image_set_string(out, "magick-format", + magick->image->magick); + + magick->n_pages = GetImageListLength(image); +#ifdef DEBUG + printf("image has %d pages\n", magick->n_pages); +#endif /*DEBUG*/ + + /* Do we have a set of equal-sized frames? Append them. + + FIXME ... there must be an attribute somewhere from dicom read + which says this is a volumetric image + + */ + magick->n_frames = 0; + + for (p = image; p; (p = GetNextImageInList(p))) { + int p_depth = + GetImageChannelDepth(p, AllChannels, &p->exception); + + if (p->columns != (unsigned int) out->Xsize || + p->rows != (unsigned int) out->Ysize || + magick_get_bands(p) != out->Bands || + p_depth != depth) { +#ifdef DEBUG + printf("frame %d differs\n", read->n_frames); + printf("%zdx%zd, %d bands\n", + p->columns, p->rows, get_bands(p)); + printf("first frame is %dx%d, %d bands\n", + im->Xsize, im->Ysize, im->Bands); +#endif /*DEBUG*/ + + break; + } + + magick->n_frames += 1; + } + if (p) + /* Nope ... just do the first image in the list. + */ + magick->n_frames = 1; + +#ifdef DEBUG + printf("will read %d frames\n", magick->n_frames); +#endif /*DEBUG*/ + + if (magick->n != -1) + magick->n_frames = VIPS_MIN(magick->n_frames, magick->n); + + /* So we can finally set the height. + */ + if (magick->n_frames > 1) { + vips_image_set_int(out, VIPS_META_PAGE_HEIGHT, out->Ysize); + out->Ysize *= magick->n_frames; + } + + vips_image_set_int(out, VIPS_META_N_PAGES, magick->n_pages); + + vips_image_set_int(out, VIPS_META_ORIENTATION, + VIPS_CLIP(1, image->orientation, 8)); + + vips_image_set_int(out, VIPS_META_BITS_PER_SAMPLE, depth); + + return 0; +} + +/* Divide by this to get 0 - MAX from a Quantum. Eg. consider QuantumRange == + * 65535, MAX == 255 (a Q16 ImageMagic representing an 8-bit image). Make sure + * this can't be zero (if QuantumRange < MAX) .. can happen if we have a Q8 + * ImageMagick trying to represent a 16-bit image. + */ +#define SCALE(MAX) \ + (QuantumRange < (MAX) \ + ? 1 \ + : ((QuantumRange + 1) / ((MAX) + 1))) + +#define GRAY_LOOP(TYPE, MAX) \ + { \ + TYPE *q = (TYPE *) q8; \ +\ + for (x = 0; x < n; x++) \ + q[x] = pixels[x].green / SCALE(MAX); \ + } + +#define GRAYA_LOOP(TYPE, MAX) \ + { \ + TYPE *q = (TYPE *) q8; \ +\ + for (x = 0; x < n; x++) { \ + q[0] = pixels[x].green / SCALE(MAX); \ + q[1] = MAX - pixels[x].opacity / SCALE(MAX); \ +\ + q += 2; \ + } \ + } + +#define RGB_LOOP(TYPE, MAX) \ + { \ + TYPE *q = (TYPE *) q8; \ +\ + for (x = 0; x < n; x++) { \ + q[0] = pixels[x].red / SCALE(MAX); \ + q[1] = pixels[x].green / SCALE(MAX); \ + q[2] = pixels[x].blue / SCALE(MAX); \ +\ + q += 3; \ + } \ + } + +#define RGBA_LOOP(TYPE, MAX) \ + { \ + TYPE *q = (TYPE *) q8; \ +\ + for (x = 0; x < n; x++) { \ + q[0] = pixels[x].red / SCALE(MAX); \ + q[1] = pixels[x].green / SCALE(MAX); \ + q[2] = pixels[x].blue / SCALE(MAX); \ + q[3] = MAX - pixels[x].opacity / SCALE(MAX); \ +\ + q += 4; \ + } \ + } + +static void +unpack_pixels(VipsImage *im, VipsPel *q8, PixelPacket *pixels, int n) +{ + int x; + + switch (im->Bands) { + case 1: + /* Gray. + */ + switch (im->BandFmt) { + case VIPS_FORMAT_UCHAR: + GRAY_LOOP(unsigned char, 255); + break; + case VIPS_FORMAT_USHORT: + GRAY_LOOP(unsigned short, 65535); + break; + case VIPS_FORMAT_UINT: + GRAY_LOOP(unsigned int, 4294967295UL); + break; + case VIPS_FORMAT_DOUBLE: + GRAY_LOOP(double, QuantumRange); + break; + + default: + g_assert_not_reached(); + } + break; + + case 2: + /* Gray plus alpha. + */ + switch (im->BandFmt) { + case VIPS_FORMAT_UCHAR: + GRAYA_LOOP(unsigned char, 255); + break; + case VIPS_FORMAT_USHORT: + GRAYA_LOOP(unsigned short, 65535); + break; + case VIPS_FORMAT_UINT: + GRAYA_LOOP(unsigned int, 4294967295UL); + break; + case VIPS_FORMAT_DOUBLE: + GRAYA_LOOP(double, QuantumRange); + break; + + default: + g_assert_not_reached(); + } + break; + + case 3: + /* RGB. + */ + switch (im->BandFmt) { + case VIPS_FORMAT_UCHAR: + RGB_LOOP(unsigned char, 255); + break; + case VIPS_FORMAT_USHORT: + RGB_LOOP(unsigned short, 65535); + break; + case VIPS_FORMAT_UINT: + RGB_LOOP(unsigned int, 4294967295UL); + break; + case VIPS_FORMAT_DOUBLE: + RGB_LOOP(double, QuantumRange); + break; + + default: + g_assert_not_reached(); + } + break; + + case 4: + /* RGBA or CMYK. + */ + switch (im->BandFmt) { + case VIPS_FORMAT_UCHAR: + RGBA_LOOP(unsigned char, 255); + break; + case VIPS_FORMAT_USHORT: + RGBA_LOOP(unsigned short, 65535); + break; + case VIPS_FORMAT_UINT: + RGBA_LOOP(unsigned int, 4294967295UL); + break; + case VIPS_FORMAT_DOUBLE: + RGBA_LOOP(double, QuantumRange); + break; + + default: + g_assert_not_reached(); + } + break; + + default: + g_assert_not_reached(); + } +} + +static PixelPacket * +get_pixels(Image *image, int left, int top, int width, int height) +{ + PixelPacket *pixels; + +#ifdef HAVE_GETVIRTUALPIXELS + if (!(pixels = (PixelPacket *) GetVirtualPixels(image, + left, top, width, height, &image->exception))) +#else + if (!(pixels = GetImagePixels(image, left, top, width, height))) +#endif + return NULL; + + /* Can't happen if red/green/blue are doubles. + */ +#ifndef UseHDRI + /* Unpack palette. + */ + if (image->storage_class == PseudoClass) { +#ifdef HAVE_GETVIRTUALPIXELS + IndexPacket *indexes = (IndexPacket *) + GetVirtualIndexQueue(image); +#else + /* Was GetIndexes(), but that's now deprecated. + */ + IndexPacket *indexes = AccessMutableIndexes(image); +#endif + + int i; + + for (i = 0; i < width * height; i++) { + IndexPacket x = indexes[i]; + + if (x < image->colors) { + pixels[i].red = image->colormap[x].red; + pixels[i].green = image->colormap[x].green; + pixels[i].blue = image->colormap[x].blue; + } + } + } +#endif /*UseHDRI*/ + + return pixels; +} + +static int +vips_foreign_load_magick_fill_region(VipsRegion *out_region, + void *seq, void *a, void *b, gboolean *stop) +{ + VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) a; + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(magick); + VipsRect *r = &out_region->valid; + VipsImage *im = out_region->im; + + int y; + + for (y = 0; y < r->height; y++) { + int top = r->top + y; + int frame = top / magick->frame_height; + int line = top % magick->frame_height; + + PixelPacket *pixels; + + vips__worker_lock(&magick->lock); + + pixels = get_pixels(magick->frames[frame], r->left, line, r->width, 1); + + g_mutex_unlock(&magick->lock); + + if (!pixels) { + vips_foreign_load_invalidate(im); + vips_error(class->nickname, "%s", _("unable to read pixels")); + return -1; + } + + unpack_pixels(im, VIPS_REGION_ADDR(out_region, r->left, top), + pixels, r->width); + } + + return 0; +} + +static int +vips_foreign_load_magick_load(VipsForeignLoadMagick *magick) +{ + VipsForeignLoad *load = (VipsForeignLoad *) magick; + + Image *p; + +#ifdef DEBUG + printf("vips_foreign_load_magick_load: %p\n", magick); +#endif /*DEBUG*/ + + if (vips_foreign_load_magick_parse(magick, magick->image, load->out)) + return -1; + + /* Record frame pointers. + */ + g_assert(!magick->frames); + if (!(magick->frames = VIPS_ARRAY(NULL, magick->n_frames, Image *))) + return -1; + p = magick->image; + for (int i = 0; i < magick->n_frames; i++) { + magick->frames[i] = p; + p = GetNextImageInList(p); + } + + if (vips_image_generate(load->out, + NULL, vips_foreign_load_magick_fill_region, NULL, + magick, NULL)) + return -1; + + return 0; } typedef struct _VipsForeignLoadMagickFile { @@ -200,18 +930,30 @@ static int vips_foreign_load_magick_file_header(VipsForeignLoad *load) { VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) load; - VipsForeignLoadMagickFile *magick_file = - (VipsForeignLoadMagickFile *) load; + VipsForeignLoadMagickFile *file = (VipsForeignLoadMagickFile *) load; + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(magick); - if (magick->all_frames) - magick->n = -1; +#ifdef DEBUG + printf("vips_foreign_load_magick_file_header: %p\n", load); +#endif /*DEBUG*/ + + g_strlcpy(magick->image_info->filename, file->filename, + MaxTextExtent); + + magick_sniff_file(magick->image_info, file->filename); - if (vips__magick_read(magick_file->filename, - load->out, magick->density, - magick->page, magick->n)) + magick->image = ReadImage(magick->image_info, magick->exception); + if (!magick->image) { + magick_vips_error(class->nickname, magick->exception); + vips_error(class->nickname, + _("unable to read file \"%s\""), file->filename); return -1; + } - VIPS_SETSTR(load->out->filename, magick_file->filename); + if (vips_foreign_load_magick_load(magick)) + return -1; + + VIPS_SETSTR(load->out->filename, file->filename); return 0; } @@ -232,7 +974,6 @@ vips_foreign_load_magick_file_class_init( load_class->is_a = ismagick; load_class->header = vips_foreign_load_magick_file_header; - load_class->load = NULL; VIPS_ARG_STRING(class, "filename", 1, _("Filename"), @@ -278,14 +1019,28 @@ vips_foreign_load_magick_buffer_header(VipsForeignLoad *load) VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) load; VipsForeignLoadMagickBuffer *magick_buffer = (VipsForeignLoadMagickBuffer *) load; + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(magick); - if (magick->all_frames) - magick->n = -1; +#ifdef DEBUG + printf("vips_foreign_load_magick_buffer_header: %p\n", load); +#endif /*DEBUG*/ + + /* It would be great if we could PingImage and just read the header, + * but sadly many IM coders do not support ping. The critical one for + * us is DICOM. TGA also has issues. + */ + magick_sniff_bytes(magick->image_info, + magick_buffer->buf->data, magick_buffer->buf->length); + magick->image = BlobToImage(magick->image_info, + magick_buffer->buf->data, magick_buffer->buf->length, + magick->exception); + if (!magick->image) { + magick_vips_error(class->nickname, magick->exception); + vips_error(class->nickname, _("unable to read buffer")); + return -1; + } - if (vips__magick_read_buffer( - magick_buffer->buf->data, magick_buffer->buf->length, - load->out, magick->density, magick->page, - magick->n)) + if (vips_foreign_load_magick_load(magick)) return -1; return 0; @@ -307,7 +1062,6 @@ vips_foreign_load_magick_buffer_class_init( load_class->is_a_buffer = vips_foreign_load_magick_buffer_is_a_buffer; load_class->header = vips_foreign_load_magick_buffer_header; - load_class->load = NULL; VIPS_ARG_BOXED(class, "buffer", 1, _("Buffer"), diff --git a/libvips/foreign/magick7load.c b/libvips/foreign/magick7load.c index 45d2819258..62defc0a57 100644 --- a/libvips/foreign/magick7load.c +++ b/libvips/foreign/magick7load.c @@ -92,7 +92,7 @@ typedef struct _VipsForeignLoadMagick7 { /* Mutex to serialise calls to libMagick during threaded read. */ - GMutex *lock; + GMutex lock; } VipsForeignLoadMagick7; @@ -268,14 +268,14 @@ vips_foreign_load_magick7_get_flags(VipsForeignLoad *load) } static void -vips_foreign_load_magick7_dispose(GObject *gobject) +vips_foreign_load_magick7_finalize(GObject *gobject) { VipsForeignLoadMagick7 *magick7 = (VipsForeignLoadMagick7 *) gobject; int i; #ifdef DEBUG - printf("vips_foreign_load_magick7_dispose: %p\n", gobject); + printf("vips_foreign_load_magick7_finalize: %p\n", gobject); #endif /*DEBUG*/ for (i = 0; i < magick7->n_frames; i++) { @@ -286,9 +286,9 @@ vips_foreign_load_magick7_dispose(GObject *gobject) VIPS_FREE(magick7->frames); VIPS_FREE(magick7->cache_view); VIPS_FREEF(magick_destroy_exception, magick7->exception); - VIPS_FREEF(vips_g_mutex_free, magick7->lock); + g_mutex_clear(&magick7->lock); - G_OBJECT_CLASS(vips_foreign_load_magick7_parent_class)->dispose(gobject); + G_OBJECT_CLASS(vips_foreign_load_magick7_parent_class)->finalize(gobject); } static int @@ -304,7 +304,6 @@ vips_foreign_load_magick7_build(VipsObject *object) magick7->image_info = CloneImageInfo(NULL); magick7->exception = magick_acquire_exception(); - magick7->lock = vips_g_mutex_new(); if (!magick7->image_info) return -1; @@ -330,10 +329,8 @@ vips_foreign_load_magick7_build(VipsObject *object) magick_set_number_scenes(magick7->image_info, magick7->page, magick7->n); - if (VIPS_OBJECT_CLASS(vips_foreign_load_magick7_parent_class)->build(object)) - return -1; - - return 0; + return VIPS_OBJECT_CLASS(vips_foreign_load_magick7_parent_class)-> + build(object); } static void @@ -345,7 +342,7 @@ vips_foreign_load_magick7_class_init(VipsForeignLoadMagick7Class *class) VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; - gobject_class->dispose = vips_foreign_load_magick7_dispose; + gobject_class->finalize = vips_foreign_load_magick7_finalize; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -404,6 +401,7 @@ static void vips_foreign_load_magick7_init(VipsForeignLoadMagick7 *magick7) { magick7->n = 1; + g_mutex_init(&magick7->lock); } static void @@ -675,13 +673,13 @@ vips_foreign_load_magick7_fill_region(VipsRegion *out_region, Quantum *restrict p; VipsPel *restrict q; - vips__worker_lock(magick7->lock); + vips__worker_lock(&magick7->lock); p = GetCacheViewAuthenticPixels(magick7->cache_view[frame], r->left, line, r->width, 1, magick7->exception); - g_mutex_unlock(magick7->lock); + g_mutex_unlock(&magick7->lock); if (!p) /* This can happen if, for example, some frames of a diff --git a/libvips/foreign/magickload.c b/libvips/foreign/magickload.c index 48fc350a3e..f3bf49e852 100644 --- a/libvips/foreign/magickload.c +++ b/libvips/foreign/magickload.c @@ -64,17 +64,12 @@ * vips_magickload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Read in an image using libMagick, the ImageMagick library. * - * * @page: %gint, load from this page - * * @n: %gint, load this many pages - * * @density: string, canvas resolution for rendering vector formats like SVG - * - * Read in an image using libMagick, the ImageMagick library. This library can - * read more than 80 file formats, including SVG, BMP, EPS, DICOM and many - * others. + * This library can read more than 80 file formats, including BMP, EPS, + * DICOM and many others. * The reader can handle any ImageMagick image, including the float and double * formats. It will work with any quantum size, including HDR. Any metadata * attached to the libMagick image is copied on to the VIPS image. @@ -94,7 +89,14 @@ * docs](http://www.imagemagick.org/script/command-line-options.php#density) * on the imagemagick website. * - * See also: vips_image_new_from_file(). + * ::: tip "Optional arguments" + * * @page: `gint`, load from this page + * * @n: `gint`, load this many pages + * * @density: string, canvas resolution for rendering vector formats + * like SVG + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -116,21 +118,22 @@ vips_magickload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, load from this page - * * @n: %gint, load this many pages - * * @density: string, canvas resolution for rendering vector formats like SVG + * @...: `NULL`-terminated list of optional named arguments * * Read an image memory block using libMagick into a VIPS image. Exactly as - * vips_magickload(), but read from a memory source. + * [ctor@Image.magickload], but read from a memory source. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. + * + * ::: tip "Optional arguments" + * * @page: `gint`, load from this page + * * @n: `gint`, load this many pages + * * @density: string, canvas resolution for rendering vector formats + * like SVG * - * See also: vips_magickload(). + * ::: seealso + * [ctor@Image.magickload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/magicksave.c b/libvips/foreign/magicksave.c index f92bd55a38..b32a4cc04f 100644 --- a/libvips/foreign/magicksave.c +++ b/libvips/foreign/magicksave.c @@ -58,15 +58,7 @@ * vips_magicksave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @quality: %gint, quality factor - * * @format: %gchararray, format to save as - * * @optimize_gif_frames: %gboolean, apply GIF frames optimization - * * @optimize_gif_transparency: %gboolean, apply GIF transparency optimization - * * @bitdepth: %gint, number of bits per pixel + * @...: `NULL`-terminated list of optional named arguments * * Write an image using libMagick. * @@ -87,7 +79,16 @@ * @bitdepth specifies the number of bits per pixel. The image will be quantized * and dithered if the value is within the valid range (1 to 8). * - * See also: vips_magicksave_buffer(), vips_magickload(). + * ::: tip "Optional arguments" + * * @quality: `gint`, quality factor + * * @format: `gchararray`, format to save as + * * @optimize_gif_frames: `gboolean`, apply GIF frames optimization + * * @optimize_gif_transparency: `gboolean`, apply GIF transparency + * optimization + * * @bitdepth: `gint`, number of bits per pixel + * + * ::: seealso + * [method@Image.magicksave_buffer], [ctor@Image.magickload]. * * Returns: 0 on success, -1 on error. */ @@ -109,23 +110,24 @@ vips_magicksave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @quality: %gint, quality factor - * * @format: %gchararray, format to save as - * * @optimize_gif_frames: %gboolean, apply GIF frames optimization - * * @optimize_gif_transparency: %gboolean, apply GIF transparency optimization - * * @bitdepth: %gint, number of bits per pixel - * - * As vips_magicksave(), but save to a memory buffer. + * As [method@Image.magicksave], but save to a memory buffer. * * The address of the buffer is returned in @obuf, the length of the buffer in - * @olen. You are responsible for freeing the buffer with g_free() when you - * are done with it. - * - * See also: vips_magicksave(), vips_image_write_to_file(). + * @olen. You are responsible for freeing the buffer with [func@GLib.free] + * when you are done with it. + * + * ::: tip "Optional arguments" + * * @quality: `gint`, quality factor + * * @format: `gchararray`, format to save as + * * @optimize_gif_frames: `gboolean`, apply GIF frames optimization + * * @optimize_gif_transparency: `gboolean`, apply GIF transparency + * optimization + * * @bitdepth: `gint`, number of bits per pixel + * + * ::: seealso + * [method@Image.magicksave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/matload.c b/libvips/foreign/matload.c index 5e3a9898eb..c4f971dbce 100644 --- a/libvips/foreign/matload.c +++ b/libvips/foreign/matload.c @@ -153,7 +153,7 @@ vips_foreign_load_mat_init(VipsForeignLoadMat *mat) * vips_matload: * @filename: file to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Read a Matlab save file into a VIPS image. * @@ -162,7 +162,8 @@ vips_foreign_load_mat_init(VipsForeignLoadMat *mat) * it as an image. It will not handle complex images. It does not handle * sparse matrices. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/matrixload.c b/libvips/foreign/matrixload.c index 651e5e9bfe..7ef9c92543 100644 --- a/libvips/foreign/matrixload.c +++ b/libvips/foreign/matrixload.c @@ -119,13 +119,15 @@ parse_matrix_header(char *line, char *p, *q; int i; - for (i = 0, p = line; - (q = vips_break_token(p, " \t")) && - i < 4; - i++, p = q) + /* Stop at newline. + */ + if ((p = strchr(line, '\r')) || + ((p = strchr(line, '\n')))) + *p = '\0'; + + for (i = 0, p = line; (q = vips_break_token(p, " \t")) && i < 4; i++, p = q) if (vips_strtod(p, &header[i])) { - vips_error("matload", - _("bad number \"%s\""), p); + vips_error("matload", _("bad number \"%s\""), p); return -1; } @@ -138,8 +140,8 @@ parse_matrix_header(char *line, return -1; } - if (VIPS_FLOOR(header[0]) != header[0] || - VIPS_FLOOR(header[1]) != header[1]) { + if (floor(header[0]) != header[0] || + floor(header[1]) != header[1]) { vips_error("mask2vips", "%s", _("width / height not int")); return -1; } @@ -152,8 +154,7 @@ parse_matrix_header(char *line, *width > 100000 || *height <= 0 || *height > 100000) { - vips_error("mask2vips", - "%s", _("width / height out of range")); + vips_error("mask2vips", "%s", _("width / height out of range")); return -1; } if (header[2] == 0.0) { @@ -426,14 +427,12 @@ vips_foreign_load_matrix_source_is_a_source(VipsSource *source) double offset; int result; - if ((bytes_read = vips_source_sniff_at_most(source, - &data, 79)) <= 0) + if ((bytes_read = vips_source_sniff_at_most(source, &data, 79)) <= 0) return FALSE; g_strlcpy(line, (const char *) data, 80); vips_error_freeze(); - result = parse_matrix_header(line, - &width, &height, &scale, &offset); + result = parse_matrix_header(line, &width, &height, &scale, &offset); vips_error_thaw(); return result == 0; @@ -475,7 +474,7 @@ vips_foreign_load_matrix_source_init(VipsForeignLoadMatrixSource *source) * vips_matrixload: * @filename: file to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Reads a matrix from a file. * @@ -499,7 +498,8 @@ vips_foreign_load_matrix_source_init(VipsForeignLoadMatrixSource *source) * Extra characters at the ends of lines or at the end of the file are * ignored. * - * See also: vips_matrixload(). + * ::: seealso + * [ctor@Image.matrixload]. * * Returns: 0 on success, -1 on error. */ @@ -520,11 +520,12 @@ vips_matrixload(const char *filename, VipsImage **out, ...) * vips_matrixload_source: * @source: source to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_matrixload(), but read from a source. + * Exactly as [ctor@Image.matrixload], but read from a source. * - * See also: vips_matrixload(). + * ::: seealso + * [ctor@Image.matrixload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/matrixsave.c b/libvips/foreign/matrixsave.c index b7cfe78ff9..4a76092941 100644 --- a/libvips/foreign/matrixsave.c +++ b/libvips/foreign/matrixsave.c @@ -177,7 +177,7 @@ vips_foreign_save_matrix_class_init(VipsForeignSaveMatrixClass *class) foreign_class->suffs = vips_foreign_save_matrix_suffs; - save_class->saveable = VIPS_SAVEABLE_MONO; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_MONO; save_class->format_table = bandfmt_matrix; } @@ -333,12 +333,13 @@ vips_foreign_print_matrix_init(VipsForeignPrintMatrix *matrix) * vips_matrixsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Write @in to @filename in matrix format. See vips_matrixload() for a + * Write @in to @filename in matrix format. See [ctor@Image.matrixload] for a * description of the format. * - * See also: vips_matrixload(). + * ::: seealso + * [ctor@Image.matrixload]. * * Returns: 0 on success, -1 on error. */ @@ -359,11 +360,12 @@ vips_matrixsave(VipsImage *in, const char *filename, ...) * vips_matrixsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_matrixsave(), but save to a target. + * As [method@Image.matrixsave], but save to a target. * - * See also: vips_matrixsave(). + * ::: seealso + * [method@Image.matrixsave]. * * Returns: 0 on success, -1 on error. */ @@ -383,12 +385,13 @@ vips_matrixsave_target(VipsImage *in, VipsTarget *target, ...) /** * vips_matrixprint: (method) * @in: image to print - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Print @in to %stdout in matrix format. See vips_matrixload() for a + * Print @in to %stdout in matrix format. See [ctor@Image.matrixload] for a * description of the format. * - * See also: vips_matrixload(). + * ::: seealso + * [ctor@Image.matrixload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/meson.build b/libvips/foreign/meson.build index 23874be308..71d55c882d 100644 --- a/libvips/foreign/meson.build +++ b/libvips/foreign/meson.build @@ -73,7 +73,6 @@ foreign_headers = files( # if it is not built as a dynamically loadable module. magick_module_sources = files( 'magick.c', - 'magick2vips.c', 'magick6load.c', 'magick7load.c', 'vips2magick.c', @@ -117,6 +116,7 @@ endif openslide_module_sources = files( 'openslideload.c', + 'openslideconnection.c', ) if not openslide_module diff --git a/libvips/foreign/niftiload.c b/libvips/foreign/niftiload.c index acff6484b1..614d74ed6a 100644 --- a/libvips/foreign/niftiload.c +++ b/libvips/foreign/niftiload.c @@ -808,13 +808,14 @@ vips_foreign_load_nifti_source_init( * vips_niftiload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Read a NIFTI image file into a VIPS image. * * NIFTI metadata is attached with the "nifti-" prefix. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -835,9 +836,9 @@ vips_niftiload(const char *filename, VipsImage **out, ...) * vips_niftiload_source: * @source: source to load from * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_niftiload(), but read from a source. + * Exactly as [ctor@Image.niftiload], but read from a source. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/niftisave.c b/libvips/foreign/niftisave.c index de2f42cd3a..15982d74e2 100644 --- a/libvips/foreign/niftisave.c +++ b/libvips/foreign/niftisave.c @@ -434,7 +434,7 @@ vips_foreign_save_nifti_class_init(VipsForeignSaveNiftiClass *class) foreign_class->suffs = vips_foreign_nifti_suffs; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; save_class->format_table = vips_nifti_bandfmt; VIPS_ARG_STRING(class, "filename", 1, @@ -456,13 +456,14 @@ vips_foreign_save_nifti_init(VipsForeignSaveNifti *nifti) * vips_niftisave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image to a file in NIFTI format. * * Use the various NIFTI suffixes to pick the nifti save format. * - * See also: vips_image_write_to_file(), vips_niftiload(). + * ::: seealso + * [method@Image.write_to_file], [ctor@Image.niftiload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/nsgifload.c b/libvips/foreign/nsgifload.c index ba24ff2b8c..b794afb4c7 100644 --- a/libvips/foreign/nsgifload.c +++ b/libvips/foreign/nsgifload.c @@ -131,6 +131,10 @@ typedef struct _VipsForeignLoadNsgif { */ int gif_delay; + /* n, ready for libnsgif. + */ + int gif_n; + /* If the GIF contains any frames with transparent elements. */ gboolean has_transparency; @@ -263,7 +267,7 @@ vips_foreign_load_nsgif_set_header(VipsForeignLoadNsgif *gif, VIPS_DEBUG_MSG("vips_foreign_load_nsgif_set_header:\n"); vips_image_init_fields(image, - gif->info->width, gif->info->height * gif->n, + gif->info->width, gif->info->height * gif->gif_n, gif->has_transparency ? 4 : 3, VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0); @@ -272,9 +276,8 @@ vips_foreign_load_nsgif_set_header(VipsForeignLoadNsgif *gif, /* Only set page-height if we have more than one page, or this could * accidentally turn into an animated image later. */ - if (gif->n > 1) - vips_image_set_int(image, - VIPS_META_PAGE_HEIGHT, gif->info->height); + if (gif->gif_n > 1) + vips_image_set_int(image, VIPS_META_PAGE_HEIGHT, gif->info->height); vips_image_set_int(image, VIPS_META_N_PAGES, gif->info->frame_count); vips_image_set_int(image, "loop", gif->info->loop_max); @@ -435,11 +438,13 @@ vips_foreign_load_nsgif_header(VipsForeignLoad *load) } if (gif->n == -1) - gif->n = gif->info->frame_count - gif->page; + gif->gif_n = gif->info->frame_count - gif->page; + else + gif->gif_n = gif->n; if (gif->page < 0 || - gif->n <= 0 || - gif->page + gif->n > gif->info->frame_count) { + gif->gif_n <= 0 || + gif->page + gif->gif_n > gif->info->frame_count) { vips_error(class->nickname, "%s", _("bad page number")); return -1; } @@ -512,7 +517,7 @@ vips_foreign_load_nsgif_generate(VipsRegion *out_region, gif->frame_number = page; } - p = (VipsPel *) gif->bitmap + line * gif->info->width * sizeof(int); + p = (VipsPel *) gif->bitmap + (size_t) line * gif->info->width * sizeof(int); q = VIPS_REGION_ADDR(out_region, 0, r->top + y); if (gif->has_transparency) memcpy(q, p, VIPS_REGION_SIZEOF_LINE(out_region)); @@ -680,6 +685,7 @@ vips_foreign_load_nsgif_init(VipsForeignLoadNsgif *gif) } gif->n = 1; + gif->gif_n = 1; gif->frame_number = -1; gif->bitmap = NULL; } @@ -918,13 +924,7 @@ vips_foreign_load_nsgif_source_init(VipsForeignLoadNsgifSource *source) * vips_gifload: * @filename: file to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, page (frame) to read - * * @n: %gint, load this many pages - * * @fail_on: #VipsFailOn, types of read error to fail on + * @...: `NULL`-terminated list of optional named arguments * * Read a GIF file into a libvips image. * @@ -932,15 +932,21 @@ vips_foreign_load_nsgif_source_init(VipsForeignLoadNsgifSource *source) * * Use @n to select the number of pages to render. The default is 1. Pages are * rendered in a vertical column. Set to -1 to mean "until the end of the - * document". Use vips_grid() to change page layout. + * document". Use [method@Image.grid] to change page layout. * * Use @fail_on to set the type of error that will cause load to fail. By - * default, loaders are permissive, that is, #VIPS_FAIL_ON_NONE. + * default, loaders are permissive, that is, [enum@Vips.FailOn.NONE]. * * The output image is RGBA for GIFs containing transparent elements, RGB * otherwise. * - * See also: vips_image_new_from_file(). + * ::: tip "Optional arguments" + * * @page: `gint`, page (frame) to read + * * @n: `gint`, load this many pages + * * @fail_on: [enum@FailOn], types of read error to fail on + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -962,20 +968,20 @@ vips_gifload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @page: %gint, page (frame) to read - * * @n: %gint, load this many pages - * * @fail_on: #VipsFailOn, types of read error to fail on - * - * Exactly as vips_gifload(), but read from a memory buffer. + * Exactly as [ctor@Image.gifload], but read from a memory buffer. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. * - * See also: vips_gifload(). + * ::: tip "Optional arguments" + * * @page: `gint`, page (frame) to read + * * @n: `gint`, load this many pages + * * @fail_on: [enum@FailOn], types of read error to fail on + * + * ::: seealso + * [ctor@Image.gifload]. * * Returns: 0 on success, -1 on error. */ @@ -1003,17 +1009,17 @@ vips_gifload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_gifload_source: * @source: source to load * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @page: %gint, page (frame) to read - * * @n: %gint, load this many pages - * * @fail_on: #VipsFailOn, types of read error to fail on + * Exactly as [ctor@Image.gifload], but read from a source. * - * Exactly as vips_gifload(), but read from a source. + * ::: tip "Optional arguments" + * * @page: `gint`, page (frame) to read + * * @n: `gint`, load this many pages + * * @fail_on: [enum@FailOn], types of read error to fail on * - * See also: vips_gifload(). + * ::: seealso + * [ctor@Image.gifload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/openexr2vips.c b/libvips/foreign/openexr2vips.c index bd0677ffe7..e3e1637494 100644 --- a/libvips/foreign/openexr2vips.c +++ b/libvips/foreign/openexr2vips.c @@ -83,7 +83,6 @@ #include #include -#include #include #include diff --git a/libvips/foreign/openexrload.c b/libvips/foreign/openexrload.c index 6ba9dad11c..dc3c3a7aaf 100644 --- a/libvips/foreign/openexrload.c +++ b/libvips/foreign/openexrload.c @@ -164,7 +164,7 @@ vips_foreign_load_openexr_init(VipsForeignLoadOpenexr *openexr) * vips_openexrload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Read a OpenEXR file into a VIPS image. * @@ -175,7 +175,8 @@ vips_foreign_load_openexr_init(VipsForeignLoadOpenexr *openexr) * This reader uses the rather limited OpenEXR C API. It should really be * redone in C++. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/openslideconnection.c b/libvips/foreign/openslideconnection.c new file mode 100644 index 0000000000..1c75a7d80c --- /dev/null +++ b/libvips/foreign/openslideconnection.c @@ -0,0 +1,285 @@ +/* Share and reuse openslide_t between many openslideload operations. + * + * 1/4/25 + * - first version! + */ + +/* + + 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 + + */ + +/* +#define VIPS_DEBUG +#define DEBUG + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#ifdef HAVE_OPENSLIDE + +#include +#include + +#include "pforeign.h" + +#include + +// we keep this many connections around after they are closed, ready for reuse +#define OPENSLIDECONNECTION (3) + +// a tile cache shared between all active openslide connections ... 32mb +#define OPENSLIDECONNECTION_CACHE_SIZE (64 * 1024 * 1024) + +typedef struct _VipsOpenslideConnection { + char *filename; + + // protected by vips_openslideconnection_lock + int ref_count; + + // first access protected by separate lock, since initialization + // is slow + openslide_t *osr; + GMutex osr_lock; + +} VipsOpenslideConnection; + +static GHashTable *vips_openslideconnection_cache = NULL; +static GQueue *vips_openslideconnection_unused = NULL; +static GMutex vips_openslideconnection_lock; + +/* Added in 4.0 ... this is a tile cache that's shared between all active + * openslide connections. + */ +#ifdef HAVE_OPENSLIDE_CACHE_CREATE +openslide_cache_t *vips_openslideconnection_openslide_cache; +#endif /*HAVE_OPENSLIDE_CACHE_CREATE*/ + +static void +vips_openslideconnection_free(VipsOpenslideConnection *connection) +{ +#ifdef DEBUG + printf("vips_openslideconnection_free: %s\n", connection->filename); +#endif /*DEBUG*/ + + VipsOpenslideConnection *cached G_GNUC_UNUSED = + g_hash_table_lookup(vips_openslideconnection_cache, + connection->filename); + g_assert(cached); + g_assert(cached == connection); + g_hash_table_remove(vips_openslideconnection_cache, connection->filename); + g_queue_remove(vips_openslideconnection_unused, connection); + + g_mutex_lock(&connection->osr_lock); + VIPS_FREEF(openslide_close, connection->osr); + g_mutex_unlock(&connection->osr_lock); + g_mutex_clear(&connection->osr_lock); + VIPS_FREE(connection->filename); + g_free(connection); +} + +static void +vips_openslideconnection_trim(void) +{ + while (vips_openslideconnection_unused->length > OPENSLIDECONNECTION) { + VipsOpenslideConnection *oldest = + g_queue_pop_head(vips_openslideconnection_unused); + vips_openslideconnection_free(oldest); + } +} + +static void +vips_openslideconnection_unref(VipsOpenslideConnection *connection) +{ +#ifdef DEBUG + printf("vips_openslideconnection_unref: %s\n", connection->filename); +#endif /*DEBUG*/ + + g_assert(connection->ref_count > 0); + + connection->ref_count -= 1; + + if (connection->ref_count == 0) { + /* If the openslide_t is in an error state, or we've no connection, + * don't leave it in the cache. + */ + if (!connection->osr || + openslide_get_error(connection->osr)) + vips_openslideconnection_free(connection); + else { + g_queue_push_tail(vips_openslideconnection_unused, connection); + vips_openslideconnection_trim(); + } + } +} + +static void +vips_openslideconnection_ref(VipsOpenslideConnection *connection) +{ +#ifdef DEBUG + printf("vips_openslideconnection_ref: %s\n", connection->filename); +#endif /*DEBUG*/ + + g_assert(connection->ref_count >= 0); + + if (connection->ref_count == 0) + g_queue_remove(vips_openslideconnection_unused, connection); + + connection->ref_count += 1; +} + +static VipsOpenslideConnection * +vips_openslideconnection_new(const char *filename) +{ +#ifdef DEBUG + printf("vips_openslideconnection_new: %s\n", filename); +#endif /*DEBUG*/ + + VipsOpenslideConnection *connection; + + connection = g_new0(VipsOpenslideConnection, 1); + connection->filename = g_strdup(filename); + g_mutex_init(&connection->osr_lock); + + g_assert(!g_hash_table_lookup(vips_openslideconnection_cache, filename)); + + g_hash_table_insert(vips_openslideconnection_cache, + connection->filename, connection); + + return connection; +} + +openslide_t * +vips__openslideconnection_open(const char *filename, gboolean revalidate) +{ +#ifdef DEBUG + printf("vips_openslideconnection_open: %s, revalidate = %d\n", + filename, revalidate); +#endif /*DEBUG*/ + + g_mutex_lock(&vips_openslideconnection_lock); + + if (!vips_openslideconnection_cache) { + vips_openslideconnection_cache = + g_hash_table_new(g_str_hash, g_str_equal); + vips_openslideconnection_unused = g_queue_new(); + +#ifdef HAVE_OPENSLIDE_CACHE_CREATE + vips_openslideconnection_openslide_cache = + openslide_cache_create(OPENSLIDECONNECTION_CACHE_SIZE); +#endif /*HAVE_OPENSLIDE_CACHE_CREATE*/ + } + + VipsOpenslideConnection *connection; + + connection = g_hash_table_lookup(vips_openslideconnection_cache, filename); + + // discard any cached connection on revalidate + if (connection && + connection->ref_count == 0 && + revalidate) + VIPS_FREEF(vips_openslideconnection_free, connection); + + if (!connection) + connection = vips_openslideconnection_new(filename); + + vips_openslideconnection_ref(connection); + + g_mutex_unlock(&vips_openslideconnection_lock); + + g_mutex_lock(&connection->osr_lock); + + gboolean unref; + + /* We do the open outside the main lock (just in the connection lock) + * since it can take many seconds for some slides. + */ + unref = FALSE; + if (!connection->osr) { + connection->osr = openslide_open(connection->filename); + + /* If open fails, we must unref the connection, since we'll return + * NULL. + */ + if (!connection->osr) + unref = TRUE; + +#ifdef HAVE_OPENSLIDE_CACHE_CREATE + if (connection->osr) + openslide_set_cache(connection->osr, + vips_openslideconnection_openslide_cache); +#endif /*HAVE_OPENSLIDE_CACHE_CREATE*/ + } + + openslide_t *osr = connection->osr; + + g_mutex_unlock(&connection->osr_lock); + + if (unref) { + g_mutex_lock(&vips_openslideconnection_lock); + vips_openslideconnection_unref(connection); + g_mutex_unlock(&vips_openslideconnection_lock); + } + + return osr; +} + +void +vips__openslideconnection_close(const char *filename) +{ +#ifdef DEBUG + printf("vips_openslideconnection_close: %s\n", filename); +#endif /*DEBUG*/ + + g_mutex_lock(&vips_openslideconnection_lock); + + VipsOpenslideConnection *connection; + connection = g_hash_table_lookup(vips_openslideconnection_cache, filename); + if (connection) + vips_openslideconnection_unref(connection); + + g_mutex_unlock(&vips_openslideconnection_lock); +} + +int +vips__openslideconnection_leak(void) +{ + int n_leaks; + + n_leaks = 0; + + g_mutex_lock(&vips_openslideconnection_lock); + + if (vips_openslideconnection_cache) + n_leaks += g_hash_table_size(vips_openslideconnection_cache) - + vips_openslideconnection_unused->length; + + g_mutex_unlock(&vips_openslideconnection_lock); + + if (n_leaks > 0) + printf("vips__openslideconnection_leak: %d leaked connections\n", + n_leaks); + + return n_leaks; +} + +#endif /*HAVE_OPENSLIDE*/ diff --git a/libvips/foreign/openslideload.c b/libvips/foreign/openslideload.c index a5a7f19af3..2314fc4b60 100644 --- a/libvips/foreign/openslideload.c +++ b/libvips/foreign/openslideload.c @@ -105,6 +105,12 @@ #include +/* From openslideconnection.c + */ +openslide_t *vips__openslideconnection_open(const char *filename, + gboolean revalidate); +void vips__openslideconnection_close(const char *filename); + typedef struct { /* Params. */ @@ -115,6 +121,7 @@ typedef struct { char *associated; gboolean attach_associated; gboolean rgb; + gboolean revalidate; openslide_t *osr; @@ -136,7 +143,6 @@ typedef struct { static int vips__openslide_isslide(const char *filename) { -#ifdef HAVE_OPENSLIDE_3_4 const char *vendor; int ok; @@ -146,48 +152,21 @@ vips__openslide_isslide(const char *filename) * Only offer to load this file if it's not a generic tiff since * we want vips_tiffload() to handle these. */ - ok = (vendor && - strcmp(vendor, "generic-tiff") != 0); - - VIPS_DEBUG_MSG("vips__openslide_isslide: %s - %d\n", filename, ok); - - return ok; -#else - openslide_t *osr; - int ok; - - ok = 0; - osr = openslide_open(filename); - - if (osr) { - const char *vendor; - - /* Generic tiled tiff images can be opened by openslide as - * well. Only offer to load this file if it's not a generic - * tiff since we want vips_tiffload() to handle these. - */ - vendor = openslide_get_property_value(osr, - OPENSLIDE_PROPERTY_NAME_VENDOR); - - /* vendor will be NULL if osr is in error state. - */ - if (vendor && - strcmp(vendor, "generic-tiff") != 0) - ok = 1; - - openslide_close(osr); - } + ok = vendor && + strcmp(vendor, "generic-tiff") != 0; VIPS_DEBUG_MSG("vips__openslide_isslide: %s - %d\n", filename, ok); return ok; -#endif } static void readslide_destroy_cb(VipsImage *image, ReadSlide *rslide) { - VIPS_FREEF(openslide_close, rslide->osr); + if (rslide->osr) { + vips__openslideconnection_close(rslide->filename); + rslide->osr = NULL; + } VIPS_FREE(rslide->associated); VIPS_FREE(rslide->filename); VIPS_FREE(rslide); @@ -229,20 +208,18 @@ get_bounds(openslide_t *osr, VipsRect *rect) int i; for (i = 0; i < 4; i++) { - if (!(value = openslide_get_property_value(osr, - openslide_names[i]))) + if (!(value = openslide_get_property_value(osr, openslide_names[i]))) return FALSE; - G_STRUCT_MEMBER(int, rect, vips_offsets[i]) = - atoi(value); + G_STRUCT_MEMBER(int, rect, vips_offsets[i]) = atoi(value); } return TRUE; } static ReadSlide * -readslide_new(const char *filename, VipsImage *out, - int level, gboolean autocrop, - const char *associated, gboolean attach_associated, gboolean rgb) +readslide_new(const char *filename, VipsImage *out, int level, + gboolean autocrop, const char *associated, gboolean attach_associated, + gboolean rgb, gboolean revalidate) { ReadSlide *rslide; @@ -262,8 +239,7 @@ readslide_new(const char *filename, VipsImage *out, rslide = VIPS_NEW(NULL, ReadSlide); memset(rslide, 0, sizeof(*rslide)); - g_signal_connect(out, "close", G_CALLBACK(readslide_destroy_cb), - rslide); + g_signal_connect(out, "close", G_CALLBACK(readslide_destroy_cb), rslide); rslide->filename = g_strdup(filename); rslide->out = out; @@ -272,6 +248,7 @@ readslide_new(const char *filename, VipsImage *out, rslide->associated = g_strdup(associated); rslide->attach_associated = attach_associated; rslide->rgb = rgb; + rslide->revalidate = revalidate; /* Non-crazy defaults, override in _parse() if we can. */ @@ -382,8 +359,7 @@ vips__openslide_get_associated(ReadSlide *rslide, const char *associated_name) } #endif /*HAVE_OPENSLIDE_ICC*/ - if (vips_image_pipelinev(associated, - VIPS_DEMAND_STYLE_THINSTRIP, NULL) || + if (vips_image_pipelinev(associated, VIPS_DEMAND_STYLE_THINSTRIP, NULL) || vips_image_write_prepare(associated)) { g_object_unref(associated); return NULL; @@ -394,8 +370,7 @@ vips__openslide_get_associated(ReadSlide *rslide, const char *associated_name) (uint32_t *) VIPS_IMAGE_ADDR(associated, 0, 0)); error = openslide_get_error(rslide->osr); if (error) { - vips_error("openslide2vips", - _("reading associated image: %s"), error); + vips_error("openslide2vips", _("reading associated image: %s"), error); g_object_unref(associated); return NULL; } @@ -411,8 +386,7 @@ vips__openslide_get_associated(ReadSlide *rslide, const char *associated_name) vips_image_init_fields(rgb, w, h, 3, VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0); - if (vips_image_pipelinev(rgb, - VIPS_DEMAND_STYLE_THINSTRIP, NULL) || + if (vips_image_pipelinev(rgb, VIPS_DEMAND_STYLE_THINSTRIP, NULL) || vips_image_write_prepare(rgb)) { g_object_unref(rgb); return NULL; @@ -437,8 +411,7 @@ readslide_attach_associated(ReadSlide *rslide, VipsImage *image) { const char *const *associated_name; - for (associated_name = - openslide_get_associated_image_names(rslide->osr); + for (associated_name = openslide_get_associated_image_names(rslide->osr); *associated_name != NULL; associated_name++) { VipsImage *associated; char buf[256]; @@ -447,8 +420,7 @@ readslide_attach_associated(ReadSlide *rslide, VipsImage *image) *associated_name))) return -1; - g_snprintf(buf, 256, - "openslide.associated.%s", *associated_name); + g_snprintf(buf, 256, "openslide.associated.%s", *associated_name); vips_image_set_image(image, buf, associated); g_object_unref(associated); @@ -479,23 +451,21 @@ readslide_parse(ReadSlide *rslide, VipsImage *image) double xres; double yres; - rslide->osr = openslide_open(rslide->filename); + rslide->osr = vips__openslideconnection_open(rslide->filename, + rslide->revalidate); if (!rslide->osr) { - vips_error("openslide2vips", - "%s", _("unsupported slide format")); + vips_error("openslide2vips", "%s", _("unsupported slide format")); return -1; } error = openslide_get_error(rslide->osr); if (error) { - vips_error("openslide2vips", - _("opening slide: %s"), error); + vips_error("openslide2vips", _("opening slide: %s"), error); return -1; } if (rslide->level < 0 || rslide->level >= openslide_get_level_count(rslide->osr)) { - vips_error("openslide2vips", - "%s", _("invalid slide level")); + vips_error("openslide2vips", "%s", _("invalid slide level")); return -1; } @@ -508,32 +478,27 @@ readslide_parse(ReadSlide *rslide, VipsImage *image) rslide->associated, &w, &h); vips_image_set_string(image, "slide-associated-image", rslide->associated); - if (vips_image_pipelinev(image, - VIPS_DEMAND_STYLE_THINSTRIP, NULL)) + if (vips_image_pipelinev(image, VIPS_DEMAND_STYLE_THINSTRIP, NULL)) return -1; } else { char buf[256]; const char *value; - openslide_get_level_dimensions(rslide->osr, - rslide->level, &w, &h); + openslide_get_level_dimensions(rslide->osr, rslide->level, &w, &h); rslide->downsample = openslide_get_level_downsample( rslide->osr, rslide->level); vips_image_set_int(image, "slide-level", rslide->level); - if (vips_image_pipelinev(image, - VIPS_DEMAND_STYLE_SMALLTILE, NULL)) + if (vips_image_pipelinev(image, VIPS_DEMAND_STYLE_SMALLTILE, NULL)) return -1; /* Try to get tile width/height. An undocumented, experimental * feature. */ - g_snprintf(buf, 256, - "openslide.level[%d].tile-width", rslide->level); + g_snprintf(buf, 256, "openslide.level[%d].tile-width", rslide->level); if ((value = openslide_get_property_value(rslide->osr, buf))) rslide->tile_width = atoi(value); - g_snprintf(buf, 256, - "openslide.level[%d].tile-height", rslide->level); + g_snprintf(buf, 256, "openslide.level[%d].tile-height", rslide->level); if ((value = openslide_get_property_value(rslide->osr, buf))) rslide->tile_height = atoi(value); if (value) @@ -559,8 +524,7 @@ readslide_parse(ReadSlide *rslide, VipsImage *image) whole.top = 0; whole.width = w; whole.height = h; - vips_rect_intersectrect(&rslide->bounds, &whole, - &rslide->bounds); + vips_rect_intersectrect(&rslide->bounds, &whole, &rslide->bounds); /* If we've clipped to nothing, ignore bounds. */ @@ -593,8 +557,7 @@ readslide_parse(ReadSlide *rslide, VipsImage *image) } if (w > INT_MAX || h > INT_MAX) { - vips_error("openslide2vips", - "%s", _("image dimensions overflow int")); + vips_error("openslide2vips", "%s", _("image dimensions overflow int")); return -1; } @@ -613,8 +576,7 @@ readslide_parse(ReadSlide *rslide, VipsImage *image) for (properties = openslide_get_property_names(rslide->osr); *properties != NULL; properties++) { const char *name = *properties; - const char *value = - openslide_get_property_value(rslide->osr, name); + const char *value = openslide_get_property_value(rslide->osr, name); /* Can be NULL for some openslides with some images. */ @@ -630,8 +592,7 @@ readslide_parse(ReadSlide *rslide, VipsImage *image) associated_names = g_strjoinv(", ", (char **) openslide_get_associated_image_names(rslide->osr)); - vips_image_set_string(image, - "slide-associated-images", associated_names); + vips_image_set_string(image, "slide-associated-images", associated_names); VIPS_FREE(associated_names); vips_image_init_fields(image, w, h, rslide->rgb ? 3 : 4, @@ -664,12 +625,14 @@ readslide_parse(ReadSlide *rslide, VipsImage *image) static int vips__openslide_read_header(const char *filename, VipsImage *out, int level, gboolean autocrop, - char *associated, gboolean attach_associated, gboolean rgb) + char *associated, gboolean attach_associated, gboolean rgb, + gboolean revalidate) { ReadSlide *rslide; if (!(rslide = readslide_new(filename, - out, level, autocrop, associated, attach_associated, rgb)) || + out, level, autocrop, associated, attach_associated, rgb, + revalidate)) || readslide_parse(rslide, out)) return -1; @@ -687,7 +650,7 @@ vips__openslide_start(VipsImage *out, void *a, void *b) uint32_t *tile_buffer; if (!(tile_buffer = VIPS_MALLOC(NULL, - (size_t) rslide->tile_width * rslide->tile_height * 4))) + (size_t) rslide->tile_width * rslide->tile_height * 4))) return NULL; return (void *) tile_buffer; @@ -740,23 +703,20 @@ vips__openslide_generate(VipsRegion *out, rslide->level, r->width, r->height); - /* openslide errors are terminal. To support - * @fail we'd have to close the openslide_t and reopen, perhaps - * somehow marking this tile as unreadable. - * - * See - * https://github.com/libvips/libvips/commit/bb0a6643f94e69294e36d2b253f9bdd60c8c40ed#commitcomment-19838911 - */ error = openslide_get_error(rslide->osr); if (error) { - vips_error("openslide2vips", - _("reading region: %s"), error); + vips_error("openslide2vips", _("reading region: %s"), error); + + /* Knock the output out of cache ... openslide errors are terminal, so + * we need to force a reopen. + */ + vips_foreign_load_invalidate(rslide->out); + return -1; } if (rslide->rgb) - argb2rgb(tile_buffer, - VIPS_REGION_ADDR(out, r->left, r->top), n); + argb2rgb(tile_buffer, VIPS_REGION_ADDR(out, r->left, r->top), n); else argb2rgba(buf, n, bg); @@ -776,7 +736,7 @@ vips__openslide_stop(void *_seq, void *a, void *b) static int vips__openslide_read(const char *filename, VipsImage *out, int level, gboolean autocrop, gboolean attach_associated, - gboolean rgb) + gboolean rgb, gboolean revalidate) { ReadSlide *rslide; VipsImage *raw; @@ -786,7 +746,7 @@ vips__openslide_read(const char *filename, VipsImage *out, filename, level); if (!(rslide = readslide_new(filename, out, level, autocrop, - NULL, attach_associated, rgb))) + NULL, attach_associated, rgb, revalidate))) return -1; raw = vips_image_new(); @@ -821,7 +781,7 @@ vips__openslide_read(const char *filename, VipsImage *out, static int vips__openslide_read_associated(const char *filename, VipsImage *out, - const char *associated_name, gboolean rgb) + const char *associated_name, gboolean rgb, gboolean revalidate) { ReadSlide *rslide; VipsImage *associated; @@ -830,9 +790,9 @@ vips__openslide_read_associated(const char *filename, VipsImage *out, filename, associated_name); if (!(rslide = readslide_new(filename, - out, 0, FALSE, associated_name, FALSE, rgb))) + out, 0, FALSE, associated_name, FALSE, rgb, revalidate))) return -1; - rslide->osr = openslide_open(rslide->filename); + rslide->osr = vips__openslideconnection_open(rslide->filename, revalidate); if (!(associated = vips__openslide_get_associated(rslide, associated_name))) return -1; @@ -905,15 +865,13 @@ vips_foreign_load_openslide_build(VipsObject *object) * the openslide library works in terms of filenames. */ if (openslide->source) { - VipsConnection *connection = - VIPS_CONNECTION(openslide->source); + VipsConnection *connection = VIPS_CONNECTION(openslide->source); const char *filename; if (!vips_source_is_file(openslide->source) || !(filename = vips_connection_filename(connection))) { - vips_error(class->nickname, "%s", - _("no filename available")); + vips_error(class->nickname, "%s", _("no filename available")); return -1; } @@ -971,7 +929,7 @@ vips_foreign_load_openslide_header(VipsForeignLoad *load) if (vips__openslide_read_header(openslide->filename, load->out, openslide->level, openslide->autocrop, openslide->associated, openslide->attach_associated, - openslide->rgb)) + openslide->rgb, load->revalidate)) return -1; VIPS_SETSTR(load->out->filename, openslide->filename); @@ -988,12 +946,13 @@ vips_foreign_load_openslide_load(VipsForeignLoad *load) if (vips__openslide_read(openslide->filename, load->real, openslide->level, openslide->autocrop, openslide->attach_associated, - openslide->rgb)) + openslide->rgb, load->revalidate)) return -1; } else { if (vips__openslide_read_associated(openslide->filename, - load->real, openslide->associated, openslide->rgb)) + load->real, openslide->associated, openslide->rgb, + load->revalidate)) return -1; } @@ -1026,13 +985,7 @@ vips_foreign_load_openslide_class_init(VipsForeignLoadOpenslideClass *class) */ foreign_class->priority = 100; - /* libopenslide does not try to recover from errors, so it's not safe - * to cache. - */ - operation_class->flags |= VIPS_OPERATION_NOCACHE; - - /* openslide has not been fuzzed and is largly unmaintained, so should - * not be used with untrusted input unless you are very careful. + /* openslide is not fuzzed too heavily. */ operation_class->flags |= VIPS_OPERATION_UNTRUSTED; @@ -1100,21 +1053,16 @@ G_DEFINE_TYPE(VipsForeignLoadOpenslideFile, vips_foreign_load_openslide_file, static int vips_foreign_load_openslide_file_build(VipsObject *object) { - VipsForeignLoadOpenslide *openslide = - (VipsForeignLoadOpenslide *) object; + VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) object; VipsForeignLoadOpenslideFile *file = (VipsForeignLoadOpenslideFile *) object; if (file->filename && - !(openslide->source = - vips_source_new_from_file(file->filename))) + !(openslide->source = vips_source_new_from_file(file->filename))) return -1; - if (VIPS_OBJECT_CLASS(vips_foreign_load_openslide_file_parent_class) - ->build(object)) - return -1; - - return 0; + return VIPS_OBJECT_CLASS(vips_foreign_load_openslide_file_parent_class) + ->build(object); } static const char *vips_foreign_openslide_suffs[] = { @@ -1179,8 +1127,7 @@ G_DEFINE_TYPE(VipsForeignLoadOpenslideSource, static int vips_foreign_load_openslide_source_build(VipsObject *object) { - VipsForeignLoadOpenslide *openslide = - (VipsForeignLoadOpenslide *) object; + VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) object; VipsForeignLoadOpenslideSource *source = (VipsForeignLoadOpenslideSource *) object; @@ -1189,11 +1136,8 @@ vips_foreign_load_openslide_source_build(VipsObject *object) g_object_ref(openslide->source); } - if (VIPS_OBJECT_CLASS(vips_foreign_load_openslide_source_parent_class) - ->build(object)) - return -1; - - return 0; + return VIPS_OBJECT_CLASS(vips_foreign_load_openslide_source_parent_class) + ->build(object); } static gboolean diff --git a/libvips/foreign/pdfiumload.c b/libvips/foreign/pdfiumload.c index 599f9cb30e..9c0bd693d2 100644 --- a/libvips/foreign/pdfiumload.c +++ b/libvips/foreign/pdfiumload.c @@ -182,7 +182,7 @@ static char *vips_pdfium_errors[] = { "page not found or content error" }; -static GMutex *vips_pdfium_mutex = NULL; +static GMutex vips_pdfium_mutex; static void vips_pdfium_error(void) @@ -199,14 +199,14 @@ vips_pdfium_error(void) static void vips_foreign_load_pdf_close(VipsForeignLoadPdf *pdf) { - g_mutex_lock(vips_pdfium_mutex); + g_mutex_lock(&vips_pdfium_mutex); VIPS_FREEF(FPDF_ClosePage, pdf->page); VIPS_FREEF(FPDFDOC_ExitFormFillEnvironment, pdf->form); VIPS_FREEF(FPDF_CloseDocument, pdf->doc); VIPS_UNREF(pdf->source); - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); } static void @@ -277,7 +277,7 @@ vips_foreign_load_pdf_build(VipsObject *object) VIPS_ONCE(&once, vips_pdfium_init_cb, NULL); if (!vips_object_argument_isset(object, "scale")) - pdf->scale = pdf->dpi / 72.0; + pdf->scale = pdf->dpi / 72.0; // FIXME: Invalidates operation cache pdf->form_callbacks.version = 2; @@ -297,11 +297,11 @@ vips_foreign_load_pdf_build(VipsObject *object) pdf->file_access.m_GetBlock = vips_pdfium_GetBlock; pdf->file_access.m_Param = pdf; - g_mutex_lock(vips_pdfium_mutex); + g_mutex_lock(&vips_pdfium_mutex); if (!(pdf->doc = FPDF_LoadCustomDocument(&pdf->file_access, pdf->password))) { - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); vips_pdfium_error(); vips_error("pdfload", _("%s: unable to load"), @@ -312,7 +312,7 @@ vips_foreign_load_pdf_build(VipsObject *object) if (!(pdf->form = FPDFDOC_InitFormFillEnvironment(pdf->doc, &pdf->form_callbacks))) { - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); vips_pdfium_error(); vips_error("pdfload", _("%s: unable to initialize form fill environment"), @@ -321,7 +321,7 @@ vips_foreign_load_pdf_build(VipsObject *object) return -1; } - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); } if (VIPS_OBJECT_CLASS(vips_foreign_load_pdf_parent_class)->build(object)) @@ -350,7 +350,7 @@ vips_foreign_load_pdf_get_page(VipsForeignLoadPdf *pdf, int page_no) if (pdf->current_page != page_no) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(pdf); - g_mutex_lock(vips_pdfium_mutex); + g_mutex_lock(&vips_pdfium_mutex); VIPS_FREEF(FPDF_ClosePage, pdf->page); pdf->current_page = -1; @@ -360,7 +360,7 @@ vips_foreign_load_pdf_get_page(VipsForeignLoadPdf *pdf, int page_no) #endif /*DEBUG*/ if (!(pdf->page = FPDF_LoadPage(pdf->doc, page_no))) { - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); vips_pdfium_error(); vips_error(class->nickname, _("unable to load page %d"), page_no); @@ -368,7 +368,7 @@ vips_foreign_load_pdf_get_page(VipsForeignLoadPdf *pdf, int page_no) } pdf->current_page = page_no; - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); } return 0; @@ -412,7 +412,7 @@ vips_foreign_load_pdf_set_image(VipsForeignLoadPdf *pdf, VipsImage *out) vips_image_set_int(out, "pdf-n_pages", pdf->n_pages); vips_image_set_int(out, VIPS_META_N_PAGES, pdf->n_pages); - g_mutex_lock(vips_pdfium_mutex); + g_mutex_lock(&vips_pdfium_mutex); for (i = 0; i < n_metadata; i++) { VipsForeignLoadPdfMetadata *metadata = @@ -436,7 +436,7 @@ vips_foreign_load_pdf_set_image(VipsForeignLoadPdf *pdf, VipsImage *out) } } - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); /* We need pixels/mm for vips. */ @@ -463,14 +463,14 @@ vips_foreign_load_pdf_header(VipsForeignLoad *load) printf("vips_foreign_load_pdf_header: %p\n", pdf); #endif /*DEBUG*/ - g_mutex_lock(vips_pdfium_mutex); + g_mutex_lock(&vips_pdfium_mutex); pdf->n_pages = FPDF_GetPageCount(pdf->doc); - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); /* @n == -1 means until the end of the doc. */ if (pdf->n == -1) - pdf->n = pdf->n_pages - pdf->page_no; + pdf->n = pdf->n_pages - pdf->page_no; // FIXME: Invalidates operation cache if (pdf->page_no + pdf->n > pdf->n_pages || pdf->page_no < 0 || @@ -498,9 +498,9 @@ vips_foreign_load_pdf_header(VipsForeignLoad *load) * does round to nearest. Without this, things like * shrink-on-load will break. */ - pdf->pages[i].width = VIPS_RINT( + pdf->pages[i].width = rint( FPDF_GetPageWidth(pdf->page) * pdf->scale); - pdf->pages[i].height = VIPS_RINT( + pdf->pages[i].height = rint( FPDF_GetPageHeight(pdf->page) * pdf->scale); /* PDFium allows page width or height to be less than 1 (!!). @@ -594,7 +594,7 @@ vips_foreign_load_pdf_generate(VipsRegion *out_region, if (vips_foreign_load_pdf_get_page(pdf, pdf->page_no + i)) return -1; - vips__worker_lock(vips_pdfium_mutex); + vips__worker_lock(&vips_pdfium_mutex); /* 4 means RGBA. */ @@ -626,7 +626,7 @@ vips_foreign_load_pdf_generate(VipsRegion *out_region, FPDFBitmap_Destroy(bitmap); - g_mutex_unlock(vips_pdfium_mutex); + g_mutex_unlock(&vips_pdfium_mutex); top += rect.height; i += 1; @@ -670,28 +670,13 @@ vips_foreign_load_pdf_load(VipsForeignLoad *load) return 0; } -static void * -vips_foreign_load_pdf_once_init(void *client) -{ - /* We must make the mutex on class init (not _build) since we - * can lock even if build is not called. - */ - vips_pdfium_mutex = vips_g_mutex_new(); - - return NULL; -} - static void vips_foreign_load_pdf_class_init(VipsForeignLoadPdfClass *class) { - static GOnce once = G_ONCE_INIT; - GObjectClass *gobject_class = G_OBJECT_CLASS(class); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; - VIPS_ONCE(&once, vips_foreign_load_pdf_once_init, NULL); - gobject_class->dispose = vips_foreign_load_pdf_dispose; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 603b8133b6..2e88cb0cfa 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -67,9 +67,11 @@ int vips__tiff_write_target(VipsImage *in, VipsTarget *target, gboolean vips__istiff_source(VipsSource *source); gboolean vips__istifftiled_source(VipsSource *source); int vips__tiff_read_header_source(VipsSource *source, VipsImage *out, - int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on); + int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on, + gboolean unlimited); int vips__tiff_read_source(VipsSource *source, VipsImage *out, - int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on); + int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on, + gboolean unlimited); extern const char *vips__foreign_tiff_suffs[]; @@ -79,14 +81,6 @@ int vips__analyze_read(const char *filename, VipsImage *out); extern const char *vips__foreign_csv_suffs[]; -int vips__matrix_read_header(const char *filename, - int *width, int *height, double *scale, double *offset); -int vips__matrix_ismatrix(const char *filename); -VipsImage *vips__matrix_read_file(FILE *fp); -VipsImage *vips__matrix_read(const char *filename); -int vips__matrix_write(VipsImage *in, const char *filename); -int vips__matrix_write_file(VipsImage *in, FILE *fp); - extern const char *vips__foreign_matrix_suffs[]; int vips__openexr_isexr(const char *filename); @@ -102,16 +96,6 @@ int vips__fits_read(const char *filename, VipsImage *out); int vips__fits_write(VipsImage *in, const char *filename); -int vips__magick_read(const char *filename, - VipsImage *out, const char *density, int page, int n); -int vips__magick_read_header(const char *filename, - VipsImage *out, const char *density, int page, int n); - -int vips__magick_read_buffer(const void *buf, const size_t len, - VipsImage *out, const char *density, int page, int n); -int vips__magick_read_buffer_header(const void *buf, const size_t len, - VipsImage *out, const char *density, int page, int n); - extern const char *vips__mat_suffs[]; int vips__mat_load(const char *filename, VipsImage *out); @@ -125,8 +109,6 @@ extern const char *vips__save_ppm_suffs[]; extern const char *vips__save_pfm_suffs[]; extern const char *vips__save_pnm_suffs[]; -int vips__ppm_save_target(VipsImage *in, VipsTarget *target, - gboolean ascii, gboolean squash); int vips__rad_israd(VipsSource *source); int vips__rad_header(VipsSource *source, VipsImage *out); int vips__rad_load(VipsSource *source, VipsImage *out); diff --git a/libvips/foreign/pngload.c b/libvips/foreign/pngload.c index 1eb0b6c58e..2cb943168c 100644 --- a/libvips/foreign/pngload.c +++ b/libvips/foreign/pngload.c @@ -166,12 +166,14 @@ vips_foreign_load_png_class_init(VipsForeignLoadPngClass *class) load_class->header = vips_foreign_load_png_header; load_class->load = vips_foreign_load_png_load; +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION VIPS_ARG_BOOL(class, "unlimited", 23, _("Unlimited"), _("Remove all denial of service limits"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignLoadPng, unlimited), FALSE); +#endif } static void @@ -407,12 +409,7 @@ vips_foreign_load_png_buffer_init(VipsForeignLoadPngBuffer *buffer) * vips_pngload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @fail_on: #VipsFailOn, types of read error to fail on - * * @unlimited: %gboolean, remove all denial of service limits + * @...: `NULL`-terminated list of optional named arguments * * Read a PNG file into a VIPS image. It can read all png images, including 8- * and 16-bit images, 1 and 3 channel, with and without an alpha channel. @@ -421,13 +418,18 @@ vips_foreign_load_png_buffer_init(VipsForeignLoadPngBuffer *buffer) * XMP metadata. * * Use @fail_on to set the type of error that will cause load to fail. By - * default, loaders are permissive, that is, #VIPS_FAIL_ON_NONE. + * default, loaders are permissive, that is, [enum@Vips.FailOn.NONE]. * * By default, the PNG loader limits the number of text and data chunks to * block some denial of service attacks. Set @unlimited to disable these * limits. * - * See also: vips_image_new_from_file(). + * ::: tip "Optional arguments" + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @unlimited: `gboolean`, Remove all denial of service limits + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -449,19 +451,19 @@ vips_pngload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @fail_on: #VipsFailOn, types of read error to fail on - * * @unlimited: %gboolean, Remove all denial of service limits - * - * Exactly as vips_pngload(), but read from a PNG-formatted memory block. + * Exactly as [ctor@Image.pngload], but read from a PNG-formatted memory block. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. + * + * ::: tip "Optional arguments" + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @unlimited: `gboolean`, Remove all denial of service limits * - * See also: vips_pngload(). + * ::: seealso + * [ctor@Image.pngload]. * * Returns: 0 on success, -1 on error. */ @@ -489,16 +491,16 @@ vips_pngload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_pngload_source: * @source: source to load from * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @fail_on: #VipsFailOn, types of read error to fail on - * * @unlimited: %gboolean, Remove all denial of service limits + * Exactly as [ctor@Image.pngload], but read from a source. * - * Exactly as vips_pngload(), but read from a source. + * ::: tip "Optional arguments" + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @unlimited: `gboolean`, Remove all denial of service limits * - * See also: vips_pngload(). + * ::: seealso + * [ctor@Image.pngload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/pngsave.c b/libvips/foreign/pngsave.c index ab412ca68f..9d384e4806 100644 --- a/libvips/foreign/pngsave.c +++ b/libvips/foreign/pngsave.c @@ -204,7 +204,10 @@ vips_foreign_save_png_class_init(VipsForeignSavePngClass *class) foreign_class->suffs = vips__png_suffs; - save_class->saveable = VIPS_SAVEABLE_RGBA; + save_class->saveable = + VIPS_FOREIGN_SAVEABLE_MONO | + VIPS_FOREIGN_SAVEABLE_RGB | + VIPS_FOREIGN_SAVEABLE_ALPHA; save_class->format_table = bandfmt_png; VIPS_ARG_INT(class, "compression", 6, @@ -452,36 +455,25 @@ vips_foreign_save_png_buffer_init(VipsForeignSavePngBuffer *buffer) * vips_pngsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @compression: %gint, compression level - * * @interlace: %gboolean, interlace image - * * @filter: #VipsForeignPngFilter row filter flag(s) - * * @palette: %gboolean, enable quantisation to 8bpp palette - * * @Q: %gint, quality for 8bpp quantisation - * * @dither: %gdouble, amount of dithering for 8bpp quantization - * * @bitdepth: %gint, set write bit depth to 1, 2, 4, 8 or 16 - * * @effort: %gint, quantisation CPU effort + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image to a file as PNG. * * @compression means compress with this much effort (0 - 9). Default 6. * - * Set @interlace to %TRUE to interlace the image with ADAM7 + * Set @interlace to `TRUE` to interlace the image with ADAM7 * interlacing. Beware * than an interlaced PNG can be up to 7 times slower to write than a * non-interlaced image. * * Use @filter to specify one or more filters, defaults to none, - * see #VipsForeignPngFilter. + * see [flags@ForeignPngFilter]. * * The image is automatically converted to RGB, RGBA, Monochrome or Mono + * alpha before saving. Images with more than one byte per band element are * saved as 16-bit PNG, others are saved as 8-bit PNG. * - * Set @palette to %TRUE to enable palette mode for RGB or RGBA images. A + * Set @palette to `TRUE` to enable palette mode for RGB or RGBA images. A * palette will be computed with enough space for @bitdepth (1, 2, 4 or 8) * bits. Use @Q to set the optimisation effort, @dither to set the degree of * Floyd-Steinberg dithering and @effort to control the CPU effort @@ -495,7 +487,18 @@ vips_foreign_save_png_buffer_init(VipsForeignSavePngBuffer *buffer) * XMP metadata is written to the XMP chunk. PNG comments are written to * separate text chunks. * - * See also: vips_image_new_from_file(). + * ::: tip "Optional arguments" + * * @compression: `gint`, compression level + * * @interlace: `gboolean`, interlace image + * * @filter: [flags@ForeignPngFilter], row filter flag(s) + * * @palette: `gboolean`, enable quantisation to 8bpp palette + * * @Q: `gint`, quality for 8bpp quantisation + * * @dither: `gdouble`, amount of dithering for 8bpp quantization + * * @bitdepth: `gint`, set write bit depth to 1, 2, 4, 8 or 16 + * * @effort: `gint`, quantisation CPU effort + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -517,26 +520,26 @@ vips_pngsave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @compression: %gint, compression level - * * @interlace: %gboolean, interlace image - * * @filter: #VipsForeignPngFilter row filter flag(s) - * * @palette: %gboolean, enable quantisation to 8bpp palette - * * @Q: %gint, quality for 8bpp quantisation - * * @dither: %gdouble, amount of dithering for 8bpp quantization - * * @bitdepth: %gint, set write bit depth to 1, 2, 4, 8 or 16 - * * @effort: %gint, quantisation CPU effort - * - * As vips_pngsave(), but save to a memory buffer. + * As [method@Image.pngsave], but save to a memory buffer. * * The address of the buffer is returned in @buf, the length of the buffer in - * @len. You are responsible for freeing the buffer with g_free() when you + * @len. You are responsible for freeing the buffer with [func@GLib.free] when you * are done with it. * - * See also: vips_pngsave(), vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @compression: `gint`, compression level + * * @interlace: `gboolean`, interlace image + * * @filter: [flags@ForeignPngFilter], row filter flag(s) + * * @palette: `gboolean`, enable quantisation to 8bpp palette + * * @Q: `gint`, quality for 8bpp quantisation + * * @dither: `gdouble`, amount of dithering for 8bpp quantization + * * @bitdepth: `gint`, set write bit depth to 1, 2, 4, 8 or 16 + * * @effort: `gint`, quantisation CPU effort + * + * ::: seealso + * [method@Image.pngsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -572,22 +575,22 @@ vips_pngsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_pngsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @compression: compression level - * * @interlace: interlace image - * * @filter: libpng row filter flag(s) - * * @palette: enable quantisation to 8bpp palette - * * @Q: quality for 8bpp quantisation - * * @dither: amount of dithering for 8bpp quantization - * * @bitdepth: %gint, set write bit depth to 1, 2, 4, 8 or 16 - * * @effort: %gint, quantisation CPU effort + * As [method@Image.pngsave], but save to a target. * - * As vips_pngsave(), but save to a target. + * ::: tip "Optional arguments" + * * @compression: `gint`, compression level + * * @interlace: `gboolean`, interlace image + * * @filter: [flags@ForeignPngFilter], row filter flag(s) + * * @palette: `gboolean`, enable quantisation to 8bpp palette + * * @Q: `gint`, quality for 8bpp quantisation + * * @dither: `gdouble`, amount of dithering for 8bpp quantization + * * @bitdepth: `gint`, set write bit depth to 1, 2, 4, 8 or 16 + * * @effort: `gint`, quantisation CPU effort * - * See also: vips_pngsave(), vips_image_write_to_target(). + * ::: seealso + * [method@Image.pngsave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/popplerload.c b/libvips/foreign/popplerload.c index 59fcc6e3fd..2e5be81c2a 100644 --- a/libvips/foreign/popplerload.c +++ b/libvips/foreign/popplerload.c @@ -325,7 +325,7 @@ vips_foreign_load_pdf_header(VipsForeignLoad *load) /* @n == -1 means until the end of the doc. */ if (pdf->n == -1) - pdf->n = pdf->n_pages - pdf->page_no; + pdf->n = pdf->n_pages - pdf->page_no; // FIXME: Invalidates operation cache if (pdf->page_no + pdf->n > pdf->n_pages || pdf->page_no < 0 || @@ -357,8 +357,8 @@ vips_foreign_load_pdf_header(VipsForeignLoad *load) * does round to nearest. Without this, things like * shrink-on-load will break. */ - pdf->pages[i].width = VIPS_RINT(width * pdf->total_scale); - pdf->pages[i].height = VIPS_RINT(height * pdf->total_scale); + pdf->pages[i].width = rint(width * pdf->total_scale); + pdf->pages[i].height = rint(height * pdf->total_scale); if (pdf->pages[i].width > pdf->image.width) pdf->image.width = pdf->pages[i].width; diff --git a/libvips/foreign/ppmload.c b/libvips/foreign/ppmload.c index 139cd0dc53..c239c1c9d7 100644 --- a/libvips/foreign/ppmload.c +++ b/libvips/foreign/ppmload.c @@ -412,10 +412,10 @@ vips_foreign_load_ppm_set_image_metadata(VipsForeignLoadPpm *ppm, if (ppm->index == 6 || ppm->index == 7) vips_image_set_double(image, - "pfm-scale", VIPS_FABS(ppm->scale)); + "pfm-scale", fabs(ppm->scale)); else vips_image_set_double(image, - "ppm-max-value", VIPS_ABS(ppm->max_value)); + "ppm-max-value", abs(ppm->max_value)); VIPS_SETSTR(image->filename, vips_connection_filename(VIPS_CONNECTION(ppm->sbuf->source))); @@ -764,7 +764,7 @@ vips_foreign_load_ppm_class_init(VipsForeignLoadPpmClass *class) static void vips_foreign_load_ppm_init(VipsForeignLoadPpm *ppm) { - ppm->scale = 1.0; + ppm->scale = 1.0F; } typedef struct _VipsForeignLoadPpmFile { @@ -905,7 +905,7 @@ vips_foreign_load_ppm_source_init(VipsForeignLoadPpmSource *source) * vips_ppmload: * @filename: file to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Read a PPM/PBM/PGM/PFM file into a VIPS image. * @@ -913,7 +913,8 @@ vips_foreign_load_ppm_source_init(VipsForeignLoadPpmSource *source) * stored in binary or in ASCII. One bit images become 8 bit VIPS images, * with 0 and 255 for 0 and 1. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -934,11 +935,12 @@ vips_ppmload(const char *filename, VipsImage **out, ...) * vips_ppmload_source: * @source: source to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_ppmload(), but read from a source. + * Exactly as [ctor@Image.ppmload], but read from a source. * - * See also: vips_ppmload(). + * ::: seealso + * [ctor@Image.ppmload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index 3461a1bc45..5e0da236dd 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -324,7 +324,7 @@ vips_foreign_save_ppm_build(VipsObject *object) /* Handle the deprecated squash parameter. */ - if (vips_object_argument_isset(object, "squash")) + if (ppm->squash) ppm->bitdepth = 1; if (vips_check_uintorf("vips2ppm", image) || @@ -335,7 +335,7 @@ vips_foreign_save_ppm_build(VipsObject *object) if (ppm->ascii && image->BandFmt == VIPS_FORMAT_FLOAT) { - g_warning("%s", _("float images must be binary -- disabling ascii")); + g_warning("float images must be binary -- disabling ascii"); ppm->ascii = FALSE; } @@ -344,9 +344,8 @@ vips_foreign_save_ppm_build(VipsObject *object) if (ppm->bitdepth && (image->Bands != 1 || image->BandFmt != VIPS_FORMAT_UCHAR)) { - g_warning("%s", - _("can only save 1 band uchar images as 1 bit -- " - "disabling 1 bit save")); + g_warning("can only save 1 band uchar images as 1 bit -- " + "disabling 1 bit save"); ppm->bitdepth = 0; } @@ -500,7 +499,7 @@ vips_foreign_save_ppm_class_init(VipsForeignSavePpmClass *class) object_class->description = _("save to ppm"); object_class->build = vips_foreign_save_ppm_build; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; save_class->format_table = bandfmt_ppm; VIPS_ARG_ENUM(class, "format", 2, @@ -792,15 +791,11 @@ vips_foreign_save_pnm_target_init(VipsForeignSavePfmTarget *target) * vips_ppmsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Write a VIPS image to a file as PPM. * - * * @format: #VipsForeignPpmFormat, format to save in - * * @ascii: %gboolean, save as ASCII rather than binary - * * @bitdepth: %gint, bitdepth to save at - * - * Write a VIPS image to a file as PPM. It can write 1, 8, 16 or + * It can write 1, 8, 16 or * 32 bit unsigned integer images, float images, colour or monochrome, * stored as binary or ASCII. * Integer images of more than 8 bits can only be stored in ASCII. @@ -808,14 +803,20 @@ vips_foreign_save_pnm_target_init(VipsForeignSavePfmTarget *target) * When writing float (PFM) images the scale factor is set from the * "pfm-scale" metadata. * - * Set @ascii to %TRUE to write as human-readable ASCII. Normally data is + * Set @ascii to `TRUE` to write as human-readable ASCII. Normally data is * written in binary. * * Set @bitdepth to 1 to write a one-bit image. * * @format defaults to the sub-type for this filename suffix. * - * See also: vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @format: [enum@ForeignPpmFormat], format to save in + * * @ascii: `gboolean`, save as ASCII rather than binary + * * @bitdepth: `gint`, bitdepth to save at + * + * ::: seealso + * [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -836,17 +837,17 @@ vips_ppmsave(VipsImage *in, const char *filename, ...) * vips_ppmsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @format: #VipsForeignPpmFormat, format to save in - * * @ascii: %gboolean, save as ASCII rather than binary - * * @bitdepth: %gint, bitdepth to save at + * As [method@Image.ppmsave], but save to a target. * - * As vips_ppmsave(), but save to a target. + * ::: tip "Optional arguments" + * * @format: [enum@ForeignPpmFormat], format to save in + * * @ascii: `gboolean`, save as ASCII rather than binary + * * @bitdepth: `gint`, bitdepth to save at * - * See also: vips_ppmsave(). + * ::: seealso + * [method@Image.ppmsave]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/quantise.c b/libvips/foreign/quantise.c index 1af1992a46..62d79b96bc 100644 --- a/libvips/foreign/quantise.c +++ b/libvips/foreign/quantise.c @@ -50,7 +50,7 @@ #ifdef HAVE_IMAGEQUANT VipsQuantiseAttr * -vips__quantise_attr_create() +vips__quantise_attr_create(void) { return liq_attr_create(); } @@ -181,7 +181,7 @@ vips__quantise_attr_destroy(VipsQuantiseAttr *attr) #elif defined(HAVE_QUANTIZR) /*!HAVE_IMAGEQUANT*/ VipsQuantiseAttr * -vips__quantise_attr_create() +vips__quantise_attr_create(void) { return quantizr_new_options(); } diff --git a/libvips/foreign/quantise.h b/libvips/foreign/quantise.h index 4b2b033c20..6d1728cc00 100644 --- a/libvips/foreign/quantise.h +++ b/libvips/foreign/quantise.h @@ -59,7 +59,7 @@ extern "C" { #endif #ifdef HAVE_QUANTIZATION -VipsQuantiseAttr *vips__quantise_attr_create(); +VipsQuantiseAttr *vips__quantise_attr_create(void); VipsQuantiseError vips__quantise_set_max_colors(VipsQuantiseAttr *attr, int colors); VipsQuantiseError vips__quantise_set_quality(VipsQuantiseAttr *attr, diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index 3039d56191..292cfbba73 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -229,8 +229,8 @@ typedef float RGBPRIMS[4][2]; /* (x,y) chromaticities for RGBW */ #define COLCORSTR "COLORCORR=" #define LCOLCORSTR 10 #define iscolcor(hl) (!strncmp(hl, COLCORSTR, LCOLCORSTR)) -#define colcorval(cc, hl) sscanf((hl) + LCOLCORSTR, "%f %f %f", \ - &(cc)[RED], &(cc)[GRN], &(cc)[BLU]) +#define colcorval(cc, hl) (sscanf((hl) + LCOLCORSTR, "%f %f %f", \ + &(cc)[RED], &(cc)[GRN], &(cc)[BLU]) == 3) #define MINELEN 8 /* minimum scanline length for encoding */ #define MAXELEN 0x7fff /* maximum scanline length for encoding */ @@ -610,7 +610,7 @@ read_new(VipsSource *source, VipsImage *out) strcpy(read->format, COLRFMT); read->expos = 1.0; for (i = 0; i < 3; i++) - read->colcor[i] = 1.0; + read->colcor[i] = 1.0F; read->aspect = 1.0; read->prims[0][0] = CIE_x_r; read->prims[0][1] = CIE_y_r; @@ -643,7 +643,8 @@ rad2vips_process_line(char *line, Read *read) COLOR cc; int i; - (void) colcorval(cc, line); + if (!colcorval(cc, line)) + return -1; for (i = 0; i < 3; i++) read->colcor[i] *= cc[i]; } @@ -651,7 +652,8 @@ rad2vips_process_line(char *line, Read *read) read->aspect *= aspectval(line); } else if (isprims(line)) { - (void) primsval(read->prims, line); + if (!primsval(read->prims, line)) + return -1; } return 0; @@ -856,7 +858,7 @@ write_new(VipsImage *in, VipsTarget *target) strcpy(write->format, COLRFMT); write->expos = 1.0; for (i = 0; i < 3; i++) - write->colcor[i] = 1.0; + write->colcor[i] = 1.0F; write->aspect = 1.0; write->prims[0][0] = CIE_x_r; write->prims[0][1] = CIE_y_r; diff --git a/libvips/foreign/radload.c b/libvips/foreign/radload.c index 52ec2cc093..6728681b20 100644 --- a/libvips/foreign/radload.c +++ b/libvips/foreign/radload.c @@ -371,15 +371,15 @@ vips_foreign_load_rad_buffer_init(VipsForeignLoadRadBuffer *buffer) * vips_radload: * @filename: file to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Read a Radiance (HDR) file into a VIPS image. * - * Radiance files are read as #VIPS_CODING_RAD. They have one byte for each of + * Radiance files are read as [enum@Vips.Coding.RAD]. They have one byte for each of * red, green and blue, and one byte of shared exponent. Some operations (like - * vips_extract_area()) can work directly with images in this format, but + * [method@Image.extract_area]) can work directly with images in this format, but * mmany (all the arithmetic operations, for example) will not. Unpack - * #VIPS_CODING_RAD images to 3 band float with vips_rad2float() if + * [enum@Vips.Coding.RAD] images to 3 band float with [method@Image.rad2float] if * you want to do arithmetic on them. * * This operation ignores some header fields, like VIEW and DATE. It will not @@ -387,7 +387,8 @@ vips_foreign_load_rad_buffer_init(VipsForeignLoadRadBuffer *buffer) * * Sections of this reader from Greg Ward and Radiance with kind permission. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -409,14 +410,15 @@ vips_radload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_radload(), but read from a HDR-formatted memory block. + * Exactly as [ctor@Image.radload], but read from a HDR-formatted memory block. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. * - * See also: vips_radload(). + * ::: seealso + * [ctor@Image.radload]. * * Returns: 0 on success, -1 on error. */ @@ -444,11 +446,12 @@ vips_radload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_radload_source: * @source: source to load from * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_radload(), but read from a source. + * Exactly as [ctor@Image.radload], but read from a source. * - * See also: vips_radload(). + * ::: seealso + * [ctor@Image.radload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/radsave.c b/libvips/foreign/radsave.c index 3e7387c3c8..13e405cb83 100644 --- a/libvips/foreign/radsave.c +++ b/libvips/foreign/radsave.c @@ -93,7 +93,8 @@ vips_foreign_save_rad_class_init(VipsForeignSaveRadClass *class) foreign_class->suffs = vips__rad_suffs; - save_class->saveable = VIPS_SAVEABLE_RGB; + save_class->saveable = + VIPS_FOREIGN_SAVEABLE_MONO | VIPS_FOREIGN_SAVEABLE_RGB; save_class->format_table = vips_foreign_save_rad_format_table; save_class->coding[VIPS_CODING_NONE] = FALSE; save_class->coding[VIPS_CODING_RAD] = TRUE; @@ -123,7 +124,8 @@ vips_foreign_save_rad_file_build(VipsObject *object) VipsTarget *target; - if (VIPS_OBJECT_CLASS(vips_foreign_save_rad_file_parent_class)->build(object)) + if (VIPS_OBJECT_CLASS(vips_foreign_save_rad_file_parent_class)-> + build(object)) return -1; if (!(target = vips_target_new_to_file(file->filename))) @@ -288,13 +290,14 @@ vips_foreign_save_rad_buffer_init(VipsForeignSaveRadBuffer *buffer) * vips_radsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image in Radiance (HDR) format. * * Sections of this reader from Greg Ward and Radiance with kind permission. * - * See also: vips_image_write_to_file(). + * ::: seealso + * [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -316,15 +319,16 @@ vips_radsave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_radsave(), but save to a memory buffer. + * As [method@Image.radsave], but save to a memory buffer. * * The address of the buffer is returned in @buf, the length of the buffer in - * @len. You are responsible for freeing the buffer with g_free() when you + * @len. You are responsible for freeing the buffer with [func@GLib.free] when you * are done with it. * - * See also: vips_radsave(), vips_image_write_to_file(). + * ::: seealso + * [method@Image.radsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -360,11 +364,12 @@ vips_radsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_radsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_radsave(), but save to a target. + * As [method@Image.radsave], but save to a target. * - * See also: vips_radsave(). + * ::: seealso + * [method@Image.radsave]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/rawload.c b/libvips/foreign/rawload.c index 3861cf951b..491077eaed 100644 --- a/libvips/foreign/rawload.c +++ b/libvips/foreign/rawload.c @@ -199,25 +199,25 @@ vips_foreign_load_raw_init(VipsForeignLoadRaw *raw) * @width: width of image in pixels * @height: height of image in pixels * @bands: number of image bands - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @offset: %guint64, offset in bytes from start of file - * * @format: #VipsBandFormat, set image format - * * @interpretation: #VipsInterpretation, set image interpretation + * @...: `NULL`-terminated list of optional named arguments * * This operation mmaps the file, setting up @out so that access to that * image will read from the file. * * By default, it assumes uchar pixels. Use @format to select something else. * - * The image will be tagged as #VIPS_INTERPRETATION_MULTIBAND. Use + * The image will be tagged as [enum@Vips.Interpretation.MULTIBAND]. Use * @interpretation to select something else. * - * Use vips_byteswap() to reverse the byte ordering if necessary. + * Use [method@Image.byteswap] to reverse the byte ordering if necessary. + * + * ::: tip "Optional arguments" + * * @offset: `guint64`, offset in bytes from start of file + * * @format: [enum@BandFormat], set image format + * * @interpretation: [enum@Interpretation], set image interpretation * - * See also: vips_image_new_from_file(), vips_copy(), vips_byteswap(). + * ::: seealso + * [ctor@Image.new_from_file], [method@Image.copy], [method@Image.byteswap]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/rawsave.c b/libvips/foreign/rawsave.c index 6c495146b3..bff1a6139b 100644 --- a/libvips/foreign/rawsave.c +++ b/libvips/foreign/rawsave.c @@ -138,7 +138,7 @@ vips_foreign_save_raw_class_init(VipsForeignSaveRawClass *class) object_class->description = _("save image to raw"); object_class->build = vips_foreign_save_raw_build; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; } static void @@ -327,12 +327,13 @@ vips_foreign_save_raw_buffer_init(VipsForeignSaveRawBuffer *buffer) * vips_rawsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Writes the pixels in @in to the file @filename with no header or other * metadata. * - * See also: vips_image_write_to_file(). + * ::: seealso + * [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -354,15 +355,16 @@ vips_rawsave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_rawsave(), but save to a memory buffer. + * As [method@Image.rawsave], but save to a memory buffer. * * The address of the buffer is returned in @buf, the length of the buffer in - * @len. You are responsible for freeing the buffer with g_free() when you + * @len. You are responsible for freeing the buffer with [func@GLib.free] when you * are done with it. * - * See also: vips_rawsave(), vips_image_write_to_memory(), vips_image_write_to_file(). + * ::: seealso + * [method@Image.rawsave], [method@Image.write_to_memory], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -398,11 +400,12 @@ vips_rawsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_rawsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_rawsave(), but save to a target. + * As [method@Image.rawsave], but save to a target. * - * See also: vips_rawsave(). + * ::: seealso + * [method@Image.rawsave]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/spngload.c b/libvips/foreign/spngload.c index 9d3a48259f..e4b2d5015b 100644 --- a/libvips/foreign/spngload.c +++ b/libvips/foreign/spngload.c @@ -673,12 +673,14 @@ vips_foreign_load_png_class_init(VipsForeignLoadPngClass *class) load_class->header = vips_foreign_load_png_header; load_class->load = vips_foreign_load_png_load; +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION VIPS_ARG_BOOL(class, "unlimited", 23, _("Unlimited"), _("Remove all denial of service limits"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignLoadPng, unlimited), FALSE); +#endif } static void diff --git a/libvips/foreign/spngsave.c b/libvips/foreign/spngsave.c index 10ecbb30c2..befc79c37a 100644 --- a/libvips/foreign/spngsave.c +++ b/libvips/foreign/spngsave.c @@ -431,8 +431,7 @@ vips_foreign_save_spng_write(VipsForeignSaveSpng *spng, VipsImage *in) ihdr.color_type = SPNG_COLOR_TYPE_INDEXED; #else if (spng->palette) - g_warning("%s", - _("ignoring palette (no quantisation support)")); + g_warning("ignoring palette (no quantisation support)"); #endif /*HAVE_QUANTIZATION*/ ihdr.compression_method = 0; @@ -453,8 +452,8 @@ vips_foreign_save_spng_write(VipsForeignSaveSpng *spng, VipsImage *in) /* Set resolution. spng uses pixels per meter. */ phys.unit_specifier = 1; - phys.ppu_x = VIPS_RINT(in->Xres * 1000.0); - phys.ppu_y = VIPS_RINT(in->Xres * 1000.0); + phys.ppu_x = rint(in->Xres * 1000.0); + phys.ppu_y = rint(in->Xres * 1000.0); spng_set_phys(spng->ctx, &phys); /* Metadata. @@ -683,7 +682,10 @@ vips_foreign_save_spng_class_init(VipsForeignSaveSpngClass *class) foreign_class->suffs = vips__png_suffs; - save_class->saveable = VIPS_SAVEABLE_RGBA; + save_class->saveable = + VIPS_FOREIGN_SAVEABLE_MONO | + VIPS_FOREIGN_SAVEABLE_RGB | + VIPS_FOREIGN_SAVEABLE_ALPHA; save_class->format_table = bandfmt_spng; VIPS_ARG_INT(class, "compression", 6, diff --git a/libvips/foreign/svgload.c b/libvips/foreign/svgload.c index 040cce9ee4..f94a2007c9 100644 --- a/libvips/foreign/svgload.c +++ b/libvips/foreign/svgload.c @@ -119,6 +119,10 @@ typedef struct _VipsForeignLoadSvg { */ gboolean unlimited; + /* Custom CSS. + */ + const char *stylesheet; + RsvgHandle *page; } VipsForeignLoadSvg; @@ -522,7 +526,7 @@ vips_foreign_load_svg_get_scaled_size(VipsForeignLoadSvg *svg, if (vips_foreign_load_svg_get_natural_size(svg, &width, &height)) return -1; - /* We scale up with cairo --- scaling with rsvg_handle_set_dpi() will + /* We scale up with cairo -- scaling with rsvg_handle_set_dpi() will * fail for SVGs with absolute sizes. */ svg->cairo_scale = svg->scale * svg->dpi / 72.0; @@ -601,6 +605,21 @@ vips_foreign_load_svg_generate(VipsRegion *out_region, cr = cairo_create(surface); cairo_surface_destroy(surface); +#ifdef HAVE_RSVG_HANDLE_SET_STYLESHEET + if (svg->stylesheet && g_utf8_validate(svg->stylesheet, -1, NULL)) { + GError *error = NULL; + if (!rsvg_handle_set_stylesheet(svg->page, + (const guint8 *) svg->stylesheet, + g_utf8_strlen(svg->stylesheet, -1), &error)) { + cairo_destroy(cr); + vips_operation_invalidate(VIPS_OPERATION(svg)); + vips_error(class->nickname, "Invalid custom CSS"); + vips_g_error(&error); + return -1; + } + } +#endif + /* rsvg is single-threaded, but we don't need to lock since we're * running inside a non-threaded tilecache. */ @@ -727,12 +746,21 @@ vips_foreign_load_svg_class_init(VipsForeignLoadSvgClass *class) G_STRUCT_OFFSET(VipsForeignLoadSvg, scale), 0.0, 100000.0, 1.0); +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION VIPS_ARG_BOOL(class, "unlimited", 23, _("Unlimited"), _("Allow SVG of any size"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignLoadSvg, unlimited), FALSE); +#endif + + VIPS_ARG_STRING(class, "stylesheet", 24, + _("Stylesheet"), + _("Custom CSS"), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET(VipsForeignLoadSvg, stylesheet), + NULL); } static void @@ -1010,16 +1038,11 @@ vips_foreign_load_svg_buffer_init(VipsForeignLoadSvgBuffer *buffer) * vips_svgload: * @filename: file to load * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * * @unlimited: %gboolean, allow SVGs of any size + * Render a SVG file into a VIPS image. * - * Render a SVG file into a VIPS image. Rendering uses the librsvg library - * and should be fast. + * Rendering uses the librsvg library and should be fast. * * Use @dpi to set the rendering resolution. The default is 72. You can also * scale the rendering by @scale. @@ -1030,7 +1053,18 @@ vips_foreign_load_svg_buffer_init(VipsForeignLoadSvgBuffer *buffer) * SVGs larger than 10MB are normally blocked for security. Set @unlimited to * allow SVGs of any size. * - * See also: vips_image_new_from_file(). + * A UTF-8 string containing custom CSS can be provided via @stylesheet. + * During the CSS cascade, the specified stylesheet will be applied with a + * User Origin. This feature requires librsvg 2.48.0 or later. + * + * ::: tip "Optional arguments" + * * @dpi: `gdouble`, render at this DPI + * * @scale: `gdouble`, scale render by this factor + * * @unlimited: `gboolean`, allow SVGs of any size + * * @stylesheet: `gchararray`, custom CSS + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -1052,21 +1086,22 @@ vips_svgload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * * @unlimited: %gboolean, allow SVGs of any size + * @...: `NULL`-terminated list of optional named arguments * * Read a SVG-formatted memory block into a VIPS image. Exactly as - * vips_svgload(), but read from a memory buffer. + * [ctor@Image.svgload], but read from a memory buffer. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. * - * See also: vips_svgload(). + * ::: tip "Optional arguments" + * * @dpi: `gdouble`, render at this DPI + * * @scale: `gdouble`, scale render by this factor + * * @unlimited: `gboolean`, allow SVGs of any size + * * @stylesheet: `gchararray`, custom CSS + * + * ::: seealso + * [ctor@Image.svgload]. * * Returns: 0 on success, -1 on error. */ @@ -1094,18 +1129,19 @@ vips_svgload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_svgload_string: * @str: string to load * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @dpi: %gdouble, render at this DPI - * * @scale: %gdouble, scale render by this factor - * * @unlimited: %gboolean, allow SVGs of any size + * Exactly as [ctor@Image.svgload], but read from a string. This function + * takes a copy of the string. * - * Exactly as vips_svgload(), but read from a string. This function takes a - * copy of the string. + * ::: tip "Optional arguments" + * * @dpi: `gdouble`, render at this DPI + * * @scale: `gdouble`, scale render by this factor + * * @unlimited: `gboolean`, allow SVGs of any size + * * @stylesheet: `gchararray`, custom CSS * - * See also: vips_svgload(). + * ::: seealso + * [ctor@Image.svgload]. * * Returns: 0 on success, -1 on error. */ @@ -1133,11 +1169,12 @@ vips_svgload_string(const char *str, VipsImage **out, ...) * vips_svgload_source: * @source: source to load from * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_svgload(), but read from a source. + * Exactly as [ctor@Image.svgload], but read from a source. * - * See also: vips_svgload(). + * ::: seealso + * [ctor@Image.svgload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/tiff.c b/libvips/foreign/tiff.c index 2cf2761384..8144e40635 100644 --- a/libvips/foreign/tiff.c +++ b/libvips/foreign/tiff.c @@ -59,6 +59,11 @@ #include "tiff.h" +#ifdef HAVE_TIFF_OPEN_OPTIONS +void +vips__tiff_init(void) {} +#else + /* Handle TIFF errors here. Shared with vips2tiff.c. These can be called from * more than one thread. */ @@ -89,6 +94,7 @@ vips__tiff_init(void) TIFFSetErrorHandler(vips__thandler_error); TIFFSetWarningHandler(vips__thandler_warning); } +#endif /*HAVE_TIFF_OPEN_OPTIONS*/ /* TIFF input from a vips source. */ @@ -98,7 +104,24 @@ openin_source_read(thandle_t st, tdata_t data, tsize_t size) { VipsSource *source = VIPS_SOURCE(st); - return vips_source_read(source, data, size); + gint64 total_read; + + total_read = 0; + + while (total_read < size) { + gint64 bytes_read; + + bytes_read = vips_source_read(source, data, size - total_read); + if (bytes_read == -1) + return -1; + if (bytes_read == 0) + break; + + total_read += bytes_read; + data = (char *) data + bytes_read; + } + + return total_read; } static tsize_t @@ -157,7 +180,8 @@ openin_source_unmap(thandle_t st, tdata_t start, toff_t len) } TIFF * -vips__tiff_openin_source(VipsSource *source) +vips__tiff_openin_source(VipsSource *source, VipsTiffErrorHandler error_fn, + VipsTiffErrorHandler warning_fn, void *user_data, gboolean unlimited) { TIFF *tiff; @@ -175,6 +199,33 @@ vips__tiff_openin_source(VipsSource *source) * chopped into c. 8kb chunks. This can reduce peak memory use for * this type of file. */ + +#ifdef HAVE_TIFF_OPEN_OPTIONS + TIFFOpenOptions *opts = TIFFOpenOptionsAlloc(); + TIFFOpenOptionsSetErrorHandlerExtR(opts, error_fn, user_data); + TIFFOpenOptionsSetWarningHandlerExtR(opts, warning_fn, user_data); +#ifdef HAVE_TIFF_OPEN_OPTIONS_SET_MAX_CUMULATED_MEM_ALLOC + if (!unlimited) { + TIFFOpenOptionsSetMaxCumulatedMemAlloc(opts, 20 * 1024 * 1024); + } +#endif /*HAVE_TIFF_OPEN_OPTIONS_SET_MAX_CUMULATED_MEM_ALLOC*/ + if (!(tiff = TIFFClientOpenExt("source input", "rmC", + (thandle_t) source, + openin_source_read, + openin_source_write, + openin_source_seek, + openin_source_close, + openin_source_length, + openin_source_map, + openin_source_unmap, + opts))) { + TIFFOpenOptionsFree(opts); + vips_error("vips__tiff_openin_source", "%s", + _("unable to open source for input")); + return NULL; + } + TIFFOpenOptionsFree(opts); +#else if (!(tiff = TIFFClientOpen("source input", "rmC", (thandle_t) source, openin_source_read, @@ -188,6 +239,7 @@ vips__tiff_openin_source(VipsSource *source) _("unable to open source for input")); return NULL; } +#endif /*HAVE_TIFF_OPEN_OPTIONS*/ /* Unreffed on close(), see above. */ @@ -264,7 +316,9 @@ openout_target_unmap(thandle_t st, tdata_t start, toff_t len) } TIFF * -vips__tiff_openout_target(VipsTarget *target, gboolean bigtiff) +vips__tiff_openout_target(VipsTarget *target, gboolean bigtiff, + VipsTiffErrorHandler error_fn, VipsTiffErrorHandler warning_fn, + void *user_data) { const char *mode = bigtiff ? "w8" : "w"; @@ -274,6 +328,27 @@ vips__tiff_openout_target(VipsTarget *target, gboolean bigtiff) printf("vips__tiff_openout_buffer:\n"); #endif /*DEBUG*/ +#ifdef HAVE_TIFF_OPEN_OPTIONS + TIFFOpenOptions *opts = TIFFOpenOptionsAlloc(); + TIFFOpenOptionsSetErrorHandlerExtR(opts, error_fn, user_data); + TIFFOpenOptionsSetWarningHandlerExtR(opts, warning_fn, user_data); + if (!(tiff = TIFFClientOpenExt("target output", mode, + (thandle_t) target, + openout_target_read, + openout_target_write, + openout_target_seek, + openout_target_close, + openout_target_length, + openout_target_map, + openout_target_unmap, + opts))) { + TIFFOpenOptionsFree(opts); + vips_error("vips__tiff_openout_target", "%s", + _("unable to open target for output")); + return NULL; + } + TIFFOpenOptionsFree(opts); +#else if (!(tiff = TIFFClientOpen("target output", mode, (thandle_t) target, openout_target_read, @@ -287,6 +362,7 @@ vips__tiff_openout_target(VipsTarget *target, gboolean bigtiff) _("unable to open target for output")); return NULL; } +#endif /*HAVE_TIFF_OPEN_OPTIONS*/ return tiff; } diff --git a/libvips/foreign/tiff.h b/libvips/foreign/tiff.h index f67167e4a0..8bfc8ea5bf 100644 --- a/libvips/foreign/tiff.h +++ b/libvips/foreign/tiff.h @@ -33,14 +33,30 @@ #include +/* Aperio TIFFs (svs) use these compression types for jp2k-compressed tiles. + */ +#define JP2K_YCC (33003) +#define JP2K_RGB (33005) + +/* Bioformats uses this tag for jp2k compressed tiles. + */ +#define JP2K_LOSSY (33004) + #ifdef __cplusplus extern "C" { #endif /*__cplusplus*/ -TIFF *vips__tiff_openin_source(VipsSource *source); +typedef int (*VipsTiffErrorHandler)(TIFF *tiff, void* user_data, + const char *module, const char *fmt, va_list ap); + +TIFF *vips__tiff_openin_source(VipsSource *source, + VipsTiffErrorHandler error_fn, VipsTiffErrorHandler warning_fn, + void *user_data, gboolean unlimited); TIFF *vips__tiff_openout(const char *path, gboolean bigtiff); -TIFF *vips__tiff_openout_target(VipsTarget *target, gboolean bigtiff); +TIFF *vips__tiff_openout_target(VipsTarget *target, gboolean bigtiff, + VipsTiffErrorHandler error_fn, VipsTiffErrorHandler warning_fn, + void *user_data); #ifdef __cplusplus } diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 3977031811..f9b7380f6d 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -261,7 +261,6 @@ #include #include -#include #include "pforeign.h" #include "tiff.h" @@ -272,15 +271,6 @@ #include "jpeg.h" #endif /*HAVE_JPEG*/ -/* Aperio TIFFs (svs) use these compression types for jp2k-compressed tiles. - */ -#define JP2K_YCC 33003 -#define JP2K_RGB 33005 - -/* Bioformats uses this tag for jp2k compressed tiles. - */ -#define JP2K_LOSSY 33004 - /* Compression types we handle ourselves. */ static int rtiff_we_decompress[] = { @@ -428,6 +418,10 @@ typedef struct _Rtiff { /* The Y we are reading at. Used to verify strip read is sequential. */ int y_pos; + + /* Stop processing due to an error or warning. + */ + gboolean failed; } Rtiff; /* Convert IEEE 754-2008 16-bit float to 32-bit float @@ -443,11 +437,11 @@ half_2_float(gushort h) case 16: return INFINITY * sign; case -15: - return sign / (float) (1 << 14) * (prec / 1024.0); + return sign / (float) (1 << 14) * (prec / 1024.0F); default: return exp > 0 - ? sign * (float) (1 << exp) * (1.0 + prec / 1024.0) - : sign / (float) (1 << -exp) * (1.0 + prec / 1024.0); + ? sign * (float) (1 << exp) * (1.0F + prec / 1024.0F) + : sign / (float) (1 << -exp) * (1.0F + prec / 1024.0F); } } @@ -516,8 +510,8 @@ get_resolution(TIFF *tiff, VipsImage *out) case RESUNIT_INCH: /* In pixels-per-inch ... convert to mm. */ - x /= 10.0 * 2.54; - y /= 10.0 * 2.54; + x /= 10.0F * 2.54F; + y /= 10.0F * 2.54F; vips_image_set_string(out, VIPS_META_RESOLUTION_UNIT, "in"); break; @@ -525,8 +519,8 @@ get_resolution(TIFF *tiff, VipsImage *out) case RESUNIT_CENTIMETER: /* In pixels-per-centimetre ... convert to mm. */ - x /= 10.0; - y /= 10.0; + x /= 10.0F; + y /= 10.0F; vips_image_set_string(out, VIPS_META_RESOLUTION_UNIT, "cm"); break; @@ -541,8 +535,8 @@ get_resolution(TIFF *tiff, VipsImage *out) /* We used to warn about missing res data, but it happens so * often and is so harmless, why bother. */ - x = 1.0; - y = 1.0; + x = 1.0F; + y = 1.0F; } out->Xres = x; @@ -614,9 +608,32 @@ rtiff_minimise_cb(VipsImage *image, Rtiff *rtiff) vips_source_minimise(rtiff->source); } +static int +rtiff_handler_error(TIFF *tiff, void* user_data, + const char *module, const char *fmt, va_list ap) +{ + vips_verror("tiff2vips", fmt, ap); + return 1; +} + +static int +rtiff_handler_warning(TIFF *tiff, void* user_data, + const char *module, const char *fmt, va_list ap) +{ + if (user_data) { + Rtiff *rtiff = (Rtiff*) user_data; + if (rtiff->fail_on >= VIPS_FAIL_ON_WARNING) { + rtiff->failed = TRUE; + } + } + g_logv("tiff2vips", G_LOG_LEVEL_WARNING, fmt, ap); + return 1; +} + static Rtiff * rtiff_new(VipsSource *source, VipsImage *out, - int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on) + int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on, + gboolean unlimited) { Rtiff *rtiff; @@ -641,6 +658,7 @@ rtiff_new(VipsSource *source, VipsImage *out, rtiff->plane_buf = NULL; rtiff->contig_buf = NULL; rtiff->y_pos = 0; + rtiff->failed = FALSE; g_signal_connect(out, "close", G_CALLBACK(rtiff_close_cb), rtiff); @@ -664,7 +682,8 @@ rtiff_new(VipsSource *source, VipsImage *out, return NULL; } - if (!(rtiff->tiff = vips__tiff_openin_source(source))) + if (!(rtiff->tiff = vips__tiff_openin_source(source, + rtiff_handler_error, rtiff_handler_warning, rtiff, unlimited))) return NULL; return rtiff; @@ -680,18 +699,21 @@ rtiff_strip_read(Rtiff *rtiff, int strip, tdata_t buf) #endif /*DEBUG_VERBOSE*/ if (rtiff->header.read_scanlinewise) - length = TIFFReadScanline(rtiff->tiff, - buf, strip, (tsample_t) 0); + length = TIFFReadScanline(rtiff->tiff, buf, strip, (tsample_t) 0); else - length = TIFFReadEncodedStrip(rtiff->tiff, - strip, buf, (tsize_t) -1); + length = TIFFReadEncodedStrip(rtiff->tiff, strip, buf, (tsize_t) -1); - if (length == -1) { + if (length == -1 && rtiff->fail_on >= VIPS_FAIL_ON_WARNING) { vips_foreign_load_invalidate(rtiff->out); vips_error("tiff2vips", "%s", _("read error")); return -1; } + if (rtiff->failed) { + vips_foreign_load_invalidate(rtiff->out); + return -1; + } + return 0; } @@ -731,6 +753,11 @@ rtiff_rgba_strip_read(Rtiff *rtiff, int strip, tdata_t buf) TIFFRGBAImageEnd(&img); + if (rtiff->failed) { + vips_foreign_load_invalidate(rtiff->out); + return -1; + } + return 0; } @@ -1584,7 +1611,7 @@ rtiff_parse_palette(Rtiff *rtiff, VipsImage *out) read->blue8[i] = read->blue16[i] >> 8; } else { - g_warning("%s", _("assuming 8-bit palette")); + g_warning("assuming 8-bit palette"); for (i = 0; i < len; i++) { read->red8[i] = read->red16[i] & 0xff; @@ -1659,7 +1686,7 @@ static void rtiff_memcpy_f16_line(Rtiff *rtiff, VipsPel *q, VipsPel *p, int n, void *client) { VipsImage *im = (VipsImage *) client; - size_t len = n * im->Bands; + size_t len = (size_t) n * im->Bands; if (im->BandFmt == VIPS_FORMAT_COMPLEX || im->BandFmt == VIPS_FORMAT_DPCOMPLEX) @@ -1828,8 +1855,7 @@ rtiff_set_header(Rtiff *rtiff, VipsImage *out) vips_connection_filename(VIPS_CONNECTION(rtiff->source))); if (rtiff->n > 1) - vips_image_set_int(out, - VIPS_META_PAGE_HEIGHT, rtiff->header.height); + vips_image_set_int(out, VIPS_META_PAGE_HEIGHT, rtiff->header.height); if (rtiff->header.subifd_count > 0) vips_image_set_int(out, @@ -1845,24 +1871,18 @@ rtiff_set_header(Rtiff *rtiff, VipsImage *out) /* Read any ICC profile. */ - if (TIFFGetField(rtiff->tiff, - TIFFTAG_ICCPROFILE, &data_len, &data)) - vips_image_set_blob_copy(out, - VIPS_META_ICC_NAME, data, data_len); + if (TIFFGetField(rtiff->tiff, TIFFTAG_ICCPROFILE, &data_len, &data)) + vips_image_set_blob_copy(out, VIPS_META_ICC_NAME, data, data_len); /* Read any XMP metadata. */ - if (TIFFGetField(rtiff->tiff, - TIFFTAG_XMLPACKET, &data_len, &data)) - vips_image_set_blob_copy(out, - VIPS_META_XMP_NAME, data, data_len); + if (TIFFGetField(rtiff->tiff, TIFFTAG_XMLPACKET, &data_len, &data)) + vips_image_set_blob_copy(out, VIPS_META_XMP_NAME, data, data_len); /* Read any IPTC metadata. */ - if (TIFFGetField(rtiff->tiff, - TIFFTAG_RICHTIFFIPTC, &data_len, &data)) { - vips_image_set_blob_copy(out, - VIPS_META_IPTC_NAME, data, data_len); + if (TIFFGetField(rtiff->tiff, TIFFTAG_RICHTIFFIPTC, &data_len, &data)) { + vips_image_set_blob_copy(out, VIPS_META_IPTC_NAME, data, data_len); /* Older versions of libvips used this misspelt name :-( attach * under this name too for compatibility. @@ -1872,10 +1892,8 @@ rtiff_set_header(Rtiff *rtiff, VipsImage *out) /* Read any photoshop metadata. */ - if (TIFFGetField(rtiff->tiff, - TIFFTAG_PHOTOSHOP, &data_len, &data)) - vips_image_set_blob_copy(out, - VIPS_META_PHOTOSHOP_NAME, data, data_len); + if (TIFFGetField(rtiff->tiff, TIFFTAG_PHOTOSHOP, &data_len, &data)) + vips_image_set_blob_copy(out, VIPS_META_PHOTOSHOP_NAME, data, data_len); if (rtiff->header.image_description) vips_image_set_string(out, VIPS_META_IMAGEDESCRIPTION, @@ -1890,8 +1908,7 @@ rtiff_set_header(Rtiff *rtiff, VipsImage *out) /* Set the "orientation" tag. This is picked up later by autorot, if * requested. */ - vips_image_set_int(out, - VIPS_META_ORIENTATION, rtiff->header.orientation); + vips_image_set_int(out, VIPS_META_ORIENTATION, rtiff->header.orientation); /* Hint smalltile for tiled images, since we may be decompressing * outside the lock and THINSTRIP would prevent parallel tile decode. @@ -1983,7 +2000,7 @@ rtiff_decompress_jpeg_fill_input_buffer(j_decompress_ptr cinfo) return TRUE; } -/* Skip data --- used to skip over a potentially large amount of +/* Skip data -- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). * * Writers of suspendable-input applications must note that skip_input_data @@ -2001,7 +2018,7 @@ rtiff_decompress_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. + * any trouble anyway -- large skips are infrequent. */ if (num_bytes > 0) { while (num_bytes > (long) src->bytes_in_buffer) { @@ -2107,7 +2124,7 @@ rtiff_decompress_jpeg_run(Rtiff *rtiff, j_decompress_ptr cinfo, } jpeg_calc_output_dimensions(cinfo); - bytes_per_scanline = cinfo->output_width * bytes_per_pixel; + bytes_per_scanline = (size_t) cinfo->output_width * bytes_per_pixel; /* Double-check tile dimensions. */ @@ -2317,7 +2334,7 @@ rtiff_read_tile(RtiffSeq *seq, tdata_t *buf, int page, int x, int y) result = rtiff_read_rgba_tile(rtiff, x, y, buf); else result = TIFFReadTile(rtiff->tiff, buf, x, y, 0, 0) < 0; - if (result) { + if (result && rtiff->fail_on >= VIPS_FAIL_ON_WARNING) { vips_foreign_load_invalidate(rtiff->out); g_rec_mutex_unlock(&rtiff->lock); return -1; @@ -3303,7 +3320,7 @@ rtiff_header_read(Rtiff *rtiff, RtiffHeader *header) for (i = 0; i < extra_samples_count; i++) if (extra_samples_types[i] == EXTRASAMPLE_ASSOCALPHA) { if (header->alpha_band != -1) - g_warning("%s", _("more than one alpha -- ignoring")); + g_warning("more than one alpha -- ignoring"); header->alpha_band = header->samples_per_pixel - extra_samples_count + i; @@ -3408,7 +3425,8 @@ vips__testtiff_source(VipsSource *source, TiffPropertyFn fn) vips__tiff_init(); - if (!(tif = vips__tiff_openin_source(source))) { + if (!(tif = vips__tiff_openin_source(source, rtiff_handler_error, + rtiff_handler_warning, NULL, FALSE))) { vips_error_clear(); return FALSE; } @@ -3434,14 +3452,15 @@ vips__istifftiled_source(VipsSource *source) int vips__tiff_read_header_source(VipsSource *source, VipsImage *out, - int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on) + int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on, + gboolean unlimited) { Rtiff *rtiff; vips__tiff_init(); if (!(rtiff = rtiff_new(source, out, - page, n, autorotate, subifd, fail_on)) || + page, n, autorotate, subifd, fail_on, unlimited)) || rtiff_header_read_all(rtiff)) return -1; @@ -3464,7 +3483,8 @@ vips__tiff_read_header_source(VipsSource *source, VipsImage *out, int vips__tiff_read_source(VipsSource *source, VipsImage *out, - int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on) + int page, int n, gboolean autorotate, int subifd, VipsFailOn fail_on, + gboolean unlimited) { Rtiff *rtiff; @@ -3475,7 +3495,7 @@ vips__tiff_read_source(VipsSource *source, VipsImage *out, vips__tiff_init(); if (!(rtiff = rtiff_new(source, out, - page, n, autorotate, subifd, fail_on)) || + page, n, autorotate, subifd, fail_on, unlimited)) || rtiff_header_read_all(rtiff)) return -1; diff --git a/libvips/foreign/tiffload.c b/libvips/foreign/tiffload.c index 036ad8aa71..31f774f90f 100644 --- a/libvips/foreign/tiffload.c +++ b/libvips/foreign/tiffload.c @@ -77,6 +77,10 @@ typedef struct _VipsForeignLoadTiff { */ gboolean autorotate; + /* Remove denial of service limits. + */ + gboolean unlimited; + } VipsForeignLoadTiff; typedef VipsForeignLoadClass VipsForeignLoadTiffClass; @@ -137,7 +141,7 @@ vips_foreign_load_tiff_header(VipsForeignLoad *load) if (vips__tiff_read_header_source(tiff->source, load->out, tiff->page, tiff->n, tiff->autorotate, tiff->subifd, - load->fail_on)) + load->fail_on, tiff->unlimited)) return -1; return 0; @@ -150,7 +154,7 @@ vips_foreign_load_tiff_load(VipsForeignLoad *load) if (vips__tiff_read_source(tiff->source, load->real, tiff->page, tiff->n, tiff->autorotate, tiff->subifd, - load->fail_on)) + load->fail_on, tiff->unlimited)) return -1; return 0; @@ -209,12 +213,21 @@ vips_foreign_load_tiff_class_init(VipsForeignLoadTiffClass *class) G_STRUCT_OFFSET(VipsForeignLoadTiff, autorotate), FALSE); - VIPS_ARG_INT(class, "subifd", 21, + VIPS_ARG_INT(class, "subifd", 23, _("subifd"), _("Subifd index"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignLoadTiff, subifd), -1, 100000, -1); + +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + VIPS_ARG_BOOL(class, "unlimited", 24, + _("Unlimited"), + _("Remove all denial of service limits"), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET(VipsForeignLoadTiff, unlimited), + FALSE); +#endif } static void @@ -223,6 +236,7 @@ vips_foreign_load_tiff_init(VipsForeignLoadTiff *tiff) tiff->page = 0; tiff->n = 1; tiff->subifd = -1; + tiff->unlimited = FALSE; } typedef struct _VipsForeignLoadTiffSource { @@ -461,17 +475,11 @@ vips_foreign_load_tiff_buffer_init(VipsForeignLoadTiffBuffer *buffer) * vips_tiffload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @page: %gint, load this page - * * @n: %gint, load this many pages - * * @autorotate: %gboolean, use orientation tag to rotate the image - * during load - * * @subifd: %gint, select this subifd index + * Read a TIFF file into a VIPS image. * - * Read a TIFF file into a VIPS image. It is a full baseline TIFF 6 reader, + * It is a full baseline TIFF 6 reader, * with extensions for tiled images, multipage images, XYZ and LAB colour * space, pyramidal images and JPEG compression, including CMYK and YCbCr. * @@ -480,18 +488,18 @@ vips_foreign_load_tiff_buffer_init(VipsForeignLoadTiffBuffer *buffer) * * @n means load this many pages. By default a single page is read. All the * pages must have the same dimensions, and they are loaded as a tall, thin - * "toilet roll" image. The #VIPS_META_PAGE_HEIGHT metadata + * "toilet roll" image. The [const@META_PAGE_HEIGHT] metadata * tag gives the height in pixels of each page. Use -1 to load all pages. * - * Setting @autorotate to %TRUE will make the loader interpret the + * Setting @autorotate to `TRUE` will make the loader interpret the * orientation tag and automatically rotate the image appropriately during * load. * - * If @autorotate is %FALSE, the metadata field #VIPS_META_ORIENTATION is set + * If @autorotate is `FALSE`, the metadata field [const@META_ORIENTATION] is set * to the value of the orientation tag. Applications may read and interpret * this field - * as they wish later in processing. See vips_autorot(). Save - * operations will use #VIPS_META_ORIENTATION, if present, to set the + * as they wish later in processing. See [method@Image.autorot]. Save + * operations will use [const@META_ORIENTATION], if present, to set the * orientation of output images. * * If @autorotate is TRUE, the image will be rotated upright during load and @@ -502,14 +510,31 @@ vips_foreign_load_tiff_buffer_init(VipsForeignLoadTiffBuffer *buffer) * selected. This can be used to read lower resolution layers from * bioformats-style image pyramids. * + * Use @fail_on to set the type of error that will cause load to fail. By + * default, loaders are permissive, that is, [enum@Vips.FailOn.NONE]. + * + * When using libtiff 4.7.0+, the TIFF loader will limit memory allocation + * for tag processing to 20MB to prevent denial of service attacks. + * Set @unlimited to remove this limit. + * * Any ICC profile is read and attached to the VIPS image as - * #VIPS_META_ICC_NAME. Any XMP metadata is read and attached to the image - * as #VIPS_META_XMP_NAME. Any IPTC is attached as #VIPS_META_IPTC_NAME. The + * [const@META_ICC_NAME]. Any XMP metadata is read and attached to the image + * as [const@META_XMP_NAME]. Any IPTC is attached as [const@META_IPTC_NAME]. The * image description is - * attached as #VIPS_META_IMAGEDESCRIPTION. Data in the photoshop tag is - * attached as #VIPS_META_PHOTOSHOP_NAME. + * attached as [const@META_IMAGEDESCRIPTION]. Data in the photoshop tag is + * attached as [const@META_PHOTOSHOP_NAME]. + * + * ::: tip "Optional arguments" + * * @page: `gint`, load this page + * * @n: `gint`, load this many pages + * * @autorotate: `gboolean`, use orientation tag to rotate the image + * during load + * * @subifd: `gint`, select this subifd index + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @unlimited: `gboolean`, remove all denial of service limits * - * See also: vips_image_new_from_file(), vips_autorot(). + * ::: seealso + * [ctor@Image.new_from_file], [method@Image.autorot]. * * Returns: 0 on success, -1 on error. */ @@ -531,23 +556,25 @@ vips_tiffload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, load this page - * * @n: %gint, load this many pages - * * @autorotate: %gboolean, use orientation tag to rotate the image - * during load - * * @subifd: %gint, select this subifd index + * @...: `NULL`-terminated list of optional named arguments * * Read a TIFF-formatted memory block into a VIPS image. Exactly as - * vips_tiffload(), but read from a memory source. + * [ctor@Image.tiffload], but read from a memory source. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. + * + * ::: tip "Optional arguments" + * * @page: `gint`, load this page + * * @n: `gint`, load this many pages + * * @autorotate: `gboolean`, use orientation tag to rotate the image + * during load + * * @subifd: `gint`, select this subifd index + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @unlimited: `gboolean`, remove all denial of service limits * - * See also: vips_tiffload(). + * ::: seealso + * [ctor@Image.tiffload]. * * Returns: 0 on success, -1 on error. */ @@ -575,19 +602,21 @@ vips_tiffload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_tiffload_source: * @source: source to load * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @page: %gint, load this page - * * @n: %gint, load this many pages - * * @autorotate: %gboolean, use orientation tag to rotate the image - * during load - * * @subifd: %gint, select this subifd index + * Exactly as [ctor@Image.tiffload], but read from a source. * - * Exactly as vips_tiffload(), but read from a source. + * ::: tip "Optional arguments" + * * @page: `gint`, load this page + * * @n: `gint`, load this many pages + * * @autorotate: `gboolean`, use orientation tag to rotate the image + * during load + * * @subifd: `gint`, select this subifd index + * * @fail_on: [enum@FailOn], types of read error to fail on + * * @unlimited: `gboolean`, remove all denial of service limits * - * See also: vips_tiffload(). + * ::: seealso + * [ctor@Image.tiffload]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/tiffsave.c b/libvips/foreign/tiffsave.c index 75bf7c91d1..4cb66e919d 100644 --- a/libvips/foreign/tiffsave.c +++ b/libvips/foreign/tiffsave.c @@ -147,73 +147,72 @@ vips_foreign_save_tiff_build(VipsObject *object) VipsForeignSave *save = (VipsForeignSave *) object; VipsForeignSaveTiff *tiff = (VipsForeignSaveTiff *) object; - const char *p; + if (VIPS_OBJECT_CLASS(vips_foreign_save_tiff_parent_class)->build(object)) + return -1; + + VipsImage *ready = save->ready; + g_object_ref(ready); /* If we are saving jpeg-in-tiff, we need a different convert_saveable * path. The regular tiff one will let through things like float and * 16-bit and alpha for example, which will make the jpeg saver choke. */ - if (save->in && - tiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) { + if (tiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) { VipsImage *x; /* See also vips_foreign_save_jpeg_class_init(). */ - if (vips__foreign_convert_saveable(save->in, &x, - VIPS_SAVEABLE_RGB_CMYK, bandfmt_jpeg, class->coding, - save->background)) + if (vips__foreign_convert_saveable(ready, &x, + VIPS_FOREIGN_SAVEABLE_MONO | + VIPS_FOREIGN_SAVEABLE_RGB | + VIPS_FOREIGN_SAVEABLE_CMYK, + bandfmt_jpeg, class->coding, + save->background)) { + VIPS_UNREF(ready); return -1; + } - g_object_set(object, "in", x, NULL); - g_object_unref(x); + VIPS_UNREF(ready); + ready = x; } - if (VIPS_OBJECT_CLASS(vips_foreign_save_tiff_parent_class)->build(object)) - return -1; - - /* Default xres/yres to the values from the image. This is always - * pixels/mm. - */ - if (!vips_object_argument_isset(object, "xres")) - tiff->xres = save->ready->Xres; - if (!vips_object_argument_isset(object, "yres")) - tiff->yres = save->ready->Yres; - - /* We default to pixels/cm. - */ - tiff->xres *= 10.0; - tiff->yres *= 10.0; - /* resunit param overrides resunit metadata. */ + VipsForeignTiffResunit resunit = tiff->resunit; + const char *p; if (!vips_object_argument_isset(object, "resunit") && - vips_image_get_typeof(save->ready, - VIPS_META_RESOLUTION_UNIT) && - !vips_image_get_string(save->ready, - VIPS_META_RESOLUTION_UNIT, &p) && + vips_image_get_typeof(ready, VIPS_META_RESOLUTION_UNIT) && + !vips_image_get_string(ready, VIPS_META_RESOLUTION_UNIT, &p) && vips_isprefix("in", p)) - tiff->resunit = VIPS_FOREIGN_TIFF_RESUNIT_INCH; + resunit = VIPS_FOREIGN_TIFF_RESUNIT_INCH; - if (tiff->resunit == VIPS_FOREIGN_TIFF_RESUNIT_INCH) { - tiff->xres *= 2.54; - tiff->yres *= 2.54; + double xres; + xres = ready->Xres; + if (vips_object_argument_isset(object, "xres")) { + if (resunit == VIPS_FOREIGN_TIFF_RESUNIT_INCH) + xres = tiff->xres * 25.4; + else + xres = tiff->xres * 10.0; } - /* Handle the deprecated squash parameter. - */ - if (tiff->squash) - /* We set that even in the case of LAB to LABQ. - */ - tiff->bitdepth = 1; + double yres; + yres = ready->Yres; + if (vips_object_argument_isset(object, "yres")) { + if (resunit == VIPS_FOREIGN_TIFF_RESUNIT_INCH) + yres = tiff->yres * 25.4; + else + yres = tiff->yres * 10.0; + } - if (vips__tiff_write_target(save->ready, tiff->target, + if (vips__tiff_write_target(ready, tiff->target, tiff->compression, tiff->Q, tiff->predictor, save->profile, tiff->tile, tiff->tile_width, tiff->tile_height, tiff->pyramid, - tiff->bitdepth, + // deprecated "squash" param + tiff->squash ? 1 : tiff->bitdepth, tiff->miniswhite, - tiff->resunit, tiff->xres, tiff->yres, + resunit, xres, yres, tiff->bigtiff, tiff->rgbjpeg, tiff->properties, @@ -223,8 +222,12 @@ vips_foreign_save_tiff_build(VipsObject *object) tiff->depth, tiff->subifd, tiff->premultiply, - save->page_height)) + save->page_height)) { + VIPS_UNREF(ready); return -1; + } + + VIPS_UNREF(ready); if (vips_target_end(tiff->target)) return -1; @@ -250,7 +253,7 @@ vips_foreign_save_tiff_class_init(VipsForeignSaveTiffClass *class) foreign_class->suffs = vips__foreign_tiff_suffs; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; save_class->coding[VIPS_CODING_LABQ] = TRUE; VIPS_ARG_ENUM(class, "compression", 6, @@ -365,7 +368,7 @@ vips_foreign_save_tiff_class_init(VipsForeignSaveTiffClass *class) _("Deflate (1-9, default 6) or ZSTD (1-22, default 9) compression level"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsForeignSaveTiff, level), - 1, 22, 6); + 0, 22, 0); VIPS_ARG_BOOL(class, "lossless", 24, _("Lossless"), @@ -603,36 +606,13 @@ vips_foreign_save_tiff_buffer_init(VipsForeignSaveTiffBuffer *buffer) * vips_tiffsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @compression: use this #VipsForeignTiffCompression - * * @Q: %gint quality factor - * * @predictor: use this #VipsForeignTiffPredictor - * * @tile: %gboolean, set %TRUE to write a tiled tiff - * * @tile_width: %gint for tile size - * * @tile_height: %gint for tile size - * * @pyramid: %gboolean, write an image pyramid - * * @bitdepth: %int, change bit depth to 1,2, or 4 bit - * * @miniswhite: %gboolean, write 1-bit images as MINISWHITE - * * @resunit: #VipsForeignTiffResunit for resolution unit - * * @xres: %gdouble horizontal resolution in pixels/mm - * * @yres: %gdouble vertical resolution in pixels/mm - * * @bigtiff: %gboolean, write a BigTiff file - * * @properties: %gboolean, set %TRUE to write an IMAGEDESCRIPTION tag - * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region. - * * @level: %gint, Zstd or Deflate (zlib) compression level - * * @lossless: %gboolean, WebP lossless mode - * * @depth: #VipsForeignDzDepth how deep to make the pyramid - * * @subifd: %gboolean write pyr layers as sub-ifds - * * @premultiply: %gboolean write premultiplied alpha + * @...: `NULL`-terminated list of optional named arguments * * Write a VIPS image to a file as TIFF. * - * If @in has the #VIPS_META_PAGE_HEIGHT metadata item, this is assumed to be a + * If @in has the [const@META_PAGE_HEIGHT] metadata item, this is assumed to be a * "toilet roll" image. It will be - * written as series of pages, each #VIPS_META_PAGE_HEIGHT pixels high. + * written as series of pages, each [const@META_PAGE_HEIGHT] pixels high. * * Use @compression to set the tiff compression. Currently jpeg, packbits, * fax4, lzw, none, deflate, webp and zstd are supported. The default is no @@ -651,7 +631,7 @@ vips_foreign_save_tiff_buffer_init(VipsForeignSaveTiffBuffer *buffer) * set WEBP lossless mode on. Use @Q to set the WEBP compression level. * * Use @predictor to set the predictor for lzw, deflate and zstd compression. - * It defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal + * It defaults to [enum@Vips.ForeignTiffPredictor.HORIZONTAL], meaning horizontal * differencing. Please refer to the libtiff * specifications for further discussion of various predictors. * @@ -684,7 +664,7 @@ vips_foreign_save_tiff_buffer_init(VipsForeignSaveTiffBuffer *buffer) * Use @resunit to override the default resolution unit. * The default * resolution unit is taken from the header field - * #VIPS_META_RESOLUTION_UNIT. If this field is not set, then + * [const@META_RESOLUTION_UNIT]. If this field is not set, then * VIPS defaults to cm. * * Use @xres and @yres to override the default horizontal and vertical @@ -695,14 +675,14 @@ vips_foreign_save_tiff_buffer_init(VipsForeignSaveTiffBuffer *buffer) * format that allows more than 4GB in a file. * * Set @properties to write all vips metadata to the IMAGEDESCRIPTION tag as - * xml. If @properties is not set, the value of #VIPS_META_IMAGEDESCRIPTION is + * xml. If @properties is not set, the value of [const@META_IMAGEDESCRIPTION] is * used instead. * - * The value of #VIPS_META_XMP_NAME is written to - * the XMP tag. #VIPS_META_ORIENTATION (if set) is used to set the value of + * The value of [const@META_XMP_NAME] is written to + * the XMP tag. [const@META_ORIENTATION] (if set) is used to set the value of * the orientation - * tag. #VIPS_META_IPTC (if set) is used to set the value of the IPTC tag. - * #VIPS_META_PHOTOSHOP_NAME (if set) is used to set the value of the PHOTOSHOP + * tag. [const@META_IPTC_NAME] (if set) is used to set the value of the IPTC tag. + * [const@META_PHOTOSHOP_NAME] (if set) is used to set the value of the PHOTOSHOP * tag. * * By default, pyramid layers are saved as consecutive pages. @@ -712,7 +692,30 @@ vips_foreign_save_tiff_buffer_init(VipsForeignSaveTiffBuffer *buffer) * Set @premultiply to save with premultiplied alpha. Some programs, such as * InDesign, will only work with premultiplied alpha. * - * See also: vips_tiffload(), vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @compression: use this [enum@ForeignTiffCompression] + * * @Q: `gint`, quality factor + * * @predictor: use this [enum@ForeignTiffPredictor] + * * @tile: `gboolean`, set `TRUE` to write a tiled tiff + * * @tile_width: `gint`, for tile size + * * @tile_height: `gint`, for tile size + * * @pyramid: `gboolean`, write an image pyramid + * * @bitdepth: `gint`, change bit depth to 1,2, or 4 bit + * * @miniswhite: `gboolean`, write 1-bit images as MINISWHITE + * * @resunit: [enum@ForeignTiffResunit] for resolution unit + * * @xres: `gdouble` horizontal resolution in pixels/mm + * * @yres: `gdouble` vertical resolution in pixels/mm + * * @bigtiff: `gboolean`, write a BigTiff file + * * @properties: `gboolean`, set `TRUE` to write an IMAGEDESCRIPTION tag + * * @region_shrink: [enum@RegionShrink] How to shrink each 2x2 region. + * * @level: `gint`, Zstd or Deflate (zlib) compression level + * * @lossless: `gboolean`, WebP lossless mode + * * @depth: [enum@ForeignDzDepth] how deep to make the pyramid + * * @subifd: `gboolean` write pyr layers as sub-ifds + * * @premultiply: `gboolean` write premultiplied alpha + * + * ::: seealso + * [ctor@Image.tiffload], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -734,38 +737,38 @@ vips_tiffsave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (array length=len) (element-type guint8): return output buffer here * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @compression: use this #VipsForeignTiffCompression - * * @Q: %gint quality factor - * * @predictor: use this #VipsForeignTiffPredictor - * * @tile: %gboolean, set %TRUE to write a tiled tiff - * * @tile_width: %gint for tile size - * * @tile_height: %gint for tile size - * * @pyramid: %gboolean, write an image pyramid - * * @bitdepth: %int, set write bit depth to 1, 2, 4 or 8 - * * @miniswhite: %gboolean, write 1-bit images as MINISWHITE - * * @resunit: #VipsForeignTiffResunit for resolution unit - * * @xres: %gdouble horizontal resolution in pixels/mm - * * @yres: %gdouble vertical resolution in pixels/mm - * * @bigtiff: %gboolean, write a BigTiff file - * * @properties: %gboolean, set %TRUE to write an IMAGEDESCRIPTION tag - * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region. - * * @level: %gint, Zstd or Deflate (zlib) compression level - * * @lossless: %gboolean, WebP lossless mode - * * @depth: #VipsForeignDzDepth how deep to make the pyramid - * * @subifd: %gboolean write pyr layers as sub-ifds - * * @premultiply: %gboolean write premultiplied alpha - * - * As vips_tiffsave(), but save to a memory buffer. + * As [method@Image.tiffsave], but save to a memory buffer. * * The address of the buffer is returned in @buf, the length of the buffer in - * @len. You are responsible for freeing the buffer with g_free() when you + * @len. You are responsible for freeing the buffer with [func@GLib.free] when you * are done with it. * - * See also: vips_tiffsave(), vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @compression: use this [enum@ForeignTiffCompression] + * * @Q: `gint`, quality factor + * * @predictor: use this [enum@ForeignTiffPredictor] + * * @tile: `gboolean`, set `TRUE` to write a tiled tiff + * * @tile_width: `gint`, for tile size + * * @tile_height: `gint`, for tile size + * * @pyramid: `gboolean`, write an image pyramid + * * @bitdepth: `gint`, change bit depth to 1,2, or 4 bit + * * @miniswhite: `gboolean`, write 1-bit images as MINISWHITE + * * @resunit: [enum@ForeignTiffResunit] for resolution unit + * * @xres: `gdouble` horizontal resolution in pixels/mm + * * @yres: `gdouble` vertical resolution in pixels/mm + * * @bigtiff: `gboolean`, write a BigTiff file + * * @properties: `gboolean`, set `TRUE` to write an IMAGEDESCRIPTION tag + * * @region_shrink: [enum@RegionShrink] How to shrink each 2x2 region. + * * @level: `gint`, Zstd or Deflate (zlib) compression level + * * @lossless: `gboolean`, WebP lossless mode + * * @depth: [enum@ForeignDzDepth] how deep to make the pyramid + * * @subifd: `gboolean` write pyr layers as sub-ifds + * * @premultiply: `gboolean` write premultiplied alpha + * + * ::: seealso + * [method@Image.tiffsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -801,34 +804,34 @@ vips_tiffsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * vips_tiffsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @compression: use this #VipsForeignTiffCompression - * * @Q: %gint quality factor - * * @predictor: use this #VipsForeignTiffPredictor - * * @tile: %gboolean, set %TRUE to write a tiled tiff - * * @tile_width: %gint for tile size - * * @tile_height: %gint for tile size - * * @pyramid: %gboolean, write an image pyramid - * * @bitdepth: %int, set write bit depth to 1, 2, 4 or 8 - * * @miniswhite: %gboolean, write 1-bit images as MINISWHITE - * * @resunit: #VipsForeignTiffResunit for resolution unit - * * @xres: %gdouble horizontal resolution in pixels/mm - * * @yres: %gdouble vertical resolution in pixels/mm - * * @bigtiff: %gboolean, write a BigTiff file - * * @properties: %gboolean, set %TRUE to write an IMAGEDESCRIPTION tag - * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region. - * * @level: %gint, Zstd or Deflate (zlib) compression level - * * @lossless: %gboolean, WebP lossless mode - * * @depth: #VipsForeignDzDepth how deep to make the pyramid - * * @subifd: %gboolean write pyr layers as sub-ifds - * * @premultiply: %gboolean write premultiplied alpha - * - * As vips_tiffsave(), but save to a target. - * - * See also: vips_tiffsave(), vips_image_write_to_target(). + * @...: `NULL`-terminated list of optional named arguments + * + * As [method@Image.tiffsave], but save to a target. + * + * ::: tip "Optional arguments" + * * @compression: use this [enum@ForeignTiffCompression] + * * @Q: `gint`, quality factor + * * @predictor: use this [enum@ForeignTiffPredictor] + * * @tile: `gboolean`, set `TRUE` to write a tiled tiff + * * @tile_width: `gint`, for tile size + * * @tile_height: `gint`, for tile size + * * @pyramid: `gboolean`, write an image pyramid + * * @bitdepth: `gint`, change bit depth to 1,2, or 4 bit + * * @miniswhite: `gboolean`, write 1-bit images as MINISWHITE + * * @resunit: [enum@ForeignTiffResunit] for resolution unit + * * @xres: `gdouble` horizontal resolution in pixels/mm + * * @yres: `gdouble` vertical resolution in pixels/mm + * * @bigtiff: `gboolean`, write a BigTiff file + * * @properties: `gboolean`, set `TRUE` to write an IMAGEDESCRIPTION tag + * * @region_shrink: [enum@RegionShrink] How to shrink each 2x2 region. + * * @level: `gint`, Zstd or Deflate (zlib) compression level + * * @lossless: `gboolean`, WebP lossless mode + * * @depth: [enum@ForeignDzDepth] how deep to make the pyramid + * * @subifd: `gboolean` write pyr layers as sub-ifds + * * @premultiply: `gboolean` write premultiplied alpha + * + * ::: seealso + * [method@Image.tiffsave], [method@Image.write_to_target]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index abeb2e537d..9e5226b864 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -314,7 +314,7 @@ write_xmp(Write *write, VipsImage *in) * error with large chunks. */ if (data_length > 60000) { - g_warning("%s", _("VipsJpeg: large XMP not saved")); + g_warning("large XMP not saved"); return 0; } @@ -435,18 +435,18 @@ vips_jfif_resolution_from_image(struct jpeg_compress_struct *cinfo, switch (unit) { case 0: - xres = VIPS_RINT(image->Xres); - yres = VIPS_RINT(image->Yres); + xres = rint(image->Xres); + yres = rint(image->Yres); break; case 1: - xres = VIPS_RINT(image->Xres * 25.4); - yres = VIPS_RINT(image->Yres * 25.4); + xres = rint(image->Xres * 25.4); + yres = rint(image->Yres * 25.4); break; case 2: - xres = VIPS_RINT(image->Xres * 10.0); - yres = VIPS_RINT(image->Yres * 10.0); + xres = rint(image->Xres * 10.0); + yres = rint(image->Yres * 10.0); break; default: @@ -607,7 +607,7 @@ set_cinfo(struct jpeg_compress_struct *cinfo, cinfo->optimize_coding = TRUE; } else - g_warning("%s", _("trellis_quant unsupported")); + g_warning("trellis_quant unsupported"); } /* Apply overshooting to samples with extreme values e.g. 0 & 255 @@ -619,8 +619,7 @@ set_cinfo(struct jpeg_compress_struct *cinfo, jpeg_c_set_bool_param(cinfo, JBOOLEAN_OVERSHOOT_DERINGING, TRUE); else - g_warning("%s", - _("overshoot_deringing unsupported")); + g_warning("overshoot_deringing unsupported"); } /* Split the spectrum of DCT coefficients into separate scans. @@ -634,12 +633,10 @@ set_cinfo(struct jpeg_compress_struct *cinfo, jpeg_c_set_bool_param(cinfo, JBOOLEAN_OPTIMIZE_SCANS, TRUE); else - g_warning("%s", - _("ignoring optimize_scans")); + g_warning("ignoring optimize_scans"); } else - g_warning("%s", - _("ignoring optimize_scans for baseline")); + g_warning("ignoring optimize_scans for baseline"); } /* Use predefined quantization table. @@ -650,21 +647,20 @@ set_cinfo(struct jpeg_compress_struct *cinfo, jpeg_c_set_int_param(cinfo, JINT_BASE_QUANT_TBL_IDX, quant_table); else - g_warning("%s", - _("setting quant_table unsupported")); + g_warning("setting quant_table unsupported"); } #else /* Using jpeglib.h without extension parameters, warn of ignored * options. */ if (trellis_quant) - g_warning("%s", _("ignoring trellis_quant")); + g_warning("ignoring trellis_quant"); if (overshoot_deringing) - g_warning("%s", _("ignoring overshoot_deringing")); + g_warning("ignoring overshoot_deringing"); if (optimize_scans) - g_warning("%s", _("ignoring optimize_scans")); + g_warning("ignoring optimize_scans"); if (quant_table > 0) - g_warning("%s", _("ignoring quant_table")); + g_warning("ignoring quant_table"); #endif /* Set compression quality. Must be called after setting params above. diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index 002f0b868d..bd14093f3c 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -166,7 +166,7 @@ vips_foreign_save_magick_next_image(VipsForeignSaveMagick *magick) page_index = magick->position.top / magick->page_height; if (page_index < magick->delays_length) image->delay = - VIPS_RINT(magick->delays[page_index] / 10.0); + rint(magick->delays[page_index] / 10.0); } /* ImageMagick uses iterations like this (at least in gif save): @@ -475,7 +475,7 @@ vips_foreign_save_magick_class_init(VipsForeignSaveMagickClass *class) foreign_class->priority = -100; foreign_class->suffs = vips__save_magick_suffs; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; save_class->format_table = bandfmt_magick; VIPS_ARG_STRING(class, "format", 2, @@ -503,8 +503,7 @@ vips_foreign_save_magick_class_init(VipsForeignSaveMagickClass *class) _("Optimize_gif_transparency"), _("Apply GIF transparency optimization"), VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET(VipsForeignSaveMagick, - optimize_gif_transparency), + G_STRUCT_OFFSET(VipsForeignSaveMagick, optimize_gif_transparency), FALSE); VIPS_ARG_INT(class, "bitdepth", 6, diff --git a/libvips/foreign/vips2tiff.c b/libvips/foreign/vips2tiff.c index 7a93d0f3d2..4c37b0e4fe 100644 --- a/libvips/foreign/vips2tiff.c +++ b/libvips/foreign/vips2tiff.c @@ -285,10 +285,6 @@ */ #define MAX_ALPHA (64) -/* Bioformats uses this tag for lossy jp2k compressed tiles. - */ -#define JP2K_LOSSY 33004 - /* Compression types we handle ourselves. */ static int wtiff_we_compress[] = { @@ -393,9 +389,19 @@ struct _Wtiff { /* Lock thread calls into libtiff with this. */ - GMutex *lock; + GMutex lock; }; +/* libvips uses size_t for the length of binary data items, but libtiff wants + * uint32. + */ +static void +set_data64(TIFF *tif, guint32 tag, size_t length, const void *data) +{ + if (length <= UINT_MAX) + TIFFSetField(tif, tag, (guint32) length, data); +} + /* Write an ICC Profile from a file into the JPEG stream. */ static int @@ -410,7 +416,7 @@ embed_profile_file(TIFF *tif, const char *profile) size_t length; const void *data = vips_blob_get(blob, &length); - TIFFSetField(tif, TIFFTAG_ICCPROFILE, length, data); + set_data64(tif, TIFFTAG_ICCPROFILE, length, data); #ifdef DEBUG printf("vips2tiff: attached profile \"%s\"\n", profile); @@ -432,7 +438,7 @@ embed_profile_meta(TIFF *tif, VipsImage *im) if (vips_image_get_blob(im, VIPS_META_ICC_NAME, &data, &length)) return -1; - TIFFSetField(tif, TIFFTAG_ICCPROFILE, length, data); + set_data64(tif, TIFFTAG_ICCPROFILE, length, data); #ifdef DEBUG printf("vips2tiff: attached profile from meta\n"); @@ -441,6 +447,22 @@ embed_profile_meta(TIFF *tif, VipsImage *im) return 0; } +static int +wtiff_handler_error(TIFF *tiff, void* user_data, + const char *module, const char *fmt, va_list ap) +{ + vips_verror("vips2tiff", fmt, ap); + return 1; +} + +static int +wtiff_handler_warning(TIFF *tiff, void* user_data, + const char *module, const char *fmt, va_list ap) +{ + g_logv("vips2tiff", G_LOG_LEVEL_WARNING, fmt, ap); + return 1; +} + static void wtiff_layer_init(Wtiff *wtiff, Layer **layer, Layer *above, int width, int height) @@ -475,9 +497,16 @@ wtiff_layer_init(Wtiff *wtiff, Layer **layer, Layer *above, (*layer)->target = wtiff->target; g_object_ref((*layer)->target); } - else - (*layer)->target = - vips_target_new_temp(wtiff->target); + else { + const guint64 disc_threshold = vips_get_disc_threshold(); + const guint64 layer_size = + VIPS_IMAGE_SIZEOF_PEL(wtiff->ready) * width * height; + + if (layer_size > disc_threshold) + (*layer)->target = vips_target_new_temp(wtiff->target); + else + (*layer)->target = vips_target_new_to_memory(); + } /* printf("wtiff_layer_init: sub = %d, width = %d, height = %d\n", @@ -553,7 +582,7 @@ wtiff_embed_xmp(Wtiff *wtiff, TIFF *tif) if (vips_image_get_blob(wtiff->ready, VIPS_META_XMP_NAME, &data, &size)) return -1; - TIFFSetField(tif, TIFFTAG_XMLPACKET, size, data); + set_data64(tif, TIFFTAG_XMLPACKET, size, data); #ifdef DEBUG printf("vips2tiff: attached XMP from meta\n"); @@ -578,14 +607,14 @@ wtiff_embed_iptc(Wtiff *wtiff, TIFF *tif) * long, not byte. */ if (size & 3) { - g_warning("%s", _("rounding up IPTC data length")); + g_warning("rounding up IPTC data length"); size /= 4; size += 1; } else size /= 4; - TIFFSetField(tif, TIFFTAG_RICHTIFFIPTC, size, data); + set_data64(tif, TIFFTAG_RICHTIFFIPTC, size, data); #ifdef DEBUG printf("vips2tiff: attached IPTC from meta\n"); @@ -600,16 +629,16 @@ wtiff_embed_photoshop(Wtiff *wtiff, TIFF *tif) const void *data; size_t size; - if (!vips_image_get_typeof(wtiff->ready, VIPS_META_PHOTOSHOP_NAME)) - return 0; - if (vips_image_get_blob(wtiff->ready, VIPS_META_PHOTOSHOP_NAME, - &data, &size)) - return -1; - TIFFSetField(tif, TIFFTAG_PHOTOSHOP, size, data); + if (vips_image_get_typeof(wtiff->ready, VIPS_META_PHOTOSHOP_NAME)) { + if (vips_image_get_blob(wtiff->ready, VIPS_META_PHOTOSHOP_NAME, + &data, &size)) + return -1; + set_data64(tif, TIFFTAG_PHOTOSHOP, size, data); #ifdef DEBUG - printf("vips2tiff: attached photoshop data from meta\n"); + printf("vips2tiff: attached %zd bytes of photoshop data\n", size); #endif /*DEBUG*/ + } return 0; } @@ -862,10 +891,10 @@ wtiff_write_header(Wtiff *wtiff, Layer *layer) if (wtiff->compression == COMPRESSION_ZSTD) { // Set zstd compression level - only accept valid values (1-22) if (wtiff->level) - TIFFSetField(tif, TIFFTAG_ZSTD_LEVEL, VIPS_CLIP(1, wtiff->level, 22)); - if (wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE) TIFFSetField(tif, - TIFFTAG_PREDICTOR, wtiff->predictor); + TIFFTAG_ZSTD_LEVEL, VIPS_CLIP(1, wtiff->level, 22)); + if (wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE) + TIFFSetField(tif, TIFFTAG_PREDICTOR, wtiff->predictor); } #endif /*HAVE_TIFF_COMPRESSION_WEBP*/ @@ -937,8 +966,7 @@ wtiff_write_header(Wtiff *wtiff, Layer *layer) int alpha_bands; - TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, - wtiff->ready->Bands); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, wtiff->ready->Bands); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, vips_format_sizeof(wtiff->ready->BandFmt) << 3); @@ -1086,7 +1114,7 @@ wtiff_write_header(Wtiff *wtiff, Layer *layer) printf("setting %zd bytes of table data\n", length); #endif /*DEBUG*/ - TIFFSetField(tif, TIFFTAG_JPEGTABLES, length, buffer); + set_data64(tif, TIFFTAG_JPEGTABLES, length, buffer); g_free(buffer); } @@ -1146,7 +1174,8 @@ wtiff_allocate_layers(Wtiff *wtiff) vips__region_no_ownership(layer->copy); layer->tif = vips__tiff_openout_target(layer->target, - wtiff->bigtiff); + wtiff->bigtiff, wtiff_handler_error, + wtiff_handler_warning, wtiff); if (!layer->tif) return -1; } @@ -1199,7 +1228,7 @@ wtiff_free(Wtiff *wtiff) VIPS_UNREF(wtiff->ready); VIPS_FREE(wtiff->tbuf); - VIPS_FREEF(vips_g_mutex_free, wtiff->lock); + g_mutex_clear(&wtiff->lock); VIPS_FREE(wtiff); } @@ -1366,7 +1395,7 @@ wtiff_new(VipsImage *input, VipsTarget *target, wtiff->page_number = 0; wtiff->n_pages = 1; wtiff->image_height = input->Ysize; - wtiff->lock = vips_g_mutex_new(); + g_mutex_init(&wtiff->lock); /* Any pre-processing on the image. */ @@ -1456,8 +1485,7 @@ wtiff_new(VipsImage *input, VipsTarget *target, !(wtiff->bitdepth == 1 || wtiff->bitdepth == 2 || wtiff->bitdepth == 4)) { - g_warning("%s", - _("bitdepth 1, 2 or 4 only -- disabling bitdepth")); + g_warning("bitdepth 1, 2 or 4 only -- disabling bitdepth"); wtiff->bitdepth = 0; } @@ -1468,16 +1496,14 @@ wtiff_new(VipsImage *input, VipsTarget *target, !(wtiff->ready->Coding == VIPS_CODING_NONE && wtiff->ready->BandFmt == VIPS_FORMAT_UCHAR && wtiff->ready->Bands == 1)) { - g_warning("%s", - ("can only set bitdepth for 1-band uchar and " - "3-band float lab -- disabling bitdepth")); + g_warning("can only set bitdepth for 1-band uchar and " + "3-band float lab -- disabling bitdepth"); wtiff->bitdepth = 0; } if (wtiff->bitdepth && wtiff->compression == COMPRESSION_JPEG) { - g_warning("%s", - _("can't have <8 bit JPEG -- disabling JPEG")); + g_warning("can't have <8 bit JPEG -- disabling JPEG"); wtiff->compression = COMPRESSION_NONE; } @@ -1487,9 +1513,8 @@ wtiff_new(VipsImage *input, VipsTarget *target, (wtiff->ready->Coding != VIPS_CODING_NONE || vips_band_format_iscomplex(wtiff->ready->BandFmt) || wtiff->ready->Bands > 2)) { - g_warning("%s", - _("can only save non-complex greyscale images " - "as miniswhite -- disabling miniswhite")); + g_warning("can only save non-complex greyscale images " + "as miniswhite -- disabling miniswhite"); wtiff->miniswhite = FALSE; } @@ -1764,11 +1789,11 @@ wtiff_row_add_tile(WtiffRow *row, tile->buffer = buffer; tile->length = length; - g_mutex_lock(row->wtiff->lock); + g_mutex_lock(&row->wtiff->lock); row->tiles = g_slist_prepend(row->tiles, tile); - g_mutex_unlock(row->wtiff->lock); + g_mutex_unlock(&row->wtiff->lock); return 0; } @@ -2277,7 +2302,7 @@ wtiff_write_lines(Wtiff *wtiff, VipsRegion *region, VipsRect *lines) */ #define CopyField(tag, v) \ if (TIFFGetField(in, tag, &v)) \ - TIFFSetField(out, tag, v) + TIFFSetField(out, tag, v) static int wtiff_copy_tiles(Wtiff *wtiff, TIFF *out, TIFF *in) @@ -2295,7 +2320,7 @@ wtiff_copy_tiles(Wtiff *wtiff, TIFF *out, TIFF *in) * simpler than searching every page for the largest tile with * TIFFTAG_TILEBYTECOUNTS. */ - tile_size = 2 * wtiff->tls * wtiff->tileh; + tile_size = (tsize_t) 2 * wtiff->tls * wtiff->tileh; buf = vips_malloc(NULL, tile_size); @@ -2401,7 +2426,8 @@ wtiff_gather(Wtiff *wtiff) if (!(source = vips_source_new_from_target(layer->target))) return -1; - if (!(in = vips__tiff_openin_source(source))) { + if (!(in = vips__tiff_openin_source(source, wtiff_handler_error, + wtiff_handler_warning, NULL, FALSE))) { VIPS_UNREF(source); return -1; } diff --git a/libvips/foreign/vipsload.c b/libvips/foreign/vipsload.c index 5678a6cb3a..7c04c20f65 100644 --- a/libvips/foreign/vipsload.c +++ b/libvips/foreign/vipsload.c @@ -325,11 +325,12 @@ vips_foreign_load_vips_source_init(VipsForeignLoadVipsSource *source) * vips_vipsload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Read in a vips image. * - * See also: vips_vipssave(). + * ::: seealso + * [method@Image.vipssave]. * * Returns: 0 on success, -1 on error. */ @@ -350,9 +351,9 @@ vips_vipsload(const char *filename, VipsImage **out, ...) * vips_vipsload_source: * @source: source to load from * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Exactly as vips_vipsload(), but read from a source. + * Exactly as [ctor@Image.vipsload], but read from a source. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index b5dc7a8bae..2dc009ebce 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -1149,8 +1149,7 @@ write_vips(Write *write, color_type = PNG_COLOR_TYPE_PALETTE; #else if (palette) - g_warning("%s", - _("ignoring palette (no quantisation support)")); + g_warning("ignoring palette (no quantisation support)"); #endif /*HAVE_QUANTIZATION*/ interlace_type = interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE; @@ -1166,7 +1165,7 @@ write_vips(Write *write, /* Set resolution. libpng uses pixels per meter. */ png_set_pHYs(write->pPng, write->pInfo, - VIPS_RINT(in->Xres * 1000), VIPS_RINT(in->Yres * 1000), + rint(in->Xres * 1000), rint(in->Yres * 1000), PNG_RESOLUTION_METER); /* Metadata diff --git a/libvips/foreign/vipssave.c b/libvips/foreign/vipssave.c index 9fbf7edade..6c496b8d0b 100644 --- a/libvips/foreign/vipssave.c +++ b/libvips/foreign/vipssave.c @@ -143,7 +143,7 @@ vips_foreign_save_vips_class_init(VipsForeignSaveVipsClass *class) foreign_class->suffs = vips__suffs; - save_class->saveable = VIPS_SAVEABLE_ANY; + save_class->saveable = VIPS_FOREIGN_SAVEABLE_ANY; for (i = 0; i < VIPS_CODING_LAST; i++) save_class->coding[i] = TRUE; } @@ -266,11 +266,12 @@ vips_foreign_save_vips_target_init(VipsForeignSaveVipsTarget *target) * vips_vipssave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Write @in to @filename in VIPS format. * - * See also: vips_vipsload(). + * ::: seealso + * [ctor@Image.vipsload]. * * Returns: 0 on success, -1 on error. */ @@ -291,9 +292,9 @@ vips_vipssave(VipsImage *in, const char *filename, ...) * vips_vipssave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * As vips_vipssave(), but save to a target. + * As [method@Image.vipssave], but save to a target. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/webp2vips.c b/libvips/foreign/webp2vips.c index 03cd483c13..fbdf87670d 100644 --- a/libvips/foreign/webp2vips.c +++ b/libvips/foreign/webp2vips.c @@ -305,7 +305,7 @@ vips_image_paint_image(VipsImage *frame, } else memcpy((char *) q, (char *) p, - ovl.width * ps); + (size_t) ovl.width * ps); p += VIPS_IMAGE_SIZEOF_LINE(sub); q += VIPS_IMAGE_SIZEOF_LINE(frame); @@ -486,7 +486,7 @@ read_header(Read *read, VipsImage *out) /* webp uses ms for delays, gif uses centiseconds. */ vips_image_set_int(out, "gif-delay", - VIPS_RINT(read->delays[0] / 10.0)); + rint(read->delays[0] / 10.0)); } WebPDemuxReleaseIterator(&iter); @@ -510,8 +510,8 @@ read_header(Read *read, VipsImage *out) /* We round-to-nearest cf. pdfload etc. */ - read->frame_width = VIPS_RINT(read->canvas_width * read->scale); - read->frame_height = VIPS_RINT(read->canvas_height * read->scale); + read->frame_width = rint(read->canvas_width * read->scale); + read->frame_height = rint(read->canvas_height * read->scale); #ifdef DEBUG printf("webp2vips: canvas_width = %d\n", read->canvas_width); @@ -656,10 +656,10 @@ read_next_frame(Read *read) * since we need the same rules as the overall image scale, or we'll * sometimes have missing pixels on edges. */ - area.left = VIPS_RINT(read->iter.x_offset * read->scale); - area.top = VIPS_RINT(read->iter.y_offset * read->scale); - area.width = VIPS_RINT(read->iter.width * read->scale); - area.height = VIPS_RINT(read->iter.height * read->scale); + area.left = rint(read->iter.x_offset * read->scale); + area.top = rint(read->iter.y_offset * read->scale); + area.width = rint(read->iter.width * read->scale); + area.height = rint(read->iter.height * read->scale); /* Dispose from the previous frame. */ diff --git a/libvips/foreign/webpload.c b/libvips/foreign/webpload.c index 9438e44b9d..8ddda46250 100644 --- a/libvips/foreign/webpload.c +++ b/libvips/foreign/webpload.c @@ -104,7 +104,7 @@ vips_foreign_load_webp_build(VipsObject *object) if (!vips_object_argument_isset(VIPS_OBJECT(webp), "scale") && vips_object_argument_isset(VIPS_OBJECT(webp), "shrink") && webp->shrink != 0) - webp->scale = 1.0 / webp->shrink; + webp->scale = 1.0 / webp->shrink; // FIXME: Invalidates operation cache if (VIPS_OBJECT_CLASS(vips_foreign_load_webp_parent_class)->build(object)) return -1; @@ -439,13 +439,7 @@ vips_foreign_load_webp_buffer_init(VipsForeignLoadWebpBuffer *buffer) * vips_webpload: * @filename: file to load * @out: (out): decompressed image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, page (frame) to read - * * @n: %gint, load this many pages - * * @scale: %gdouble, scale by this much on load + * @...: `NULL`-terminated list of optional named arguments * * Read a WebP file into a VIPS image. * @@ -453,7 +447,7 @@ vips_foreign_load_webp_buffer_init(VipsForeignLoadWebpBuffer *buffer) * * Use @n to select the number of pages to render. The default is 1. Pages are * rendered in a vertical column, with each individual page aligned to the - * left. Set to -1 to mean "until the end of the document". Use vips_grid() + * left. Set to -1 to mean "until the end of the document". Use [method@Image.grid] * to change page layout. * * Use @scale to specify a scale-on-load factor. For example, 2.0 to double @@ -462,7 +456,13 @@ vips_foreign_load_webp_buffer_init(VipsForeignLoadWebpBuffer *buffer) * * The loader supports ICC, EXIF and XMP metadata. * - * See also: vips_image_new_from_file(). + * ::: tip "Optional arguments" + * * @page: `gint`, page (frame) to read + * * @n: `gint`, load this many pages + * * @scale: `gdouble`, scale by this much on load + * + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, -1 on error. */ @@ -484,21 +484,21 @@ vips_webpload(const char *filename, VipsImage **out, ...) * @buf: (array length=len) (element-type guint8): memory area to load * @len: (type gsize): size of memory area * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @page: %gint, page (frame) to read - * * @n: %gint, load this many pages - * * @scale: %gdouble, scale by this much on load + * @...: `NULL`-terminated list of optional named arguments * * Read a WebP-formatted memory block into a VIPS image. Exactly as - * vips_webpload(), but read from a memory buffer. + * [ctor@Image.webpload], but read from a memory buffer. * * You must not free the buffer while @out is active. The - * #VipsObject::postclose signal on @out is a good place to free. + * [signal@Object::postclose] signal on @out is a good place to free. + * + * ::: tip "Optional arguments" + * * @page: `gint`, page (frame) to read + * * @n: `gint`, load this many pages + * * @scale: `gdouble`, scale by this much on load * - * See also: vips_webpload() + * ::: seealso + * [ctor@Image.webpload] * * Returns: 0 on success, -1 on error. */ @@ -526,17 +526,17 @@ vips_webpload_buffer(void *buf, size_t len, VipsImage **out, ...) * vips_webpload_source: * @source: source to load from * @out: (out): image to write - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @page: %gint, page (frame) to read - * * @n: %gint, load this many pages - * * @scale: %gdouble, scale by this much on load + * Exactly as [ctor@Image.webpload], but read from a source. * - * Exactly as vips_webpload(), but read from a source. + * ::: tip "Optional arguments" + * * @page: `gint`, page (frame) to read + * * @n: `gint`, load this many pages + * * @scale: `gdouble`, scale by this much on load * - * See also: vips_webpload() + * ::: seealso + * [ctor@Image.webpload] * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/foreign/webpsave.c b/libvips/foreign/webpsave.c index 452a77d7cc..2ad31c4916 100644 --- a/libvips/foreign/webpsave.c +++ b/libvips/foreign/webpsave.c @@ -294,7 +294,25 @@ vips_foreign_save_webp_write_webp_image(VipsForeignSaveWebp *webp, return 0; } -/* We have a complete frame --- write! +static int +vips_foreign_save_webp_get_delay(VipsForeignSaveWebp *webp, int page_number) +{ + int delay; + + if (webp->delay && + page_number < webp->delay_length) + delay = webp->delay[page_number]; + else + // the old gif delay field was in centiseconds, so convert to ms + delay = webp->gif_delay * 10; + + /* Force frames with a small or no duration to 100ms for consistency + * with web browsers and other transcoding tools. + */ + return delay <= 10 ? 100 : delay; +} + +/* We have a complete frame -- write! */ static int vips_foreign_save_webp_write_frame(VipsForeignSaveWebp *webp) @@ -318,11 +336,8 @@ vips_foreign_save_webp_write_frame(VipsForeignSaveWebp *webp) /* Adjust current timestamp */ - if (webp->delay && - webp->page_number < webp->delay_length) - webp->timestamp_ms += webp->delay[webp->page_number]; - else - webp->timestamp_ms += webp->gif_delay * 10; + webp->timestamp_ms += + vips_foreign_save_webp_get_delay(webp, webp->page_number); } else { /* Single image write @@ -355,7 +370,7 @@ vips_foreign_save_webp_sink_disc(VipsRegion *region, VipsRect *area, void *a) memcpy(webp->frame_bytes + area->width * webp->write_y * save->ready->Bands, VIPS_REGION_ADDR(region, 0, area->top + i), - area->width * save->ready->Bands); + (size_t) area->width * save->ready->Bands); webp->write_y += 1; @@ -636,7 +651,6 @@ vips_foreign_save_webp_init_anim_enc(VipsForeignSaveWebp *webp) int page_height = vips_image_get_page_height(save->ready); WebPAnimEncoderOptions anim_config; - int i; /* Init config for animated write */ @@ -659,31 +673,19 @@ vips_foreign_save_webp_init_anim_enc(VipsForeignSaveWebp *webp) /* Get delay array * * There might just be the old gif-delay field. This is centiseconds. + * New images have an array of ints giving millisecond durations. */ webp->gif_delay = 10; if (vips_image_get_typeof(save->ready, "gif-delay") && vips_image_get_int(save->ready, "gif-delay", &webp->gif_delay)) return -1; - /* New images have an array of ints instead. - */ webp->delay = NULL; if (vips_image_get_typeof(save->ready, "delay") && vips_image_get_array_int(save->ready, "delay", &webp->delay, &webp->delay_length)) return -1; - /* Force frames with a small or no duration to 100ms - * to be consistent with web browsers and other - * transcoding tools. - */ - if (webp->gif_delay <= 1) - webp->gif_delay = 10; - - for (i = 0; i < webp->delay_length; i++) - if (webp->delay[i] <= 10) - webp->delay[i] = 100; - return 0; } @@ -819,7 +821,8 @@ vips_foreign_save_webp_class_init(VipsForeignSaveWebpClass *class) foreign_class->suffs = vips__save_webp_suffs; - save_class->saveable = VIPS_SAVEABLE_RGBA_ONLY; + save_class->saveable = + VIPS_FOREIGN_SAVEABLE_RGB | VIPS_FOREIGN_SAVEABLE_ALPHA; save_class->format_table = bandfmt_webp; VIPS_ARG_INT(class, "Q", 10, @@ -1168,24 +1171,7 @@ vips_foreign_save_webp_mime_init(VipsForeignSaveWebpMime *mime) * vips_webpsave: (method) * @in: image to save * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @lossless: %gboolean, enables lossless compression - * * @preset: #VipsForeignWebpPreset, choose lossy compression preset - * * @smart_subsample: %gboolean, enables high quality chroma subsampling - * * @smart_deblock: %gboolean, enables auto-adjusting of the deblocking filter - * * @near_lossless: %gboolean, preprocess in lossless mode (controlled by Q) - * * @alpha_q: %gint, set alpha quality in lossless mode - * * @effort: %gint, level of CPU effort to reduce file size - * * @target_size: %gint, desired target size in bytes - * * @passes: %gint, number of entropy-analysis passes - * * @min_size: %gboolean, minimise size - * * @mixed: %gboolean, allow both lossy and lossless encoding - * * @kmin: %gint, minimum number of frames between keyframes - * * @kmax: %gint, maximum number of frames between keyframes + * @...: `NULL`-terminated list of optional named arguments * * Write an image to a file in WebP format. * @@ -1194,7 +1180,7 @@ vips_foreign_save_webp_mime_init(VipsForeignSaveWebpMime *mime) * default 75. * * Use @preset to hint the image type to the lossy compressor. The default is - * #VIPS_FOREIGN_WEBP_PRESET_DEFAULT. + * [enum@Vips.ForeignWebpPreset.DEFAULT]. * * Set @smart_subsample to enable high quality chroma subsampling. * @@ -1233,7 +1219,26 @@ vips_foreign_save_webp_mime_init(VipsForeignSaveWebpMime *mime) * Use the metadata items `loop` and `delay` to set the number of * loops for the animation and the frame delays. * - * See also: vips_webpload(), vips_image_write_to_file(). + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @lossless: `gboolean`, enables lossless compression + * * @preset: [enum@ForeignWebpPreset], choose lossy compression preset + * * @smart_subsample: `gboolean`, enables high quality chroma subsampling + * * @smart_deblock: `gboolean`, enables auto-adjusting of the deblocking + * filter + * * @near_lossless: `gboolean`, preprocess in lossless mode (controlled + * by Q) + * * @alpha_q: `gint`, set alpha quality in lossless mode + * * @effort: `gint`, level of CPU effort to reduce file size + * * @target_size: `gint`, desired target size in bytes + * * @passes: `gint`, number of entropy-analysis passes + * * @min_size: `gboolean`, minimise size + * * @mixed: `gboolean`, allow both lossy and lossless encoding + * * @kmin: `gint`, minimum number of frames between keyframes + * * @kmax: `gint`, maximum number of frames between keyframes + * + * ::: seealso + * [ctor@Image.webpload], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -1255,32 +1260,34 @@ vips_webpsave(VipsImage *in, const char *filename, ...) * @in: image to save * @buf: (out) (array length=len) (element-type guint8): return output buffer here * @len: return output length here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @Q: %gint, quality factor - * * @lossless: %gboolean, enables lossless compression - * * @preset: #VipsForeignWebpPreset, choose lossy compression preset - * * @smart_subsample: %gboolean, enables high quality chroma subsampling - * * @smart_deblock: %gboolean, enables auto-adjusting of the deblocking filter - * * @near_lossless: %gboolean, preprocess in lossless mode (controlled by Q) - * * @alpha_q: %gint, set alpha quality in lossless mode - * * @effort: %gint, level of CPU effort to reduce file size - * * @target_size: %gint, desired target size in bytes - * * @passes: %gint, number of entropy-analysis passes - * * @min_size: %gboolean, minimise size - * * @mixed: %gboolean, allow both lossy and lossless encoding - * * @kmin: %gint, minimum number of frames between keyframes - * * @kmax: %gint, maximum number of frames between keyframes - * - * As vips_webpsave(), but save to a memory buffer. + * As [method@Image.webpsave], but save to a memory buffer. * * The address of the buffer is returned in @buf, the length of the buffer in - * @len. You are responsible for freeing the buffer with g_free() when you + * @len. You are responsible for freeing the buffer with [func@GLib.free] when you * are done with it. * - * See also: vips_webpsave(). + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @lossless: `gboolean`, enables lossless compression + * * @preset: [enum@ForeignWebpPreset], choose lossy compression preset + * * @smart_subsample: `gboolean`, enables high quality chroma subsampling + * * @smart_deblock: `gboolean`, enables auto-adjusting of the deblocking + * filter + * * @near_lossless: `gboolean`, preprocess in lossless mode (controlled + * by Q) + * * @alpha_q: `gint`, set alpha quality in lossless mode + * * @effort: `gint`, level of CPU effort to reduce file size + * * @target_size: `gint`, desired target size in bytes + * * @passes: `gint`, number of entropy-analysis passes + * * @min_size: `gboolean`, minimise size + * * @mixed: `gboolean`, allow both lossy and lossless encoding + * * @kmin: `gint`, minimum number of frames between keyframes + * * @kmax: `gint`, maximum number of frames between keyframes + * + * ::: seealso + * [method@Image.webpsave]. * * Returns: 0 on success, -1 on error. */ @@ -1315,28 +1322,30 @@ vips_webpsave_buffer(VipsImage *in, void **buf, size_t *len, ...) /** * vips_webpsave_mime: (method) * @in: image to save - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * As [method@Image.webpsave], but save as a mime webp on stdout. * - * * @Q: %gint, quality factor - * * @lossless: %gboolean, enables lossless compression - * * @preset: #VipsForeignWebpPreset, choose lossy compression preset - * * @smart_subsample: %gboolean, enables high quality chroma subsampling - * * @smart_deblock: %gboolean, enables auto-adjusting of the deblocking filter - * * @near_lossless: %gboolean, preprocess in lossless mode (controlled by Q) - * * @alpha_q: %gint, set alpha quality in lossless mode - * * @effort: %gint, level of CPU effort to reduce file size - * * @target_size: %gint, desired target size in bytes - * * @passes: %gint, number of entropy-analysis passes - * * @min_size: %gboolean, minimise size - * * @mixed: %gboolean, allow both lossy and lossless encoding - * * @kmin: %gint, minimum number of frames between keyframes - * * @kmax: %gint, maximum number of frames between keyframes + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @lossless: `gboolean`, enables lossless compression + * * @preset: [enum@ForeignWebpPreset], choose lossy compression preset + * * @smart_subsample: `gboolean`, enables high quality chroma subsampling + * * @smart_deblock: `gboolean`, enables auto-adjusting of the deblocking + * filter + * * @near_lossless: `gboolean`, preprocess in lossless mode (controlled + * by Q) + * * @alpha_q: `gint`, set alpha quality in lossless mode + * * @effort: `gint`, level of CPU effort to reduce file size + * * @target_size: `gint`, desired target size in bytes + * * @passes: `gint`, number of entropy-analysis passes + * * @min_size: `gboolean`, minimise size + * * @mixed: `gboolean`, allow both lossy and lossless encoding + * * @kmin: `gint`, minimum number of frames between keyframes + * * @kmax: `gint`, maximum number of frames between keyframes * - * As vips_webpsave(), but save as a mime webp on stdout. - * - * See also: vips_webpsave(), vips_image_write_to_file(). + * ::: seealso + * [method@Image.webpsave], [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error. */ @@ -1357,28 +1366,30 @@ vips_webpsave_mime(VipsImage *in, ...) * vips_webpsave_target: (method) * @in: image to save * @target: save image to this target - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @Q: %gint, quality factor - * * @lossless: %gboolean, enables lossless compression - * * @preset: #VipsForeignWebpPreset, choose lossy compression preset - * * @smart_subsample: %gboolean, enables high quality chroma subsampling - * * @smart_deblock: %gboolean, enables auto-adjusting of the deblocking filter - * * @near_lossless: %gboolean, preprocess in lossless mode (controlled by Q) - * * @alpha_q: %gint, set alpha quality in lossless mode - * * @effort: %gint, level of CPU effort to reduce file size - * * @target_size: %gint, desired target size in bytes - * * @passes: %gint, number of entropy-analysis passes - * * @min_size: %gboolean, minimise size - * * @mixed: %gboolean, allow both lossy and lossless encoding - * * @kmin: %gint, minimum number of frames between keyframes - * * @kmax: %gint, maximum number of frames between keyframes + * As [method@Image.webpsave], but save to a target. * - * As vips_webpsave(), but save to a target. + * ::: tip "Optional arguments" + * * @Q: `gint`, quality factor + * * @lossless: `gboolean`, enables lossless compression + * * @preset: [enum@ForeignWebpPreset], choose lossy compression preset + * * @smart_subsample: `gboolean`, enables high quality chroma subsampling + * * @smart_deblock: `gboolean`, enables auto-adjusting of the deblocking + * filter + * * @near_lossless: `gboolean`, preprocess in lossless mode (controlled + * by Q) + * * @alpha_q: `gint`, set alpha quality in lossless mode + * * @effort: `gint`, level of CPU effort to reduce file size + * * @target_size: `gint`, desired target size in bytes + * * @passes: `gint`, number of entropy-analysis passes + * * @min_size: `gboolean`, minimise size + * * @mixed: `gboolean`, allow both lossy and lossless encoding + * * @kmin: `gint`, minimum number of frames between keyframes + * * @kmax: `gint`, maximum number of frames between keyframes * - * See also: vips_webpsave(). + * ::: seealso + * [method@Image.webpsave]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/freqfilt/freqfilt.c b/libvips/freqfilt/freqfilt.c index 41bc90dc71..7b0603de6c 100644 --- a/libvips/freqfilt/freqfilt.c +++ b/libvips/freqfilt/freqfilt.c @@ -49,17 +49,6 @@ #include "pfreqfilt.h" -/** - * SECTION: freqfilt - * @short_description: fourier transforms and frequency-domin filters - * @stability: Stable - * @see_also: image - * @include: vips/vips.h - * - * To and from Fourier space, filter in Fourier space, convert Fourier-space - * images to a displayable form. - */ - G_DEFINE_ABSTRACT_TYPE(VipsFreqfilt, vips_freqfilt, VIPS_TYPE_OPERATION); static int @@ -127,8 +116,8 @@ vips_freqfilt_init(VipsFreqfilt *freqfilt) * partial bandjoin -> * output pipeline * - * vips__fftproc() needs to just call VipsFftProcessFn directly for 1 band images, - * so we can't cache the output in this fn. + * vips__fftproc() needs to just call VipsFftProcessFn directly for 1 band + * images, so we can't cache the output in this fn. */ int vips__fftproc(VipsObject *context, diff --git a/libvips/freqfilt/freqmult.c b/libvips/freqfilt/freqmult.c index 8f586d71eb..5d5df8bb81 100644 --- a/libvips/freqfilt/freqmult.c +++ b/libvips/freqfilt/freqmult.c @@ -143,7 +143,7 @@ vips_freqmult_init(VipsFreqmult *freqmult) * @in: input image * @mask: mask image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Multiply @in by @mask in Fourier space. * @@ -151,7 +151,8 @@ vips_freqmult_init(VipsFreqmult *freqmult) * transformed back to real space. If @in is already a complex image, just * multiply then inverse transform. * - * See also: vips_invfft(), vips_mask_ideal(). + * ::: seealso + * [method@Image.invfft], [ctor@Image.mask_ideal]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/freqfilt/fwfft.c b/libvips/freqfilt/fwfft.c index daadc29271..dfab2b728b 100644 --- a/libvips/freqfilt/fwfft.c +++ b/libvips/freqfilt/fwfft.c @@ -95,23 +95,7 @@ G_DEFINE_TYPE(VipsFwfft, vips_fwfft, VIPS_TYPE_FREQFILT); /* Everything in fftw3 except execute has to be behind a mutex. */ -GMutex *vips__fft_lock = NULL; - -static void * -vips__fft_thread_init(void *data) -{ - vips__fft_lock = vips_g_mutex_new(); - - return NULL; -} - -void -vips__fft_init(void) -{ - static GOnce once = G_ONCE_INIT; - - VIPS_ONCE(&once, vips__fft_thread_init, NULL); -} +GMutex vips__fft_lock; /* Real to complex forward transform. */ @@ -152,23 +136,23 @@ rfwfft1(VipsObject *object, VipsImage *in, VipsImage **out) if (!(half_complex = VIPS_ARRAY(fwfft, in->Ysize * half_width * 2, double))) return -1; - g_mutex_lock(vips__fft_lock); + g_mutex_lock(&vips__fft_lock); if (!(plan = fftw_plan_dft_r2c_2d(in->Ysize, in->Xsize, planner_scratch, (fftw_complex *) half_complex, 0))) { - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); vips_error(class->nickname, "%s", _("unable to create transform plan")); return -1; } - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); fftw_execute_dft_r2c(plan, (double *) t[1]->data, (fftw_complex *) half_complex); - g_mutex_lock(vips__fft_lock); + g_mutex_lock(&vips__fft_lock); fftw_destroy_plan(plan); - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); /* Write to out as another memory buffer. */ @@ -271,25 +255,25 @@ cfwfft1(VipsObject *object, VipsImage *in, VipsImage **out) /* Make the plan for the transform. */ - g_mutex_lock(vips__fft_lock); + g_mutex_lock(&vips__fft_lock); if (!(plan = fftw_plan_dft_2d(in->Ysize, in->Xsize, (fftw_complex *) planner_scratch, (fftw_complex *) planner_scratch, FFTW_FORWARD, 0))) { - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); vips_error(class->nickname, "%s", _("unable to create transform plan")); return -1; } - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); fftw_execute_dft(plan, (fftw_complex *) t[1]->data, (fftw_complex *) t[1]->data); - g_mutex_lock(vips__fft_lock); + g_mutex_lock(&vips__fft_lock); fftw_destroy_plan(plan); - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); /* Write to out as another memory buffer. */ @@ -332,8 +316,6 @@ vips_fwfft_build(VipsObject *object) VipsImage *in; - vips__fft_init(); - if (VIPS_OBJECT_CLASS(vips_fwfft_parent_class)->build(object)) return -1; @@ -381,14 +363,15 @@ vips_fwfft_init(VipsFwfft *fwfft) * vips_fwfft: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Transform an image to Fourier space. * * VIPS uses the fftw Fourier Transform library. If this library was not * available when VIPS was configured, these functions will fail. * - * See also: vips_invfft(). + * ::: seealso + * [method@Image.invfft]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/freqfilt/invfft.c b/libvips/freqfilt/invfft.c index 874df553c5..79052c57c0 100644 --- a/libvips/freqfilt/invfft.c +++ b/libvips/freqfilt/invfft.c @@ -113,25 +113,25 @@ cinvfft1(VipsObject *object, VipsImage *in, VipsImage **out) if (!(planner_scratch = VIPS_ARRAY(invfft, VIPS_IMAGE_N_PELS(in) * 2, double))) return -1; - g_mutex_lock(vips__fft_lock); + g_mutex_lock(&vips__fft_lock); if (!(plan = fftw_plan_dft_2d(in->Ysize, in->Xsize, (fftw_complex *) planner_scratch, (fftw_complex *) planner_scratch, FFTW_BACKWARD, 0))) { - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); vips_error(class->nickname, "%s", _("unable to create transform plan")); return -1; } - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); fftw_execute_dft(plan, (fftw_complex *) (*out)->data, (fftw_complex *) (*out)->data); - g_mutex_lock(vips__fft_lock); + g_mutex_lock(&vips__fft_lock); fftw_destroy_plan(plan); - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); (*out)->Type = VIPS_INTERPRETATION_B_W; @@ -194,23 +194,23 @@ rinvfft1(VipsObject *object, VipsImage *in, VipsImage **out) if (!(planner_scratch = VIPS_ARRAY(invfft, t[1]->Ysize * half_width * 2, double))) return -1; - g_mutex_lock(vips__fft_lock); + g_mutex_lock(&vips__fft_lock); if (!(plan = fftw_plan_dft_c2r_2d(t[1]->Ysize, t[1]->Xsize, (fftw_complex *) planner_scratch, (double *) (*out)->data, 0))) { - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); vips_error(class->nickname, "%s", _("unable to create transform plan")); return -1; } - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); fftw_execute_dft_c2r(plan, (fftw_complex *) half_complex, (double *) (*out)->data); - g_mutex_lock(vips__fft_lock); + g_mutex_lock(&vips__fft_lock); fftw_destroy_plan(plan); - g_mutex_unlock(vips__fft_lock); + g_mutex_unlock(&vips__fft_lock); return 0; } @@ -224,8 +224,6 @@ vips_invfft_build(VipsObject *object) VipsImage *in; - vips__fft_init(); - if (VIPS_OBJECT_CLASS(vips_invfft_parent_class)->build(object)) return -1; @@ -284,19 +282,21 @@ vips_invfft_init(VipsInvfft *invfft) * vips_invfft: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @real: only output the real part + * Transform an image from Fourier space to real space. * - * Transform an image from Fourier space to real space. The result is complex. - * If you are OK with a real result, set @real, it's quicker. + * The result is complex. If you are OK with a real result, set @real, + * it's quicker. * * VIPS uses the fftw Fourier Transform library. If this library was not * available when VIPS was configured, these functions will fail. * - * See also: vips_fwfft(). + * ::: tip "Optional arguments" + * * @real: `gboolean`, only output the real part + * + * ::: seealso + * [method@Image.fwfft]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/freqfilt/pfreqfilt.h b/libvips/freqfilt/pfreqfilt.h index 768b1e316f..097d1cdb8c 100644 --- a/libvips/freqfilt/pfreqfilt.h +++ b/libvips/freqfilt/pfreqfilt.h @@ -37,9 +37,7 @@ extern "C" { /* All fftw3 calls except execute() need to be locked. */ -extern GMutex *vips__fft_lock; - -void vips__fft_init(void); +extern GMutex vips__fft_lock; #define VIPS_TYPE_FREQFILT (vips_freqfilt_get_type()) #define VIPS_FREQFILT(obj) \ diff --git a/libvips/freqfilt/phasecor.c b/libvips/freqfilt/phasecor.c index 6671425a80..39d2a1bf30 100644 --- a/libvips/freqfilt/phasecor.c +++ b/libvips/freqfilt/phasecor.c @@ -120,16 +120,17 @@ vips_phasecor_init(VipsPhasecor *phasecor) } /** - * vips_phasecor: + * vips_phasecor: (method) * @in1: first input image * @in2: second input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Convert the two input images to Fourier space, calculate phase-correlation, * back to real space. * - * See also: vips_fwfft(), vips_cross_phase(), + * ::: seealso + * [method@Image.fwfft], [method@Image.cross_phase], * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/freqfilt/spectrum.c b/libvips/freqfilt/spectrum.c index 7caf60b531..31ac6792e0 100644 --- a/libvips/freqfilt/spectrum.c +++ b/libvips/freqfilt/spectrum.c @@ -110,14 +110,16 @@ vips_spectrum_init(VipsSpectrum *spectrum) * vips_spectrum: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Make a displayable (ie. 8-bit unsigned int) power spectrum. * * If @in is non-complex, it is transformed to Fourier space. Then the - * absolute value is passed through vips_scale() in log mode, and vips_wrap(). + * absolute value is passed through [method@Image.scale] in log mode, and + * [method@Image.wrap]. * - * See also: vips_fwfft(), vips_scale(), vips_wrap(). + * ::: seealso + * [method@Image.fwfft], [method@Image.scale], [method@Image.wrap]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/histogram/case.c b/libvips/histogram/case.c index 109cf7e817..d27e21d2ab 100644 --- a/libvips/histogram/case.c +++ b/libvips/histogram/case.c @@ -280,7 +280,7 @@ vips_casev(VipsImage *index, VipsImage **cases, VipsImage **out, int n, * @cases: (array length=n): array of case images * @out: (out): output image * @n: number of case images - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Use values in @index to select pixels from @cases. * @@ -290,10 +290,11 @@ vips_casev(VipsImage *index, VipsImage **cases, VipsImage **out, int n, * The output image is the same size as @index. Images in @cases are * expanded to the smallest common format and number of bands. * - * Combine this with vips_switch() to make something like a case statement or - * a multi-way vips_ifthenelse(). + * Combine this with [func@Image.switch] to make something like a case + * statement or a multi-way [method@Image.ifthenelse]. * - * See also: vips_maplut(), vips_switch(), vips_ifthenelse(). + * ::: seealso + * [method@Image.maplut], [func@Image.switch], [method@Image.ifthenelse]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histogram/hist_cum.c b/libvips/histogram/hist_cum.c index d51588585c..e7d648f1a8 100644 --- a/libvips/histogram/hist_cum.c +++ b/libvips/histogram/hist_cum.c @@ -170,11 +170,12 @@ vips_hist_cum_init(VipsHistCum *hist_cum) * vips_hist_cum: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Form cumulative histogram. * - * See also: vips_hist_norm(). + * ::: seealso + * [method@Image.hist_norm]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histogram/hist_entropy.c b/libvips/histogram/hist_entropy.c index cadcbab712..bf0126aa5c 100644 --- a/libvips/histogram/hist_entropy.c +++ b/libvips/histogram/hist_entropy.c @@ -130,13 +130,13 @@ vips_hist_entropy_init(VipsHistEntropy *entropy) * vips_hist_entropy: (method) * @in: input histogram * @out: (out): image entropy - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Estimate image entropy from a histogram. Entropy is calculated as: * - * |[ + * ``` * -sum(p * log2(p)) - * ]| + * ``` * * where p is histogram-value / sum-of-histogram-values. * diff --git a/libvips/histogram/hist_equal.c b/libvips/histogram/hist_equal.c index c2f4930bee..f54f7606f4 100644 --- a/libvips/histogram/hist_equal.c +++ b/libvips/histogram/hist_equal.c @@ -140,17 +140,16 @@ vips_hist_equal_init(VipsHistEqual *equal) * vips_hist_equal: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Histogram-equalise @in. * - * * @band: band to equalise - * - * Histogram-equalise @in. Equalise using band @bandno, or if @bandno is -1, + * Equalise using band @bandno, or if @bandno is -1, * equalise bands independently. The output format is always the same as the * input format. * - * See also: + * ::: tip "Optional arguments" + * * @band: `gint`, band to equalise * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histogram/hist_ismonotonic.c b/libvips/histogram/hist_ismonotonic.c index 52c091a03e..ca632b5455 100644 --- a/libvips/histogram/hist_ismonotonic.c +++ b/libvips/histogram/hist_ismonotonic.c @@ -137,7 +137,7 @@ vips_hist_ismonotonic_init(VipsHistIsmonotonic *ismonotonic) * vips_hist_ismonotonic: (method) * @in: lookup-table to test * @out: (out): set non-zero if @in is monotonic - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Test @in for monotonicity. @out is set non-zero if @in is monotonic. * diff --git a/libvips/histogram/hist_local.c b/libvips/histogram/hist_local.c index d0a696d2af..1bb91bb4c1 100644 --- a/libvips/histogram/hist_local.c +++ b/libvips/histogram/hist_local.c @@ -257,7 +257,7 @@ vips_hist_local_generate(VipsRegion *out_region, q[b] = 255 * sum / (local->width * local->height); - /* Adapt histogram --- remove the pels from + /* Adapt histogram -- remove the pels from * the left hand column, add in pels for a * new right-hand column. */ @@ -402,11 +402,7 @@ vips_hist_local_init(VipsHistLocal *local) * @out: (out): output image * @width: width of region * @height: height of region - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @max_slope: maximum brightening + * @...: `NULL`-terminated list of optional named arguments * * Performs local histogram equalisation on @in using a * window of size @width by @height centered on the input pixel. @@ -419,7 +415,11 @@ vips_hist_local_init(VipsHistLocal *local) * performed. A value of 3 is often used. Local histogram equalization with * contrast limiting is usually called CLAHE. * - * See also: vips_hist_equal(). + * ::: tip "Optional arguments" + * * @max_slope: `gint`, maximum brightening + * + * ::: seealso + * [method@Image.hist_equal]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histogram/hist_match.c b/libvips/histogram/hist_match.c index 074ece49a6..780fab68b3 100644 --- a/libvips/histogram/hist_match.c +++ b/libvips/histogram/hist_match.c @@ -180,14 +180,15 @@ vips_hist_match_init(VipsHistMatch *match) * @in: input histogram * @ref: reference histogram * @out: (out): output histogram - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Adjust @in to match @ref. If @in and @ref are normalised * cumulative histograms, @out will be a LUT that adjusts the PDF of the image * from which @in was made to match the PDF of @ref's image. * - * See also: vips_maplut(), vips_hist_find(), vips_hist_norm(), - * vips_hist_cum(). + * ::: seealso + * [method@Image.maplut], [method@Image.hist_find], [method@Image.hist_norm], + * [method@Image.hist_cum]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histogram/hist_norm.c b/libvips/histogram/hist_norm.c index bd6dc649e8..1d2ac279b8 100644 --- a/libvips/histogram/hist_norm.c +++ b/libvips/histogram/hist_norm.c @@ -159,13 +159,14 @@ vips_hist_norm_init(VipsHistNorm *hist_norm) * vips_hist_norm: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Normalise histogram. The maximum of each band becomes equal to the maximum * index, so for example the max for a uchar image becomes 255. * Normalise each band separately. * - * See also: vips_hist_cum(). + * ::: seealso + * [method@Image.hist_cum]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histogram/hist_plot.c b/libvips/histogram/hist_plot.c index 779557d7ef..fb1b8b54ee 100644 --- a/libvips/histogram/hist_plot.c +++ b/libvips/histogram/hist_plot.c @@ -280,7 +280,7 @@ vips_hist_plot_build(VipsObject *object) if (in->BandFmt == VIPS_FORMAT_UCHAR) tsize = 256; else - tsize = VIPS_CEIL(max); + tsize = ceil(max); /* Make sure we don't make a zero height image. */ @@ -351,19 +351,19 @@ vips_hist_plot_init(VipsHistPlot *hist_plot) * vips_hist_plot: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Plot a 1 by any or any by 1 image file as a max by any or * any by max image using these rules: * - * unsigned char max is always 256 + * *unsigned char* max is always 256 * - * other unsigned integer types output 0 - maximum + * *other unsigned integer types* output 0 - maximum * value of @in. * - * signed int types min moved to 0, max moved to max + min. + * *signed int types* min moved to 0, max moved to max + min. * - * float types min moved to 0, max moved to any + * *float types* min moved to 0, max moved to any * (square output) * * Returns: 0 on success, -1 on error diff --git a/libvips/histogram/histogram.c b/libvips/histogram/histogram.c index f5be1c18fc..d54d20fc90 100644 --- a/libvips/histogram/histogram.c +++ b/libvips/histogram/histogram.c @@ -46,34 +46,6 @@ #include "phistogram.h" -/** - * SECTION: histogram - * @short_description: find, manipulate and apply histograms and lookup tables - * @stability: Stable - * @see_also: image - * arithmetic - * create - * @include: vips/vips.h - * - * Histograms and look-up tables are 1xn or nx1 images, where n is less than - * 256 or less than 65536, corresponding to 8- and 16-bit unsigned int images. - * They are tagged with a #VipsInterpretation of - * #VIPS_INTERPRETATION_HISTOGRAM and usually displayed by user-interfaces - * such as nip2 as plots rather than images. - * - * These functions can be broadly grouped as things to find or build - * histograms (vips_hist_find(), vips_hist_find_indexed(), - * vips_hist_find_ndim(), vips_buildlut(), vips_identity()), - * operations that - * manipulate histograms in some way (vips_hist_cum(), vips_hist_norm()), - * operations to apply histograms (vips_maplut()), and a variety of utility - * operations. - * - * A final group of operations build tone curves. These are useful in - * pre-press work for adjusting the appearance of images. They are designed - * for CIELAB images, but might be useful elsewhere. - */ - G_DEFINE_ABSTRACT_TYPE(VipsHistogram, vips_histogram, VIPS_TYPE_OPERATION); /* sizealike by expanding in just one dimension and copying the final element. diff --git a/libvips/histogram/maplut.c b/libvips/histogram/maplut.c index c0acb5707c..d2de901908 100644 --- a/libvips/histogram/maplut.c +++ b/libvips/histogram/maplut.c @@ -777,11 +777,7 @@ vips_maplut_init(VipsMaplut *maplut) * @in: input image * @out: (out): output image * @lut: look-up table - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @band: apply one-band @lut to this band of @in + * @...: `NULL`-terminated list of optional named arguments * * Map an image through another image acting as a LUT (Look Up Table). * The lut may have any type and the output image will be that type. @@ -804,7 +800,11 @@ vips_maplut_init(VipsMaplut *maplut) * separately. If @in has one band, then @lut may have many bands and * the output will have the same number of bands as @lut. * - * See also: vips_hist_find(), vips_identity(). + * ::: tip "Optional arguments" + * * @band: `gint`, apply one-band @lut to this band of @in + * + * ::: seealso + * [method@Image.hist_find], [ctor@Image.identity]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histogram/percent.c b/libvips/histogram/percent.c index 258d99d7b9..e214ae1fda 100644 --- a/libvips/histogram/percent.c +++ b/libvips/histogram/percent.c @@ -136,22 +136,23 @@ vips_percent_init(VipsPercent *percent) * @in: input image * @percent: threshold percentage * @threshold: (out): output threshold value - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * vips_percent() returns (through the @threshold parameter) the threshold + * [method@Image.percent] returns (through the @threshold parameter) the threshold * below which there are @percent values of @in. For example: * - * |[ + * ```bash * $ vips percent k2.jpg 90 * 214 - * ]| + * ``` * * Means that 90% of pixels in `k2.jpg` have a value less than 214. * * The function works for uchar and ushort images only. It can be used * to threshold the scaled result of a filtering operation. * - * See also: vips_hist_find(), vips_profile(). + * ::: seealso + * [method@Image.hist_find], [method@Image.profile]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histogram/stdif.c b/libvips/histogram/stdif.c index 0d73b4603b..e442008d02 100644 --- a/libvips/histogram/stdif.c +++ b/libvips/histogram/stdif.c @@ -364,27 +364,22 @@ vips_stdif_init(VipsStdif *stdif) * @out: (out): output image * @width: width of region * @height: height of region - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * [method@Image.stdif] performs statistical differencing according to the + * formula given in page 45 of the book "An Introduction to Digital Image + * Processing" by Wayne Niblack. * - * * @a: weight of new mean - * * @m0: target mean - * * @b: weight of new deviation - * * @s0: target deviation - * - * vips_stdif() performs statistical differencing according to the formula - * given in page 45 of the book "An Introduction to Digital Image - * Processing" by Wayne Niblack. This transformation emphasises the way in + * This transformation emphasises the way in * which a pel differs statistically from its neighbours. It is useful for * enhancing low-contrast images with lots of detail, such as X-ray plates. * * At point (i,j) the output is given by the equation: * - * |[ + * ``` * vout(i,j) = @a * @m0 + (1 - @a) * meanv + * (vin(i,j) - meanv) * (@b * @s0) / (@s0 + @b * stdv) - * ]| + * ``` * * Values @a, @m0, @b and @s0 are entered, while meanv and stdv are the values * calculated over a moving window of size @width, @height centred on pixel @@ -393,15 +388,22 @@ vips_stdif_init(VipsStdif *stdif) * * Try: * - * |[ + * ``` * vips stdif $VIPSHOME/pics/huysum.v fred.v 0.5 128 0.5 50 11 11 - * ]| + * ``` * * The operation works on one-band uchar images only, and writes a one-band * uchar image as its result. The output image has the same size as the * input. * - * See also: vips_hist_local(). + * ::: tip "Optional arguments" + * * @a: `gdouble`, weight of new mean + * * @m0: `gdouble`, target mean + * * @b: `gdouble`, weight of new deviation + * * @s0: `gdouble`, target deviation + * + * ::: seealso + * [method@Image.hist_local]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/include/vips/almostdeprecated.h b/libvips/include/vips/almostdeprecated.h index e18cb26bde..fe25e7d4e2 100644 --- a/libvips/include/vips/almostdeprecated.h +++ b/libvips/include/vips/almostdeprecated.h @@ -151,6 +151,16 @@ VIPS_DEPRECATED_FOR(g_warning) void im_warning(const char *fmt, ...) G_GNUC_PRINTF(1, 2); +VIPS_DEPRECATED_FOR(g_mutex_init) +GMutex *vips_g_mutex_new(void); +VIPS_DEPRECATED_FOR(g_mutex_clear) +void vips_g_mutex_free(GMutex *); + +VIPS_DEPRECATED_FOR(g_cond_init) +GCond *vips_g_cond_new(void); +VIPS_DEPRECATED_FOR(g_cond_clear) +void vips_g_cond_free(GCond *); + VIPS_DEPRECATED_FOR(g_thread_join) void *vips_g_thread_join(GThread *thread); @@ -354,7 +364,7 @@ int im_rank_raw(IMAGE *in, IMAGE *out, int xsize, int ysize, int order); * * Set jpeg subsampling mode. * - * DEPRECATED: use #VipsForeignSubsample + * DEPRECATED: use [enum@ForeignSubsample] */ typedef enum { VIPS_FOREIGN_JPEG_SUBSAMPLE_AUTO, @@ -460,6 +470,24 @@ VIPS_DEPRECATED_FOR(g_snprintf) int vips_snprintf(char *str, size_t size, const char *format, ...) G_GNUC_PRINTF(3, 4); +/* This has been deprecated and replaced by VipsForeignSaveable. + */ +typedef enum /*< skip >*/ { + VIPS_SAVEABLE_MONO = + VIPS_FOREIGN_SAVEABLE_MONO, + VIPS_SAVEABLE_RGB = + VIPS_FOREIGN_SAVEABLE_MONO | VIPS_FOREIGN_SAVEABLE_RGB, + VIPS_SAVEABLE_RGBA = + VIPS_SAVEABLE_RGB | VIPS_FOREIGN_SAVEABLE_ALPHA, + VIPS_SAVEABLE_RGBA_ONLY = + VIPS_FOREIGN_SAVEABLE_RGB | VIPS_FOREIGN_SAVEABLE_ALPHA, + VIPS_SAVEABLE_RGB_CMYK = + VIPS_SAVEABLE_RGB | VIPS_FOREIGN_SAVEABLE_CMYK, + VIPS_SAVEABLE_ANY = + VIPS_FOREIGN_SAVEABLE_ANY, + VIPS_SAVEABLE_LAST = 99, +} VipsSaveable; + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/arithmetic.h b/libvips/include/vips/arithmetic.h index 239abba227..7a039e9726 100644 --- a/libvips/include/vips/arithmetic.h +++ b/libvips/include/vips/arithmetic.h @@ -43,24 +43,24 @@ extern "C" { /** * VipsOperationMath: - * @VIPS_OPERATION_MATH_SIN: sin(), angles in degrees - * @VIPS_OPERATION_MATH_COS: cos(), angles in degrees - * @VIPS_OPERATION_MATH_TAN: tan(), angles in degrees - * @VIPS_OPERATION_MATH_ASIN: asin(), angles in degrees - * @VIPS_OPERATION_MATH_ACOS: acos(), angles in degrees - * @VIPS_OPERATION_MATH_ATAN: atan(), angles in degrees + * @VIPS_OPERATION_MATH_SIN: `sin()`, angles in degrees + * @VIPS_OPERATION_MATH_COS: `cos()`, angles in degrees + * @VIPS_OPERATION_MATH_TAN: `tan()`, angles in degrees + * @VIPS_OPERATION_MATH_ASIN: `asin()`, angles in degrees + * @VIPS_OPERATION_MATH_ACOS: `acos()`, angles in degrees + * @VIPS_OPERATION_MATH_ATAN: `atan()`, angles in degrees * @VIPS_OPERATION_MATH_LOG: log base e * @VIPS_OPERATION_MATH_LOG10: log base 10 * @VIPS_OPERATION_MATH_EXP: e to the something * @VIPS_OPERATION_MATH_EXP10: 10 to the something - * @VIPS_OPERATION_MATH_SINH: sinh(), angles in radians - * @VIPS_OPERATION_MATH_COSH: cosh(), angles in radians - * @VIPS_OPERATION_MATH_TANH: tanh(), angles in radians - * @VIPS_OPERATION_MATH_ASINH: asinh(), angles in radians - * @VIPS_OPERATION_MATH_ACOSH: acosh(), angles in radians - * @VIPS_OPERATION_MATH_ATANH: atanh(), angles in radians + * @VIPS_OPERATION_MATH_SINH: `sinh()`, angles in radians + * @VIPS_OPERATION_MATH_COSH: `cosh()`, angles in radians + * @VIPS_OPERATION_MATH_TANH: `tanh()`, angles in radians + * @VIPS_OPERATION_MATH_ASINH: `asinh()`, angles in radians + * @VIPS_OPERATION_MATH_ACOSH: `acosh()`, angles in radians + * @VIPS_OPERATION_MATH_ATANH: `atanh()`, angles in radians * - * See also: vips_math(). + * See also: [method@Image.math]. */ typedef enum { VIPS_OPERATION_MATH_SIN, @@ -84,11 +84,11 @@ typedef enum { /** * VipsOperationMath2: - * @VIPS_OPERATION_MATH2_POW: pow(left, right) - * @VIPS_OPERATION_MATH2_WOP: pow(right, left) - * @VIPS_OPERATION_MATH2_ATAN2: atan2(left, right) + * @VIPS_OPERATION_MATH2_POW: `pow(left, right)` + * @VIPS_OPERATION_MATH2_WOP: `pow(right, left)` + * @VIPS_OPERATION_MATH2_ATAN2: `atan2(left, right)` * - * See also: vips_math(). + * See also: [method@Image.math]. */ typedef enum { VIPS_OPERATION_MATH2_POW, @@ -103,7 +103,7 @@ typedef enum { * @VIPS_OPERATION_ROUND_FLOOR: largest integral value not greater than * @VIPS_OPERATION_ROUND_CEIL: the smallest integral value not less than * - * See also: vips_round(). + * See also: [method@Image.round]. */ typedef enum { VIPS_OPERATION_ROUND_RINT, @@ -114,14 +114,14 @@ typedef enum { /** * VipsOperationRelational: - * @VIPS_OPERATION_RELATIONAL_EQUAL: == - * @VIPS_OPERATION_RELATIONAL_NOTEQ: != - * @VIPS_OPERATION_RELATIONAL_LESS: < - * @VIPS_OPERATION_RELATIONAL_LESSEQ: <= - * @VIPS_OPERATION_RELATIONAL_MORE: > - * @VIPS_OPERATION_RELATIONAL_MOREEQ: >= + * @VIPS_OPERATION_RELATIONAL_EQUAL: `==` + * @VIPS_OPERATION_RELATIONAL_NOTEQ: `!=` + * @VIPS_OPERATION_RELATIONAL_LESS: `<` + * @VIPS_OPERATION_RELATIONAL_LESSEQ: `<=` + * @VIPS_OPERATION_RELATIONAL_MORE: `>` + * @VIPS_OPERATION_RELATIONAL_MOREEQ: `>=` * - * See also: vips_relational(). + * See also: [method@Image.relational]. */ typedef enum { VIPS_OPERATION_RELATIONAL_EQUAL, @@ -135,13 +135,13 @@ typedef enum { /** * VipsOperationBoolean: - * @VIPS_OPERATION_BOOLEAN_AND: & - * @VIPS_OPERATION_BOOLEAN_OR: | - * @VIPS_OPERATION_BOOLEAN_EOR: ^ - * @VIPS_OPERATION_BOOLEAN_LSHIFT: >> - * @VIPS_OPERATION_BOOLEAN_RSHIFT: << + * @VIPS_OPERATION_BOOLEAN_AND: `&` + * @VIPS_OPERATION_BOOLEAN_OR: `|` + * @VIPS_OPERATION_BOOLEAN_EOR: `^` + * @VIPS_OPERATION_BOOLEAN_LSHIFT: `>>` + * @VIPS_OPERATION_BOOLEAN_RSHIFT: `<<` * - * See also: vips_boolean(). + * See also: [method@Image.boolean]. */ typedef enum { VIPS_OPERATION_BOOLEAN_AND, @@ -158,7 +158,7 @@ typedef enum { * @VIPS_OPERATION_COMPLEX_RECT: convert to rectangular coordinates * @VIPS_OPERATION_COMPLEX_CONJ: complex conjugate * - * See also: vips_complex(). + * See also: [method@Image.complex]. */ typedef enum { VIPS_OPERATION_COMPLEX_POLAR, @@ -171,7 +171,7 @@ typedef enum { * VipsOperationComplex2: * @VIPS_OPERATION_COMPLEX2_CROSS_PHASE: convert to polar coordinates * - * See also: vips_complex2(). + * See also: [method@Image.complex2]. */ typedef enum { VIPS_OPERATION_COMPLEX2_CROSS_PHASE, @@ -183,7 +183,7 @@ typedef enum { * @VIPS_OPERATION_COMPLEXGET_REAL: get real component * @VIPS_OPERATION_COMPLEXGET_IMAG: get imaginary component * - * See also: vips_complexget(). + * See also: [method@Image.complexget]. */ typedef enum { VIPS_OPERATION_COMPLEXGET_REAL, diff --git a/libvips/include/vips/basic.h b/libvips/include/vips/basic.h index 26c4e3fef7..e74deb48df 100644 --- a/libvips/include/vips/basic.h +++ b/libvips/include/vips/basic.h @@ -56,6 +56,18 @@ #define VIPS_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) VIPS_API #endif +#if !defined(VIPS_DISABLE_DEPRECATION_WARNINGS) && \ + (G_GNUC_CHECK_VERSION(4, 6) || \ + __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 4)) +#define _VIPS_GNUC_DO_PRAGMA(x) _Pragma(G_STRINGIFY(x)) +#define VIPS_DEPRECATED_MACRO _VIPS_GNUC_DO_PRAGMA(GCC warning "Deprecated pre-processor symbol") +#define VIPS_DEPRECATED_MACRO_FOR(f) \ + _VIPS_GNUC_DO_PRAGMA(GCC warning G_STRINGIFY(Deprecated pre-processor symbol: replace with #f)) +#else +#define VIPS_DEPRECATED_MACRO +#define VIPS_DEPRECATED_MACRO_FOR(f) +#endif + #ifdef __cplusplus extern "C" { #endif /*__cplusplus*/ @@ -88,6 +100,8 @@ typedef enum { VIPS_PRECISION_LAST } VipsPrecision; +#ifndef __GI_SCANNER__ + /* Just for testing. */ VIPS_API @@ -95,6 +109,8 @@ char *vips_path_filename7(const char *path); VIPS_API char *vips_path_mode7(const char *path); +#endif /* !__GI_SCANNER__ */ + struct _VipsImage; typedef struct _VipsImage VipsImage; struct _VipsRegion; diff --git a/libvips/include/vips/buf.h b/libvips/include/vips/buf.h index 3951369163..fece94f8dd 100644 --- a/libvips/include/vips/buf.h +++ b/libvips/include/vips/buf.h @@ -39,11 +39,6 @@ extern "C" { #endif /*__cplusplus*/ -/* A string in the process of being written to ... multiple calls to - * vips_buf_append add to it. On overflow append "..." and block further - * writes. - */ - struct _VipsBuf { /* All fields are private. */ diff --git a/libvips/include/vips/colour.h b/libvips/include/vips/colour.h index 895f25e1dd..5848249b83 100644 --- a/libvips/include/vips/colour.h +++ b/libvips/include/vips/colour.h @@ -93,11 +93,18 @@ extern "C" { #define VIPS_D3250_Y0 (100.0) #define VIPS_D3250_Z0 (45.8501) +/* Note: constants align with those defined in lcms2.h, except for + * VIPS_INTENT_AUTO, which is libvips-specific. + */ typedef enum { VIPS_INTENT_PERCEPTUAL = 0, VIPS_INTENT_RELATIVE, VIPS_INTENT_SATURATION, VIPS_INTENT_ABSOLUTE, + /* Leave room for possible new rendering intents beyond the + * four standard ones. + */ + VIPS_INTENT_AUTO = 32, VIPS_INTENT_LAST } VipsIntent; @@ -142,12 +149,6 @@ VIPS_API int vips_Lab2LCh(VipsImage *in, VipsImage **out, ...) G_GNUC_NULL_TERMINATED; VIPS_API -int vips_Yxy2Lab(VipsImage *in, VipsImage **out, ...) - G_GNUC_NULL_TERMINATED; -VIPS_API -int vips_CMC2XYZ(VipsImage *in, VipsImage **out, ...) - G_GNUC_NULL_TERMINATED; -VIPS_API int vips_Lab2XYZ(VipsImage *in, VipsImage **out, ...) G_GNUC_NULL_TERMINATED; VIPS_API diff --git a/libvips/include/vips/connection.h b/libvips/include/vips/connection.h index ef4995b6ea..ac639b9877 100644 --- a/libvips/include/vips/connection.h +++ b/libvips/include/vips/connection.h @@ -58,8 +58,6 @@ extern "C" { (G_TYPE_INSTANCE_GET_CLASS((obj), \ VIPS_TYPE_CONNECTION, VipsConnectionClass)) -/* Communicate with something like a socket or pipe. - */ typedef struct _VipsConnection { VipsObject parent_object; @@ -116,13 +114,6 @@ void vips_pipe_read_limit_set(gint64 limit); (G_TYPE_INSTANCE_GET_CLASS((obj), \ VIPS_TYPE_SOURCE, VipsSourceClass)) -/* Read from something like a socket, file or memory area and present the data - * with a unified seek / read / map interface. - * - * During the header phase, we save data from unseekable sources in a buffer - * so readers can rewind and read again. We don't buffer data during the - * decode stage. - */ struct _VipsSource { VipsConnection parent_object; @@ -194,14 +185,14 @@ typedef struct _VipsSourceClass { */ /* Read from the source into the supplied buffer, args exactly as - * read(2). Set errno on error. + * [`read()`](man:read(2)). Set errno on error. * * We must return gint64, since ssize_t is often defined as unsigned * on Windows. */ - gint64 (*read)(VipsSource *, void *, size_t); + gint64 (*read)(VipsSource *source, void *buffer, size_t length); - /* Seek to a certain position, args exactly as lseek(2). Set errno on + /* Seek to a certain position, args exactly as [`lseek()`](man:lseek(2)). Set errno on * error. * * Unseekable sources should always return -1. VipsSource will then @@ -210,7 +201,7 @@ typedef struct _VipsSourceClass { * We have to use int64 rather than off_t, since we must work on * Windows, where off_t can be 32-bits. */ - gint64 (*seek)(VipsSource *, gint64, int); + gint64 (*seek)(VipsSource *source, gint64 offset, int whence); } VipsSourceClass; @@ -226,7 +217,7 @@ VipsSource *vips_source_new_from_blob(VipsBlob *blob); VIPS_API VipsSource *vips_source_new_from_target(VipsTarget *target); VIPS_API -VipsSource *vips_source_new_from_memory(const void *data, size_t size); +VipsSource *vips_source_new_from_memory(const void *data, size_t length); VIPS_API VipsSource *vips_source_new_from_options(const char *options); @@ -237,7 +228,7 @@ int vips_source_unminimise(VipsSource *source); VIPS_API int vips_source_decode(VipsSource *source); VIPS_API -gint64 vips_source_read(VipsSource *source, void *data, size_t length); +gint64 vips_source_read(VipsSource *source, void *buffer, size_t length); VIPS_API gboolean vips_source_is_mappable(VipsSource *source); VIPS_API @@ -273,9 +264,6 @@ gint64 vips_source_length(VipsSource *source); (G_TYPE_INSTANCE_GET_CLASS((obj), \ VIPS_TYPE_SOURCE_CUSTOM, VipsSourceCustomClass)) -/* Subclass of source_custom with signals for handlers. This is supposed to be - * useful for language bindings. - */ typedef struct _VipsSourceCustom { VipsSource parent_object; @@ -288,8 +276,8 @@ typedef struct _VipsSourceCustomClass { * We must use gint64 everywhere since there's no G_TYPE_SIZE. */ - gint64 (*read)(VipsSourceCustom *, void *, gint64); - gint64 (*seek)(VipsSourceCustom *, gint64, int); + gint64 (*read)(VipsSourceCustom *source, void *buffer, gint64 length); + gint64 (*seek)(VipsSourceCustom *source, gint64 offset, int whence); } VipsSourceCustomClass; @@ -355,6 +343,10 @@ GInputStream *vips_g_input_stream_new_from_source(VipsSource *source); (G_TYPE_INSTANCE_GET_CLASS((obj), \ VIPS_TYPE_SOURCE_G_INPUT_STREAM, VipsSourceGInputStreamClass)) +/** + * VipsSourceGInputStream: (copy-func g_object_ref) + * (free-func g_object_unref) + */ typedef struct _VipsSourceGInputStream { VipsSource parent_instance; @@ -396,8 +388,6 @@ VipsSourceGInputStream *vips_source_g_input_stream_new(GInputStream *stream); */ #define VIPS_TARGET_BUFFER_SIZE (8500) -/* Output to something like a socket, pipe or memory area. - */ struct _VipsTarget { VipsConnection parent_object; @@ -448,11 +438,11 @@ typedef struct _VipsTargetClass { * We must return gint64, since ssize_t is often defined as unsigned * on Windows. */ - gint64 (*write)(VipsTarget *, const void *, size_t); + gint64 (*write)(VipsTarget *target, const void *data, size_t length); /* Deprecated in favour of ::end. */ - void (*finish)(VipsTarget *); + void (*finish)(VipsTarget *target); /* libtiff needs to be able to seek and read on targets, * unfortunately. @@ -461,24 +451,24 @@ typedef struct _VipsTargetClass { */ /* Read from the target into the supplied buffer, args exactly as - * read(2). Set errno on error. + * [`read()`](man:read(2)). Set errno on error. * * We must return gint64, since ssize_t is often defined as unsigned * on Windows. */ - gint64 (*read)(VipsTarget *, void *, size_t); + gint64 (*read)(VipsTarget *target, void *buffer, size_t length); - /* Seek output. Args exactly as lseek(2). + /* Seek output. Args exactly as [`lseek()`](man:lseek(2)). * * We have to use int64 rather than off_t, since we must work on * Windows, where off_t can be 32-bits. */ - gint64 (*seek)(VipsTarget *, gint64 offset, int whence); + gint64 (*seek)(VipsTarget *target, gint64 offset, int whence); /* Output has been generated, so do any clearing up, * eg. copy the bytes we saved in memory to the target blob. */ - int (*end)(VipsTarget *); + int (*end)(VipsTarget *target); } VipsTargetClass; @@ -492,7 +482,7 @@ VipsTarget *vips_target_new_to_file(const char *filename); VIPS_API VipsTarget *vips_target_new_to_memory(void); VIPS_API -VipsTarget *vips_target_new_temp(VipsTarget *target); +VipsTarget *vips_target_new_temp(VipsTarget *based_on); VIPS_API int vips_target_write(VipsTarget *target, const void *data, size_t length); VIPS_API @@ -537,8 +527,6 @@ int vips_target_write_amp(VipsTarget *target, const char *str); #define VIPS_TARGET_CUSTOM_BUFFER_SIZE (4096) -/* Output to something like a socket, pipe or memory area. - */ typedef struct _VipsTargetCustom { VipsTarget parent_object; @@ -551,11 +539,11 @@ typedef struct _VipsTargetCustomClass { * We must use gint64 everywhere since there's no G_TYPE_SIZE. */ - gint64 (*write)(VipsTargetCustom *, const void *, gint64); - void (*finish)(VipsTargetCustom *); - gint64 (*read)(VipsTargetCustom *, void *, gint64); - gint64 (*seek)(VipsTargetCustom *, gint64, int); - int (*end)(VipsTargetCustom *); + gint64 (*write)(VipsTargetCustom *target, const void *data, gint64 length); + void (*finish)(VipsTargetCustom *target); + gint64 (*read)(VipsTargetCustom *target, void *buffer, gint64 length); + gint64 (*seek)(VipsTargetCustom *target, gint64 offset, int whence); + int (*end)(VipsTargetCustom *target); } VipsTargetCustomClass; diff --git a/libvips/include/vips/enumtypes.c.in b/libvips/include/vips/enumtypes.c.in index f57755dd57..8e7f1971ec 100644 --- a/libvips/include/vips/enumtypes.c.in +++ b/libvips/include/vips/enumtypes.c.in @@ -38,3 +38,11 @@ GType } /*** END value-tail ***/ +/*** BEGIN file-tail ***/ +/* Deprecated enumerations */ +GType +vips_saveable_get_type(void) +{ + return vips_foreign_saveable_get_type(); +} +/*** END file-tail ***/ diff --git a/libvips/include/vips/enumtypes.h.in b/libvips/include/vips/enumtypes.h.in index 83bf63c095..e4acbfaeac 100644 --- a/libvips/include/vips/enumtypes.h.in +++ b/libvips/include/vips/enumtypes.h.in @@ -17,6 +17,12 @@ GType @enum_name@_get_type(void) G_GNUC_CONST; /*** END value-header ***/ /*** BEGIN file-tail ***/ +/* Deprecated enumerations */ +#ifndef __GI_SCANNER__ +VIPS_API +GType vips_saveable_get_type(void) G_GNUC_CONST; +#define VIPS_TYPE_SAVEABLE (vips_saveable_get_type()) +#endif /*__GI_SCANNER__*/ G_END_DECLS #endif /*VIPS_ENUM_TYPES_H*/ diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index f2e7134b6b..ab6f3ebfa2 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -82,8 +82,6 @@ typedef struct _VipsForeignClass { } VipsForeignClass; -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_foreign_get_type(void); @@ -117,8 +115,8 @@ typedef enum /*< flags >*/ { * How sensitive loaders are to errors, from never stop (very insensitive), to * stop on the smallest warning (very sensitive). * - * Each one implies the ones before it, so #VIPS_FAIL_ON_ERROR implies - * #VIPS_FAIL_ON_TRUNCATED. + * Each one implies the ones before it, so [enum@Vips.FailOn.ERROR] implies + * [enum@Vips.FailOn.TRUNCATED]. */ typedef enum { VIPS_FAIL_ON_NONE, @@ -145,6 +143,7 @@ typedef enum { typedef struct _VipsForeignLoad { VipsForeign parent_object; + /*< private >*/ /* Set TRUE to force open via memory. @@ -201,11 +200,12 @@ typedef struct _VipsForeignLoad { typedef struct _VipsForeignLoadClass { VipsForeignClass parent_class; + /*< public >*/ /* Is a file in this format. * - * This function should return %TRUE if the file contains an image of + * This function should return `TRUE` if the file contains an image of * this type. If you don't define this function, #VipsForeignLoad * will use @suffs instead. */ @@ -213,14 +213,14 @@ typedef struct _VipsForeignLoadClass { /* Is a buffer in this format. * - * This function should return %TRUE if the buffer contains an image of + * This function should return `TRUE` if the buffer contains an image of * this type. */ gboolean (*is_a_buffer)(const void *data, size_t size); /* Is a stream in this format. * - * This function should return %TRUE if the stream contains an image of + * This function should return `TRUE` if the stream contains an image of * this type. */ gboolean (*is_a_source)(VipsSource *source); @@ -268,8 +268,6 @@ typedef struct _VipsForeignLoadClass { int (*load)(VipsForeignLoad *load); } VipsForeignLoadClass; -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_foreign_load_get_type(void); @@ -310,25 +308,25 @@ void vips_foreign_load_invalidate(VipsImage *image); VIPS_TYPE_FOREIGN_SAVE, VipsForeignSaveClass)) /** - * VipsSaveable: - * @VIPS_SAVEABLE_MONO: 1 band (eg. CSV) - * @VIPS_SAVEABLE_RGB: 1 or 3 bands (eg. PPM) - * @VIPS_SAVEABLE_RGBA: 1, 2, 3 or 4 bands (eg. PNG) - * @VIPS_SAVEABLE_RGBA_ONLY: 3 or 4 bands (eg. WEBP) - * @VIPS_SAVEABLE_RGB_CMYK: 1, 3 or 4 bands (eg. JPEG) - * @VIPS_SAVEABLE_ANY: any number of bands (eg. TIFF) + * VipsForeignSaveable: + * @VIPS_FOREIGN_SAVEABLE_MONO: 1 band + * @VIPS_FOREIGN_SAVEABLE_RGB: 3 bands + * @VIPS_FOREIGN_SAVEABLE_CMYK: 4 bands + * @VIPS_FOREIGN_SAVEABLE_ALPHA: an extra band + * @VIPS_FOREIGN_SAVEABLE_ANY: saver supports everything (eg. TIFF) + * + * The set of image types supported by a saver. * - * See also: #VipsForeignSave. + * See also: [class@ForeignSave]. */ -typedef enum { - VIPS_SAVEABLE_MONO, - VIPS_SAVEABLE_RGB, - VIPS_SAVEABLE_RGBA, - VIPS_SAVEABLE_RGBA_ONLY, - VIPS_SAVEABLE_RGB_CMYK, - VIPS_SAVEABLE_ANY, - VIPS_SAVEABLE_LAST -} VipsSaveable; +typedef enum /*< flags >*/ { + VIPS_FOREIGN_SAVEABLE_MONO = 1, + VIPS_FOREIGN_SAVEABLE_RGB = 2, + VIPS_FOREIGN_SAVEABLE_CMYK = 4, + VIPS_FOREIGN_SAVEABLE_ALPHA = 8, + VIPS_FOREIGN_SAVEABLE_ANY = 16, + VIPS_FOREIGN_SAVEABLE_ALL = 31, +} VipsForeignSaveable; /** * VipsForeignKeep: @@ -403,11 +401,11 @@ typedef struct _VipsForeignSaveClass { /* How this format treats bands. * - * @saveable describes the bands that your saver can handle. For + * @saveable describes the image types that your saver can handle. For * example, PPM images can have 1 or 3 bands (mono or RGB), so it - * uses #VIPS_SAVEABLE_RGB. + * uses VIPS_SAVEABLE_FLAGS_MONO | VIPS_SAVEABLE_FLAGS_RGB. */ - VipsSaveable saveable; + VipsForeignSaveable saveable; /* How this format treats band formats. * @@ -425,8 +423,6 @@ typedef struct _VipsForeignSaveClass { gboolean coding[VIPS_CODING_LAST]; } VipsForeignSaveClass; -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_foreign_save_get_type(void); @@ -632,6 +628,9 @@ VIPS_API int vips_fitsload(const char *filename, VipsImage **out, ...) G_GNUC_NULL_TERMINATED; VIPS_API +int vips_fitsload_source(VipsSource *source, VipsImage **out, ...) + G_GNUC_NULL_TERMINATED; +VIPS_API int vips_fitssave(VipsImage *in, const char *filename, ...) G_GNUC_NULL_TERMINATED; @@ -745,15 +744,15 @@ int vips_pngsave_buffer(VipsImage *in, void **buf, size_t *len, ...) * * The netpbm file format to save as. * - * #VIPS_FOREIGN_PPM_FORMAT_PBM images are single bit. + * [enum@Vips.ForeignPpmFormat.PBM] images are single bit. * - * #VIPS_FOREIGN_PPM_FORMAT_PGM images are 8, 16, or 32-bits, one band. + * [enum@Vips.ForeignPpmFormat.PGM] images are 8, 16, or 32-bits, one band. * - * #VIPS_FOREIGN_PPM_FORMAT_PPM images are 8, 16, or 32-bits, three bands. + * [enum@Vips.ForeignPpmFormat.PPM] images are 8, 16, or 32-bits, three bands. * - * #VIPS_FOREIGN_PPM_FORMAT_PFM images are 32-bit float pixels. + * [enum@Vips.ForeignPpmFormat.PFM] images are 32-bit float pixels. * - * #VIPS_FOREIGN_PPM_FORMAT_PNM images are anymap images -- the image format + * [enum@Vips.ForeignPpmFormat.PNM] images are anymap images -- the image format * is used to pick the saver. * */ @@ -980,7 +979,7 @@ int vips_dzsave_target(VipsImage *in, VipsTarget *target, ...) * * The compression format to use inside a HEIF container. * - * This is assumed to use the same numbering as %heif_compression_format. + * This is assumed to use the same numbering as `heif_compression_format`. */ typedef enum { VIPS_FOREIGN_HEIF_COMPRESSION_HEVC = 1, diff --git a/libvips/include/vips/format.h b/libvips/include/vips/format.h index b96c4eb9a9..37aeb729ec 100644 --- a/libvips/include/vips/format.h +++ b/libvips/include/vips/format.h @@ -64,6 +64,7 @@ typedef enum { typedef struct _VipsFormat { VipsObject parent_object; + /*< public >*/ } VipsFormat; @@ -72,25 +73,26 @@ typedef struct _VipsFormatClass { VipsObjectClass parent_class; /*< public >*/ + /* Is a file in this format. */ - gboolean (*is_a)(const char *); + gboolean (*is_a)(const char *filename); /* Read just the header into the VipsImage. */ - int (*header)(const char *, VipsImage *); + int (*header)(const char *filename, VipsImage *image); /* Load the whole image. */ - int (*load)(const char *, VipsImage *); + int (*load)(const char *filename, VipsImage *image); /* Write the VipsImage to the file in this format. */ - int (*save)(VipsImage *, const char *); + int (*save)(VipsImage *image, const char *filename); /* Get the flags for this file in this format. */ - VipsFormatFlags (*get_flags)(const char *); + VipsFormatFlags (*get_flags)(const char *filename); /* Loop over formats in this order, default 0. We need this because * some formats can be read by several loaders (eg. tiff can be read diff --git a/libvips/include/vips/gate.h b/libvips/include/vips/gate.h index 2b53e22b07..57e179ab22 100644 --- a/libvips/include/vips/gate.h +++ b/libvips/include/vips/gate.h @@ -69,20 +69,9 @@ extern "C" { } \ G_STMT_END -extern gboolean vips__thread_profile; - VIPS_API void vips_profile_set(gboolean profile); -void vips__thread_profile_attach(const char *thread_name); -void vips__thread_profile_detach(void); -void vips__thread_profile_stop(void); - -void vips__thread_gate_start(const char *gate_name); -void vips__thread_gate_stop(const char *gate_name); - -void vips__thread_malloc_free(gint64 size); - #endif /*VIPS_GATE_H*/ #ifdef __cplusplus diff --git a/libvips/include/vips/header.h b/libvips/include/vips/header.h index 16c3df2fc9..24ee3e0b4f 100644 --- a/libvips/include/vips/header.h +++ b/libvips/include/vips/header.h @@ -73,7 +73,7 @@ extern "C" { * The name we use to attach an ICC profile. The file read and write * operations for TIFF, JPEG, PNG and others use this item of metadata to * attach and save ICC profiles. The profile is updated by the - * vips_icc_transform() operations. + * [method@Image.icc_transform] operations. */ #define VIPS_META_ICC_NAME "icc-profile-data" @@ -117,8 +117,8 @@ extern "C" { /** * VIPS_META_SEQUENTIAL: * - * Images loaded via vips_sequential() have this int field defined. Some - * operations (eg. vips_shrinkv()) add extra caches if they see it on their + * Images loaded via [method@Image.sequential] have this int field defined. Some + * operations (eg. [method@Image.shrinkv]) add extra caches if they see it on their * input. */ #define VIPS_META_SEQUENTIAL "vips-sequential" diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index b5d6752755..f9b91241c1 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -252,7 +252,7 @@ struct _VipsImage { VipsStopFn stop_fn; void *client1; /* user arguments */ void *client2; - GMutex *sslock; /* start-stop lock */ + GMutex sslock; /* start-stop lock */ GSList *regions; /* list of regions current for this image */ VipsDemandStyle dhint; /* demand style hint */ @@ -367,8 +367,6 @@ typedef struct _VipsImageClass { } VipsImageClass; -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_image_get_type(void); @@ -444,6 +442,13 @@ void vips_image_minimise_all(VipsImage *image); VIPS_API gboolean vips_image_is_sequential(VipsImage *image); +VIPS_API +void vips_image_preeval(VipsImage *image); +VIPS_API +void vips_image_eval(VipsImage *image, guint64 processed); +VIPS_API +void vips_image_posteval(VipsImage *image); + VIPS_API void vips_image_set_progress(VipsImage *image, gboolean progress); VIPS_API diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index edde31a272..8a583961ca 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -107,6 +107,10 @@ int vips__exif_update(VipsImage *image); void vips_check_init(void); +/* Set from the command-line. + */ +extern gboolean vips__vector_enabled; + void vips__vector_init(void); void vips__meta_init_types(void); @@ -151,6 +155,13 @@ extern gboolean vips__cache_trace; void vips__thread_init(void); void vips__threadpool_init(void); void vips__threadpool_shutdown(void); + +typedef struct _VipsThreadset VipsThreadset; +VipsThreadset *vips_threadset_new(int max_threads); +int vips_threadset_run(VipsThreadset *set, + const char *domain, GFunc func, gpointer data); +void vips_threadset_free(VipsThreadset *set); + VIPS_API void vips__worker_lock(GMutex *mutex); VIPS_API void vips__worker_cond_wait(GCond *cond, GMutex *mutex); @@ -160,6 +171,10 @@ int vips__print_renders(void); int vips__type_leak(void); int vips__object_leak(void); +#ifdef HAVE_OPENSLIDE +int vips__openslideconnection_leak(void); +#endif /*HAVE_OPENSLIDE*/ + /* iofuncs */ int vips__open_image_read(const char *filename); @@ -218,12 +233,9 @@ VIPS_API int vips__write_header_bytes(VipsImage *im, unsigned char *to); int vips__image_meta_copy(VipsImage *dst, const VipsImage *src); -extern GMutex *vips__global_lock; +extern GMutex vips__global_lock; int vips_image_written(VipsImage *image); -void vips_image_preeval(VipsImage *image); -void vips_image_eval(VipsImage *image, guint64 processed); -void vips_image_posteval(VipsImage *image); /* Defined in `vips.h`, unless building with `-Ddeprecated=false` */ @@ -330,7 +342,7 @@ typedef struct _VipsImagePixels { } VipsImagePixels; int vips__foreign_convert_saveable(VipsImage *in, VipsImage **ready, - VipsSaveable saveable, VipsBandFormat *format, VipsCoding *coding, + VipsForeignSaveable saveable, VipsBandFormat *format, VipsCoding *coding, VipsArrayDouble *background); int vips_foreign_load(const char *filename, VipsImage **out, ...) @@ -351,6 +363,10 @@ VipsWindow *vips_window_take(VipsWindow *window, int vips__profile_set(VipsImage *image, const char *name); +void vips__thread_profile_attach(const char *thread_name); +void vips__thread_profile_detach(void); +void vips__thread_profile_stop(void); + int vips__lrmosaic(VipsImage *ref, VipsImage *sec, VipsImage *out, int bandno, int xref, int yref, int xsec, int ysec, @@ -368,6 +384,48 @@ int vips__correl(VipsImage *ref, VipsImage *sec, int hwindowsize, int hsearchsize, double *correlation, int *x, int *y); +unsigned int vips_operation_hash(VipsOperation *operation); + +int vips__open_read(const char *filename); +FILE *vips__fopen(const char *filename, const char *mode); + +char *vips__file_read_name(const char *name, const char *fallback_dir, + size_t *length_out); +int vips__file_write(void *data, size_t size, size_t nmemb, FILE *stream); + +int vips__fgetc(FILE *fp); + +GValue *vips__gvalue_ref_string_new(const char *text); +void vips__gslist_gvalue_free(GSList *list); +GSList *vips__gslist_gvalue_copy(const GSList *list); +GSList *vips__gslist_gvalue_merge(GSList *a, const GSList *b); +char *vips__gslist_gvalue_get(const GSList *list); + +gint64 vips__seek_no_error(int fd, gint64 pos, int whence); + +int vips__ftruncate(int fd, gint64 pos); + +const char *vips__token_must(const char *buffer, VipsToken *token, + char *string, int size); +const char *vips__token_need(const char *buffer, VipsToken need_token, + char *string, int size); +const char *vips__token_segment(const char *p, VipsToken *token, + char *string, int size); +const char *vips__token_segment_need(const char *p, VipsToken need_token, + char *string, int size); +const char *vips__find_rightmost_brackets(const char *p); + +void vips__change_suffix(const char *name, char *out, int mx, + const char *new_suff, const char **olds, int nolds); + +guint32 vips__random(guint32 seed); +guint32 vips__random_add(guint32 seed, int value); + +const char *vips__icc_dir(void); +const char *vips__windows_prefix(void); + +char *vips__get_iso8601(void); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/interpolate.h b/libvips/include/vips/interpolate.h index 18ffa7a34b..6695eea89e 100644 --- a/libvips/include/vips/interpolate.h +++ b/libvips/include/vips/interpolate.h @@ -91,8 +91,6 @@ typedef struct _VipsInterpolateClass { int window_offset; } VipsInterpolateClass; -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_interpolate_get_type(void); VIPS_API diff --git a/libvips/include/vips/memory.h b/libvips/include/vips/memory.h index 4f75cc5a27..93e669340b 100644 --- a/libvips/include/vips/memory.h +++ b/libvips/include/vips/memory.h @@ -71,6 +71,8 @@ extern "C" { #define VIPS_ARRAY(OBJ, N, T) \ ((T *) VIPS_MALLOC(OBJ, (N) * sizeof(T))) +#ifndef __GI_SCANNER__ + G_DEFINE_AUTOPTR_CLEANUP_FUNC(VipsImage, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(VipsObject, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(VipsRegion, g_object_unref) @@ -89,6 +91,8 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(VipsOperation, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(VipsArrayDouble, VipsArrayDouble_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(VipsArrayImage, VipsArrayImage_unref) +#endif /* !__GI_SCANNER__ */ + VIPS_API void *vips_malloc(VipsObject *object, size_t size); VIPS_API diff --git a/libvips/include/vips/meson.build b/libvips/include/vips/meson.build index 17bf777c79..217a5ea7a9 100644 --- a/libvips/include/vips/meson.build +++ b/libvips/include/vips/meson.build @@ -1,19 +1,9 @@ +# Headers that we install but neither introspect nor document. public_other_headers = files( - 'buf.h', - 'connection.h', - 'dbuf.h', 'debug.h', 'format.h', - 'gate.h', - 'generate.h', 'private.h', - 'sbuf.h', - 'semaphore.h', - 'thread.h', - 'threadpool.h', 'transform.h', - 'util.h', - 'vector.h', ) public_deprecated_headers = files( @@ -33,14 +23,19 @@ endif public_headers = files( 'arithmetic.h', 'basic.h', + 'buf.h', 'colour.h', + 'connection.h', 'conversion.h', 'convolution.h', 'create.h', + 'dbuf.h', 'draw.h', 'error.h', 'foreign.h', 'freqfilt.h', + 'gate.h', + 'generate.h', 'header.h', 'histogram.h', 'image.h', @@ -53,7 +48,13 @@ public_headers = files( 'rect.h', 'region.h', 'resample.h', + 'sbuf.h', + 'semaphore.h', + 'thread.h', + 'threadpool.h', 'type.h', + 'util.h', + 'vector.h', 'vips.h', ) @@ -94,8 +95,8 @@ enumtypes = gnome.mkenums( vips_verbose_config = [] foreach _, section : build_summary foreach key, arr : section - if key.contains('gtk-doc') or \ - key.contains('doxygen') or \ + if key.contains('docs') or \ + key.contains('cpp-docs') or \ key.contains('introspection') or \ key.contains('examples') continue diff --git a/libvips/include/vips/mosaicing.h b/libvips/include/vips/mosaicing.h index 28388a55c4..0c794c9b8c 100644 --- a/libvips/include/vips/mosaicing.h +++ b/libvips/include/vips/mosaicing.h @@ -72,6 +72,10 @@ VIPS_API int vips_matrixinvert(VipsImage *m, VipsImage **out, ...) G_GNUC_NULL_TERMINATED; +VIPS_API +int vips_matrixmultiply(VipsImage *left, VipsImage *right, VipsImage **out, ...) + G_GNUC_NULL_TERMINATED; + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index 0c4cbddf04..368f0b2a63 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -137,8 +137,7 @@ typedef enum /*< flags >*/ { #define VIPS_ARG_INTERPOLATE(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET) \ VIPS_ARG_OBJECT(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, VIPS_TYPE_INTERPOLATE) -#define VIPS_ARG_BOOL(CLASS, NAME, PRIORITY, LONG, DESC, \ - FLAGS, OFFSET, VALUE) \ +#define VIPS_ARG_BOOL(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, VALUE) \ { \ GParamSpec *pspec; \ \ @@ -151,8 +150,7 @@ typedef enum /*< flags >*/ { pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET)); \ } -#define VIPS_ARG_DOUBLE(CLASS, NAME, PRIORITY, LONG, DESC, \ - FLAGS, OFFSET, MIN, MAX, VALUE) \ +#define VIPS_ARG_DOUBLE(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, MIN, MAX, VALUE) \ { \ GParamSpec *pspec; \ \ @@ -165,8 +163,7 @@ typedef enum /*< flags >*/ { pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET)); \ } -#define VIPS_ARG_BOXED(CLASS, NAME, PRIORITY, LONG, DESC, \ - FLAGS, OFFSET, TYPE) \ +#define VIPS_ARG_BOXED(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, TYPE) \ { \ GParamSpec *pspec; \ \ @@ -179,8 +176,7 @@ typedef enum /*< flags >*/ { pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET)); \ } -#define VIPS_ARG_INT(CLASS, NAME, PRIORITY, LONG, DESC, \ - FLAGS, OFFSET, MIN, MAX, VALUE) \ +#define VIPS_ARG_INT(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, MIN, MAX, VALUE) \ { \ GParamSpec *pspec; \ \ @@ -193,8 +189,7 @@ typedef enum /*< flags >*/ { pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET)); \ } -#define VIPS_ARG_UINT64(CLASS, NAME, PRIORITY, LONG, DESC, \ - FLAGS, OFFSET, MIN, MAX, VALUE) \ +#define VIPS_ARG_UINT64(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, MIN, MAX, VALUE) \ { \ GParamSpec *pspec; \ \ @@ -207,8 +202,7 @@ typedef enum /*< flags >*/ { pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET)); \ } -#define VIPS_ARG_ENUM(CLASS, NAME, PRIORITY, LONG, DESC, \ - FLAGS, OFFSET, TYPE, VALUE) \ +#define VIPS_ARG_ENUM(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, TYPE, VALUE) \ { \ GParamSpec *pspec; \ \ @@ -221,8 +215,7 @@ typedef enum /*< flags >*/ { pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET)); \ } -#define VIPS_ARG_FLAGS(CLASS, NAME, PRIORITY, LONG, DESC, \ - FLAGS, OFFSET, TYPE, VALUE) \ +#define VIPS_ARG_FLAGS(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, TYPE, VALUE) \ { \ GParamSpec *pspec; \ \ @@ -235,8 +228,7 @@ typedef enum /*< flags >*/ { pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET)); \ } -#define VIPS_ARG_STRING(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \ - VALUE) \ +#define VIPS_ARG_STRING(CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, VALUE) \ { \ GParamSpec *pspec; \ \ @@ -318,8 +310,14 @@ typedef GHashTable VipsArgumentTable; VIPS_API int vips_argument_get_id(void); + +#ifndef __GI_SCANNER__ + void vips__object_set_member(VipsObject *object, GParamSpec *pspec, GObject **member, GObject *argument); + +#endif /* !__GI_SCANNER__ */ + typedef void *(*VipsArgumentMapFn)(VipsObject *object, GParamSpec *pspec, VipsArgumentClass *argument_class, VipsArgumentInstance *argument_instance, void *a, void *b); @@ -626,8 +624,6 @@ void vips_object_print_name(VipsObject *object); VIPS_API gboolean vips_object_sanity(VipsObject *object); -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_object_get_type(void); diff --git a/libvips/include/vips/operation.h b/libvips/include/vips/operation.h index 7384a4eede..8e115f0ca6 100644 --- a/libvips/include/vips/operation.h +++ b/libvips/include/vips/operation.h @@ -100,8 +100,6 @@ typedef struct _VipsOperationClass { void (*invalidate)(VipsOperation *operation); } VipsOperationClass; -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_operation_get_type(void); diff --git a/libvips/include/vips/private.h b/libvips/include/vips/private.h index 766c455c97..19cbf15f42 100644 --- a/libvips/include/vips/private.h +++ b/libvips/include/vips/private.h @@ -40,6 +40,8 @@ extern "C" { #endif /*__cplusplus*/ +#include + #define VIPS_SPARE (8) /* Private to iofuncs: the minimum number of scanlines we add above and below @@ -218,8 +220,6 @@ int vips__view_image(struct _VipsImage *image); VIPS_API int _vips__argument_id; -void vips__meta_init(void); - // autoptr needs typed functions for autofree ... this needs to be in the // public API since downstream projects can use our auto defs VIPS_API @@ -227,6 +227,54 @@ void VipsArrayDouble_unref(VipsArrayDouble *array); VIPS_API void VipsArrayImage_unref(VipsArrayImage *array); +extern gboolean vips__thread_profile; + +void vips__thread_gate_start(const char *gate_name); +void vips__thread_gate_stop(const char *gate_name); + +void vips__thread_malloc_free(gint64 size); + +FILE *vips__file_open_read(const char *filename, + const char *fallback_dir, gboolean text_mode); +FILE *vips__file_open_write(const char *filename, + gboolean text_mode); + +/* TODO(kleisauke): VIPS_API is required by vipsedit. + */ +VIPS_API +int vips__write(int fd, const void *buf, size_t count); + +/* TODO(kleisauke): VIPS_API is required by test_connections. + */ +VIPS_API +int vips__open(const char *filename, int flags, int mode); + +/* TODO(kleisauke): VIPS_API is required by vipsedit. + */ +VIPS_API +char *vips__file_read(FILE *fp, const char *name, size_t *length_out); + +/* TODO(kleisauke): VIPS_API is required by the magick module. + */ +VIPS_API +gint64 vips__get_bytes(const char *filename, unsigned char buf[], gint64 len); + +/* TODO(kleisauke): VIPS_API is required by vipsedit. + */ +VIPS_API +gint64 vips__seek(int fd, gint64 pos, int whence); + +/* TODO(kleisauke): VIPS_API is required by libvips-cpp and vipsheader. + */ +VIPS_API +void vips__filename_split8(const char *name, + char *filename, char *option_string); + +/* TODO(kleisauke): VIPS_API is required by jpegsave_file_fuzzer. + */ +VIPS_API +char *vips__temp_name(const char *format); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/region.h b/libvips/include/vips/region.h index b0662890f5..d7f06c5746 100644 --- a/libvips/include/vips/region.h +++ b/libvips/include/vips/region.h @@ -90,9 +90,9 @@ typedef enum { struct _VipsRegion { VipsObject parent_object; - /*< public >*/ /* Users may read these two fields. */ + /*< public >*/ VipsImage *im; /* Link back to parent image */ VipsRect valid; /* Area of parent we can see */ @@ -128,8 +128,6 @@ typedef struct _VipsRegionClass { } VipsRegionClass; -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_region_get_type(void); diff --git a/libvips/include/vips/semaphore.h b/libvips/include/vips/semaphore.h index adab65cd8a..d548c397c0 100644 --- a/libvips/include/vips/semaphore.h +++ b/libvips/include/vips/semaphore.h @@ -38,8 +38,6 @@ #define VIPS_SEMAPHORE_H #include -#include -#include #ifdef __cplusplus extern "C" { @@ -48,10 +46,17 @@ extern "C" { /* Implement our own semaphores. */ typedef struct { + /* All fields are private. + */ + /*< private >*/ char *name; int v; - GMutex *mutex; + GMutex mutex; + + /* FIXME: sizeof(GCond) != sizeof(GCond *) + * https://gitlab.gnome.org/GNOME/glib/-/issues/1256 + */ GCond *cond; } VipsSemaphore; diff --git a/libvips/include/vips/thread.h b/libvips/include/vips/thread.h index 79f41e213a..3670c83001 100644 --- a/libvips/include/vips/thread.h +++ b/libvips/include/vips/thread.h @@ -36,25 +36,8 @@ extern "C" { #endif /*__cplusplus*/ -/* We need wrappers over g_mutex_new(), it was replaced by g_mutex_init() in - * glib 2.32+ - */ -VIPS_API -GMutex *vips_g_mutex_new(void); -VIPS_API -void vips_g_mutex_free(GMutex *); - -/* Same for GCond. - */ VIPS_API -GCond *vips_g_cond_new(void); -VIPS_API -void vips_g_cond_free(GCond *); - -/* ... and for GThread. - */ -VIPS_API -GThread *vips_g_thread_new(const char *, GThreadFunc, gpointer); +GThread *vips_g_thread_new(const char *domain, GThreadFunc func, gpointer data); VIPS_API gboolean vips_thread_isvips(void); @@ -62,12 +45,6 @@ gboolean vips_thread_isvips(void); VIPS_API int vips_thread_execute(const char *domain, GFunc func, gpointer data); -typedef struct _VipsThreadset VipsThreadset; -VipsThreadset *vips_threadset_new(int max_threads); -int vips_threadset_run(VipsThreadset *set, - const char *domain, GFunc func, gpointer data); -void vips_threadset_free(VipsThreadset *set); - #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/threadpool.h b/libvips/include/vips/threadpool.h index 77230f3128..9f31bb17ed 100644 --- a/libvips/include/vips/threadpool.h +++ b/libvips/include/vips/threadpool.h @@ -51,10 +51,6 @@ extern "C" { #endif /*__cplusplus*/ -/* Per-thread state. Allocate functions can use these members to - * communicate with work functions. - */ - #define VIPS_TYPE_THREAD_STATE (vips_thread_state_get_type()) #define VIPS_THREAD_STATE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), \ @@ -112,8 +108,6 @@ typedef struct _VipsThreadStateClass { VIPS_API void *vips_thread_state_set(VipsObject *object, void *a, void *b); -/* Don't put spaces around void here, it breaks gtk-doc. - */ VIPS_API GType vips_thread_state_get_type(void); diff --git a/libvips/include/vips/type.h b/libvips/include/vips/type.h index 1de36a631f..8514aab023 100644 --- a/libvips/include/vips/type.h +++ b/libvips/include/vips/type.h @@ -38,6 +38,8 @@ extern "C" { #endif /*__cplusplus*/ +#ifndef __GI_SCANNER__ + /* A very simple boxed type for testing. Just holds an int. */ typedef struct _VipsThing { @@ -47,7 +49,7 @@ typedef struct _VipsThing { /** * VIPS_TYPE_THING: * - * The #GType for a #VipsThing. + * The [alias@GObject.Type] for a #VipsThing. */ #define VIPS_TYPE_THING (vips_thing_get_type()) VIPS_API @@ -55,6 +57,8 @@ GType vips_thing_get_type(void); VIPS_API VipsThing *vips_thing_new(int i); +#endif /* !__GI_SCANNER__ */ + /* A ref-counted area of memory. Can hold arrays of things as well. */ typedef struct _VipsArea { @@ -74,7 +78,7 @@ typedef struct _VipsArea { * structure, so a simple GMutex is OK. */ int count; - GMutex *lock; + GMutex lock; /* Things like ICC profiles need their own free functions. * @@ -131,7 +135,7 @@ void *vips_area_get_data(VipsArea *area, /** * VIPS_TYPE_AREA: * - * The #GType for a #VipsArea. + * The [alias@GObject.Type] for a [struct@Area]. */ #define VIPS_TYPE_AREA (vips_area_get_type()) #define VIPS_AREA(X) ((VipsArea *) (X)) @@ -141,7 +145,7 @@ GType vips_area_get_type(void); /** * VIPS_TYPE_SAVE_STRING: * - * The #GType for a #VipsSaveString. + * The [alias@GObject.Type] for a [struct@SaveString]. */ #define VIPS_TYPE_SAVE_STRING (vips_save_string_get_type()) VIPS_API @@ -154,7 +158,7 @@ typedef struct _VipsSaveString { /** * VIPS_TYPE_REF_STRING: * - * The #GType for a #VipsRefString. + * The [alias@GObject.Type] for a [struct@RefString]. */ #define VIPS_TYPE_REF_STRING (vips_ref_string_get_type()) @@ -172,7 +176,7 @@ GType vips_ref_string_get_type(void); /** * VIPS_TYPE_BLOB: * - * The %GType for a #VipsBlob. + * The [alias@GObject.Type] for a [struct@Blob]. */ #define VIPS_TYPE_BLOB (vips_blob_get_type()) @@ -196,7 +200,7 @@ GType vips_blob_get_type(void); /** * VIPS_TYPE_ARRAY_DOUBLE: * - * The #GType for a #VipsArrayDouble. + * The [alias@GObject.Type] for a [struct@ArrayDouble]. */ #define VIPS_TYPE_ARRAY_DOUBLE (vips_array_double_get_type()) @@ -216,7 +220,7 @@ GType vips_array_double_get_type(void); /** * VIPS_TYPE_ARRAY_INT: * - * The #GType for a #VipsArrayInt. + * The [alias@GObject.Type] for a [struct@ArrayInt]. */ #define VIPS_TYPE_ARRAY_INT (vips_array_int_get_type()) @@ -236,7 +240,7 @@ GType vips_array_int_get_type(void); /** * VIPS_TYPE_ARRAY_IMAGE: * - * The #GType for a #VipsArrayImage. + * The [alias@GObject.Type] for a [struct@ArrayImage]. */ #define VIPS_TYPE_ARRAY_IMAGE (vips_array_image_get_type()) diff --git a/libvips/include/vips/util.h b/libvips/include/vips/util.h index 201adf9251..82f619bca3 100644 --- a/libvips/include/vips/util.h +++ b/libvips/include/vips/util.h @@ -39,7 +39,6 @@ extern "C" { #endif /*__cplusplus*/ -#include #include /* Some platforms don't have M_PI :-( @@ -54,38 +53,25 @@ extern "C" { #define VIPS_MAX(A, B) ((A) > (B) ? (A) : (B)) #define VIPS_MIN(A, B) ((A) < (B) ? (A) : (B)) +#define VIPS_FMAX(A, B) fmax((A), (B)) VIPS_DEPRECATED_MACRO_FOR(fmax) +#define VIPS_FMIN(A, B) fmin((A), (B)) VIPS_DEPRECATED_MACRO_FOR(fmin) + #define VIPS_CLIP(A, V, B) VIPS_MAX((A), VIPS_MIN((B), (V))) -#define VIPS_FCLIP(A, V, B) VIPS_FMAX((A), VIPS_FMIN((B), (V))) +#define VIPS_FCLIP(A, V, B) fmax((A), fmin((B), (V))) #define VIPS_NUMBER(R) ((int) (sizeof(R) / sizeof(R[0]))) -#define VIPS_ABS(X) (((X) >= 0) ? (X) : -(X)) +#define VIPS_ABS(V) (((V) >= 0) ? (V) : -(V)) +#define VIPS_FABS(V) fabs((V)) VIPS_DEPRECATED_MACRO_FOR(fabs) // is something (eg. a pointer) N aligned #define VIPS_ALIGNED(P, N) ((((guint64) (P)) & ((N) - 1)) == 0) -/* The built-in isnan and isinf functions provided by gcc 4+ and clang are - * up to 7x faster than their libc equivalent included from . - */ -#if defined(__clang__) || (__GNUC__ >= 4) -#define VIPS_ISNAN(V) __builtin_isnan(V) -#define VIPS_FLOOR(V) __builtin_floor(V) -#define VIPS_CEIL(V) __builtin_ceil(V) -#define VIPS_RINT(V) __builtin_rint(V) -#define VIPS_ROUND(V) __builtin_round(V) -#define VIPS_FABS(V) __builtin_fabs(V) -#define VIPS_FMAX(A, B) __builtin_fmax(A, B) -#define VIPS_FMIN(A, B) __builtin_fmin(A, B) -#else -#define VIPS_ISNAN(V) isnan(V) -#define VIPS_FLOOR(V) floor(V) -#define VIPS_CEIL(V) ceil(V) -#define VIPS_RINT(V) rint(V) -#define VIPS_ROUND(V) round(V) -#define VIPS_FABS(V) VIPS_ABS(V) -#define VIPS_FMAX(A, B) VIPS_MAX(A, B) -#define VIPS_FMIN(A, B) VIPS_MIN(A, B) -#endif +#define VIPS_ISNAN(V) isnan(V) VIPS_DEPRECATED_MACRO_FOR(isnan) +#define VIPS_FLOOR(V) floor(V) VIPS_DEPRECATED_MACRO_FOR(floor) +#define VIPS_CEIL(V) ceil(V) VIPS_DEPRECATED_MACRO_FOR(ceil) +#define VIPS_RINT(V) rint(V) VIPS_DEPRECATED_MACRO_FOR(rint) +#define VIPS_ROUND(V) round(V) VIPS_DEPRECATED_MACRO_FOR(round) /* Testing status before the function call saves a lot of time. */ @@ -97,7 +83,7 @@ extern "C" { } \ G_STMT_END -/* VIPS_RINT() does "bankers rounding", it rounds to the nearest even integer. +/* rint() does "bankers rounding", it rounds to the nearest even integer. * For things like image geometry, we want strict nearest int. * * If you know it's unsigned, _UINT is a little faster. @@ -298,47 +284,7 @@ int vips_filename_suffix_match(const char *path, const char *suffixes[]); VIPS_API gint64 vips_file_length(int fd); -/* TODO(kleisauke): VIPS_API is required by vipsedit. - */ -VIPS_API -int vips__write(int fd, const void *buf, size_t count); - -/* TODO(kleisauke): VIPS_API is required by test_connections. - */ -VIPS_API -int vips__open(const char *filename, int flags, int mode); -int vips__open_read(const char *filename); -FILE *vips__fopen(const char *filename, const char *mode); - -FILE *vips__file_open_read(const char *filename, - const char *fallback_dir, gboolean text_mode); -FILE *vips__file_open_write(const char *filename, - gboolean text_mode); -/* TODO(kleisauke): VIPS_API is required by vipsedit. - */ -VIPS_API -char *vips__file_read(FILE *fp, const char *name, size_t *length_out); -char *vips__file_read_name(const char *name, const char *fallback_dir, - size_t *length_out); -int vips__file_write(void *data, size_t size, size_t nmemb, FILE *stream); -/* TODO(kleisauke): VIPS_API is required by the magick module. - */ -VIPS_API -gint64 vips__get_bytes(const char *filename, unsigned char buf[], gint64 len); -int vips__fgetc(FILE *fp); - -GValue *vips__gvalue_ref_string_new(const char *text); -void vips__gslist_gvalue_free(GSList *list); -GSList *vips__gslist_gvalue_copy(const GSList *list); -GSList *vips__gslist_gvalue_merge(GSList *a, const GSList *b); -char *vips__gslist_gvalue_get(const GSList *list); -gint64 vips__seek_no_error(int fd, gint64 pos, int whence); -/* TODO(kleisauke): VIPS_API is required by vipsedit. - */ -VIPS_API -gint64 vips__seek(int fd, gint64 pos, int whence); -int vips__ftruncate(int fd, gint64 pos); VIPS_API int vips_existsf(const char *name, ...) G_GNUC_PRINTF(1, 2); @@ -355,7 +301,7 @@ VIPS_API int vips_rename(const char *old_name, const char *new_name); /** - * VipsToken: + * VipsToken: (skip) * @VIPS_TOKEN_LEFT: left bracket * @VIPS_TOKEN_RIGHT: right bracket * @VIPS_TOKEN_STRING: string constant @@ -369,7 +315,6 @@ int vips_rename(const char *old_name, const char *new_name); * * Strings may be in double quotes, and may contain escaped quote characters, * for example string, "string" and "str\"ing". - * */ typedef enum { VIPS_TOKEN_LEFT = 1, @@ -379,49 +324,23 @@ typedef enum { VIPS_TOKEN_COMMA } VipsToken; +#ifndef __GI_SCANNER__ + // we expose this one in the API for testing VIPS_API const char *vips__token_get(const char *buffer, VipsToken *token, char *string, int size); -const char *vips__token_must(const char *buffer, VipsToken *token, - char *string, int size); -const char *vips__token_need(const char *buffer, VipsToken need_token, - char *string, int size); -const char *vips__token_segment(const char *p, VipsToken *token, - char *string, int size); -const char *vips__token_segment_need(const char *p, VipsToken need_token, - char *string, int size); -const char *vips__find_rightmost_brackets(const char *p); -/* TODO(kleisauke): VIPS_API is required by libvips-cpp and vipsheader. - */ -VIPS_API -void vips__filename_split8(const char *name, - char *filename, char *option_string); + +#endif /* !__GI_SCANNER__ */ VIPS_API int vips_ispoweroftwo(int p); VIPS_API int vips_amiMSBfirst(void); -/* TODO(kleisauke): VIPS_API is required by jpegsave_file_fuzzer. - */ -VIPS_API -char *vips__temp_name(const char *format); - -void vips__change_suffix(const char *name, char *out, int mx, - const char *new_suff, const char **olds, int nolds); - VIPS_API char *vips_realpath(const char *path); -guint32 vips__random(guint32 seed); -guint32 vips__random_add(guint32 seed, int value); - -const char *vips__icc_dir(void); -const char *vips__windows_prefix(void); - -char *vips__get_iso8601(void); - VIPS_API int vips_strtod(const char *str, double *out); diff --git a/libvips/include/vips/vector.h b/libvips/include/vips/vector.h index 7dc1ee6864..445ecb2b26 100644 --- a/libvips/include/vips/vector.h +++ b/libvips/include/vips/vector.h @@ -38,10 +38,6 @@ extern "C" { #endif /*__cplusplus*/ -/* Set from the command-line. - */ -extern gboolean vips__vector_enabled; - VIPS_API gboolean vips_vector_isenabled(void); VIPS_API diff --git a/libvips/include/vips/vips.h b/libvips/include/vips/vips.h index 9e74ef5579..e77dcbd34d 100644 --- a/libvips/include/vips/vips.h +++ b/libvips/include/vips/vips.h @@ -117,6 +117,7 @@ extern "C" { #include #include #include +#include #include #include #include diff --git a/libvips/iofuncs/buf.c b/libvips/iofuncs/buf.c index 38c05cb4c0..7b9ebcfc3c 100644 --- a/libvips/iofuncs/buf.c +++ b/libvips/iofuncs/buf.c @@ -46,11 +46,7 @@ #include /** - * SECTION: buf - * @short_description: a string you can append to - * @stability: Stable - * @see_also: #vips - * @include: vips/vips.h + * VipsBuf: * * A message buffer you can append stuff to safely and quickly. If the message * gets too long, you get "..." and truncation. Message buffers can be on the @@ -58,19 +54,19 @@ * * For example: * - * |[ + * ```c * char txt[256]; * VipsBuf buf = VIPS_BUF_STATIC(txt); * int i; * * vips_buf_appends(&buf, "Numbers are: "); - * for (i = 0; i < array_length; i++) { - * if (i > 0) + * for (i = 0; i < array_length; i++) { + * if (i > 0) * vips_buf_appends(&buf, ", "); * vips_buf_appendg(&buf, array[i]); * } * printf("%s", vips_buf_all(&buf)); - * ]| + * ``` */ /** @@ -79,10 +75,10 @@ * * Initialize a heap buffer. For example: * - * |[ + * ```c * char txt[256]; * VipsBuf buf = VIPS_BUF_STATIC(txt); - * ]| + * ``` */ /** @@ -162,17 +158,17 @@ vips_buf_set_static(VipsBuf *buf, char *base, int mx) * @base: the start of the memory area to use for storage * @mx: the size of the storage area * - * Initialise and attach to a static memory area. VIPS_BUF_STATIC() is usually + * Initialise and attach to a static memory area. [func@BUF_STATIC] is usually * more convenient. * * For example: * - * |[ + * ```c * char txt[256]; * VipsBuf buf; * * vips_buf_init_static(&buf, txt, 256); - * ]| + * ``` * * Static buffers don't need to be freed when they go out of scope, but their * size must be set at compile-time. @@ -224,13 +220,13 @@ vips_buf_set_dynamic(VipsBuf *buf, int mx) * Initialise and attach to a heap memory area. * The memory area needs to be at least 4 bytes long. * - * |[ + * ```c * VipsBuf buf; * - * vips_buf_init_synamic(&buf, 256); - * ]| + * vips_buf_init_dynamic(&buf, 256); + * ``` * - * Dynamic buffers must be freed with vips_buf_destroy(), but their size can + * Dynamic buffers must be freed with [method@Buf.destroy], but their size can * be set at runtime. */ void @@ -247,10 +243,10 @@ vips_buf_init_dynamic(VipsBuf *buf, int mx) * @sz: the size of the string to append * * Append at most @sz chars from @str to @buf. @sz < 0 means unlimited. This - * is the low-level append operation: functions like vips_buf_appendf() build + * is the low-level append operation: functions like [method@Buf.appendf] build * on top of this. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_appendns(VipsBuf *buf, const char *str, int sz) @@ -304,7 +300,7 @@ vips_buf_appendns(VipsBuf *buf, const char *str, int sz) * * Append the whole of @str to @buf. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_appends(VipsBuf *buf, const char *str) @@ -319,7 +315,7 @@ vips_buf_appends(VipsBuf *buf, const char *str) * * Append a single character @ch to @buf. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_appendc(VipsBuf *buf, char ch) @@ -340,7 +336,7 @@ vips_buf_appendc(VipsBuf *buf, char ch) * * Swap the rightmost occurrence of @o for @n. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_change(VipsBuf *buf, const char *old, const char *new) @@ -365,8 +361,7 @@ vips_buf_change(VipsBuf *buf, const char *old, const char *new) /* Move tail of buffer to make right-size space for new. */ - memmove(buf->base + i + nlen, buf->base + i + olen, - buf->i - i - olen); + memmove(buf->base + i + nlen, buf->base + i + olen, buf->i - i - olen); /* Copy new in. */ @@ -383,7 +378,7 @@ vips_buf_change(VipsBuf *buf, const char *old, const char *new) * * Remove the last character, if it's @ch. * - * Returns: %FALSE on failure, %TRUE otherwise. + * Returns: `FALSE` on failure, `TRUE` otherwise. */ gboolean vips_buf_removec(VipsBuf *buf, char ch) @@ -401,12 +396,12 @@ vips_buf_removec(VipsBuf *buf, char ch) /** * vips_buf_vappendf: * @buf: the buffer - * @fmt: printf()-style format string + * @fmt: `printf()`-style format string * @ap: arguments to format string * - * Append to @buf, args as vprintf(). + * Append to @buf, args as [`vprintf()`](man:vprintf(3)). * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_vappendf(VipsBuf *buf, const char *fmt, va_list ap) @@ -417,7 +412,10 @@ vips_buf_vappendf(VipsBuf *buf, const char *fmt, va_list ap) if (buf->full) return FALSE; - avail = buf->mx - buf->i - 4; + // -3 to leave space for "..." + // not -4, since the terminating \0 will already be on the string written + // by g_vsnprintf() + avail = buf->mx - buf->i - 3; p = buf->base + buf->i; (void) g_vsnprintf(p, avail, fmt, ap); buf->i += strlen(p); @@ -435,12 +433,12 @@ vips_buf_vappendf(VipsBuf *buf, const char *fmt, va_list ap) /** * vips_buf_appendf: * @buf: the buffer - * @fmt: printf()-style format string + * @fmt: `printf()`-style format string * @...: arguments to format string * * Format the string and append to @buf. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_appendf(VipsBuf *buf, const char *fmt, ...) @@ -462,7 +460,7 @@ vips_buf_appendf(VipsBuf *buf, const char *fmt, ...) * * Append a double, non-localised. Useful for config files etc. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_appendg(VipsBuf *buf, double g) @@ -482,7 +480,7 @@ vips_buf_appendg(VipsBuf *buf, double g) * Append a number. If the number is -ve, add brackets. Needed for * building function arguments. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_appendd(VipsBuf *buf, int d) @@ -496,15 +494,15 @@ vips_buf_appendd(VipsBuf *buf, int d) /** * vips_buf_appendgv: * @buf: the buffer - * @value: #GValue to format and append + * @value: [struct@GObject.Value] to format and append * - * Format and append a #GValue as a printable thing. We display text line "3144 - * bytes of binary data" for BLOBs like icc-profile-data. + * Format and append a [struct@GObject.Value] as a printable thing. + * We display text like "3144 bytes of binary data" for BLOBs like icc-profile-data. * - * Use vips_image_get_as_string() to make a text representation of a field. + * Use [method@Image.get_as_string] to make a text representation of a field. * That will base64-encode blobs, for example. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_appendgv(VipsBuf *buf, GValue *value) @@ -542,8 +540,7 @@ vips_buf_appendgv(VipsBuf *buf, GValue *value) } break; case G_TYPE_INT: - result = vips_buf_appendf(buf, - "%d", g_value_get_int(value)); + result = vips_buf_appendf(buf, "%d", g_value_get_int(value)); handled = TRUE; break; @@ -554,8 +551,7 @@ vips_buf_appendgv(VipsBuf *buf, GValue *value) break; case G_TYPE_DOUBLE: - result = vips_buf_appendf(buf, - "%g", g_value_get_double(value)); + result = vips_buf_appendf(buf, "%g", g_value_get_double(value)); handled = TRUE; break; @@ -636,8 +632,7 @@ vips_buf_appendgv(VipsBuf *buf, GValue *value) arr = vips_value_get_array_image(value, &n); for (i = 0; i < n; i++) { - vips_object_summary(VIPS_OBJECT(arr[i]), - buf); + vips_object_summary(VIPS_OBJECT(arr[i]), buf); result = vips_buf_appends(buf, " "); } handled = TRUE; @@ -667,7 +662,7 @@ vips_buf_appendgv(VipsBuf *buf, GValue *value) * Turn a number of bytes into a sensible string ... eg "12", "12KB", "12MB", * "12GB" etc. * - * Returns: %FALSE on overflow, %TRUE otherwise. + * Returns: `FALSE` on overflow, `TRUE` otherwise. */ gboolean vips_buf_append_size(VipsBuf *buf, size_t n) @@ -716,7 +711,7 @@ vips_buf_append_size(VipsBuf *buf, size_t n) * * Return the contents of the buffer as a C string. * - * Returns: the %NULL-terminated contents of the buffer. This is a pointer to + * Returns: the `NULL`-terminated contents of the buffer. This is a pointer to * the memory managed by the buffer and must not be freed. */ const char * @@ -733,7 +728,7 @@ vips_buf_all(VipsBuf *buf) * * Trim to just the first line (excluding "\n"). * - * Returns: the %NULL-terminated contents of the buffer. This is a pointer to + * Returns: the `NULL`-terminated contents of the buffer. This is a pointer to * the memory managed by the buffer and must not be freed. */ const char * @@ -751,7 +746,7 @@ vips_buf_firstline(VipsBuf *buf) * vips_buf_is_empty: * @buf: the buffer * - * Returns: %TRUE if the buffer is empty. + * Returns: `TRUE` if the buffer is empty. */ gboolean vips_buf_is_empty(VipsBuf *buf) @@ -763,7 +758,7 @@ vips_buf_is_empty(VipsBuf *buf) * vips_buf_is_full: * @buf: the buffer * - * Returns: %TRUE if the buffer is full. + * Returns: `TRUE` if the buffer is full. */ gboolean vips_buf_is_full(VipsBuf *buf) diff --git a/libvips/iofuncs/buffer.c b/libvips/iofuncs/buffer.c index 3b0acac999..158d272abd 100644 --- a/libvips/iofuncs/buffer.c +++ b/libvips/iofuncs/buffer.c @@ -70,7 +70,6 @@ #include #include -#include #ifdef DEBUG /* Track all buffers here for debugging. @@ -206,12 +205,12 @@ vips_buffer_free(VipsBuffer *buffer) g_free(buffer); #ifdef DEBUG - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); g_assert(g_slist_find(vips__buffer_all, buffer)); vips__buffer_all = g_slist_remove(vips__buffer_all, buffer); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); #endif /*DEBUG*/ #ifdef DEBUG_VERBOSE @@ -234,10 +233,10 @@ buffer_cache_free(VipsBufferCache *cache) GSList *p; #ifdef DEBUG_CREATE - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips__buffer_cache_all = g_slist_remove(vips__buffer_cache_all, cache); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); printf("buffer_cache_free: freeing cache %p on thread %p\n", cache, g_thread_self()); @@ -283,10 +282,10 @@ buffer_cache_new(VipsBufferThread *buffer_thread, VipsImage *im) cache->n_reserve = 0; #ifdef DEBUG_CREATE - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips__buffer_cache_all = g_slist_prepend(vips__buffer_cache_all, cache); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); printf("buffer_cache_new: new cache %p for thread %p on image %p\n", cache, g_thread_self(), im); @@ -537,10 +536,10 @@ vips_buffer_new(VipsImage *im, VipsRect *area) buffer->bsize = 0; #ifdef DEBUG - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips__buffer_all = g_slist_prepend(vips__buffer_all, buffer); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); #endif /*DEBUG*/ } diff --git a/libvips/iofuncs/cache.c b/libvips/iofuncs/cache.c index 7a187ec182..0a23084d8b 100644 --- a/libvips/iofuncs/cache.c +++ b/libvips/iofuncs/cache.c @@ -103,7 +103,7 @@ static int vips_cache_time = 0; /* Protect cache access with this. */ -static GMutex *vips_cache_lock = NULL; +static GMutex vips_cache_lock; /* A cache entry. */ @@ -131,7 +131,7 @@ typedef struct _VipsOperationCacheEntry { * VipsImage. generics are much faster to compare. */ static unsigned int -vips_value_hash(GParamSpec *pspec, GValue *value) +vips_value_hash(GParamSpec *pspec, const GValue *value) { GType generic = G_PARAM_SPEC_TYPE(pspec); @@ -227,7 +227,7 @@ vips_value_hash(GParamSpec *pspec, GValue *value) * could be of type VipsImage. generics are much faster to compare. */ static gboolean -vips_value_equal(GParamSpec *pspec, GValue *v1, GValue *v2) +vips_value_equal(GParamSpec *pspec, const GValue *v1, const GValue *v2) { GType generic = G_PARAM_SPEC_TYPE(pspec); GType t1 = G_VALUE_TYPE(v1); @@ -335,14 +335,16 @@ vips_object_hash_arg(VipsObject *object, return NULL; } -/* Find a hash from the input arguments to a VipsOperstion. +/* Find a hash from the input arguments to a VipsOperation. */ -static unsigned int +unsigned int vips_operation_hash(VipsOperation *operation) { - if (!operation->found_hash) { - guint hash; + guint hash; + if (operation->found_hash) + hash = operation->hash; + else { /* Include the operation type in the hash. */ hash = (guint) G_OBJECT_TYPE(operation); @@ -353,11 +355,16 @@ vips_operation_hash(VipsOperation *operation) */ hash |= 1; - operation->hash = hash; - operation->found_hash = TRUE; + /* The hash can change up to the moment of construction. After that, + * it should be fixed. + */ + if (VIPS_OBJECT(operation)->constructed) { + operation->hash = hash; + operation->found_hash = TRUE; + } } - return operation->hash; + return hash; } static void * @@ -393,7 +400,7 @@ vips_object_equal_arg(VipsObject *object, /* Optional and was not set on other ... we've found a * difference! */ - return object; + return (void *) name; g_value_init(&v1, type); g_value_init(&v2, type); @@ -405,7 +412,7 @@ vips_object_equal_arg(VipsObject *object, /* Stop (return non-NULL) if we've found a difference. */ - return !equal ? object : NULL; + return !equal ? (void *) name : NULL; } /* Are two objects equal, ie. have the same inputs. @@ -418,21 +425,110 @@ vips_operation_equal(VipsOperation *a, VipsOperation *b) if (G_OBJECT_TYPE(a) == G_OBJECT_TYPE(b) && vips_operation_hash(a) == vips_operation_hash(b) && - !vips_argument_map(VIPS_OBJECT(a), - vips_object_equal_arg, b, NULL)) + !vips_argument_map(VIPS_OBJECT(a), vips_object_equal_arg, b, NULL)) return TRUE; return FALSE; } +static void * +vips_operation_copy_argument(VipsObject *object, + GParamSpec *pspec, + VipsArgumentClass *argument_class, + VipsArgumentInstance *argument_instance, + void *a, void *b) +{ + VipsOperation *new = VIPS_OPERATION(a); + + if ((argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && + (argument_class->flags & VIPS_ARGUMENT_INPUT) && + argument_instance->assigned) { + const char *name = g_param_spec_get_name(pspec); + GType type = G_PARAM_SPEC_VALUE_TYPE(pspec); + GValue value = G_VALUE_INIT; + + g_value_init(&value, type); + g_object_get_property(G_OBJECT(object), name, &value); + g_object_set_property(G_OBJECT(new), name, &value); + g_value_unset(&value); + } + + return NULL; +} + +static VipsOperation * +vips_operation_copy(VipsOperation *operation) +{ + VipsObject *object = VIPS_OBJECT(operation); + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); + + VipsOperation *new = vips_operation_new(class->nickname); + (void) vips_argument_map(object, vips_operation_copy_argument, new, NULL); + + return new; +} + +static void * +vips_object_unref_arg(VipsObject *object, + GParamSpec *pspec, + VipsArgumentClass *argument_class, + VipsArgumentInstance *argument_instance, + void *a, void *b) +{ + if ((argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && + (argument_class->flags & VIPS_ARGUMENT_OUTPUT) && + argument_instance->assigned && + G_IS_PARAM_SPEC_OBJECT(pspec)) { + GObject *value; + + /* This will up the ref count for us. + */ + g_object_get(G_OBJECT(object), + g_param_spec_get_name(pspec), &value, NULL); + + /* This operation is probably going, so we must wipe the cache + * entry pointer on the object. + */ + g_object_set_data(value, "libvips-cache-entry", NULL); + + /* Drop the ref we just got, then drop the ref we make when we + * added to the cache. + */ + g_object_unref(value); + g_object_unref(value); + } + + return NULL; +} + +static void +vips_cache_free_cb(VipsOperationCacheEntry *entry) +{ +#ifdef DEBUG + printf("vips_cache_free_cb: "); + vips_object_print_summary(VIPS_OBJECT(entry->operation)); +#endif /*DEBUG*/ + + if (entry->invalidate_id) { + g_signal_handler_disconnect(entry->operation, entry->invalidate_id); + entry->invalidate_id = 0; + } + + (void) vips_argument_map(VIPS_OBJECT(entry->operation), + vips_object_unref_arg, NULL, NULL); + g_object_unref(entry->operation); + + g_free(entry); +} + void * vips__cache_once_init(void *data) { - vips_cache_lock = vips_g_mutex_new(); - - vips_cache_table = g_hash_table_new( + vips_cache_table = g_hash_table_new_full( (GHashFunc) vips_operation_hash, - (GEqualFunc) vips_operation_equal); + (GEqualFunc) vips_operation_equal, + NULL, + (GDestroyNotify) vips_cache_free_cb); return NULL; } @@ -478,20 +574,36 @@ vips_cache_print_nolock(void) void vips_cache_print(void) { - g_mutex_lock(vips_cache_lock); + g_mutex_lock(&vips_cache_lock); vips_cache_print_nolock(); - g_mutex_unlock(vips_cache_lock); + g_mutex_unlock(&vips_cache_lock); +} + +static VipsOperationCacheEntry * +vips_cache_operation_get(VipsOperation *operation) +{ + return g_hash_table_lookup(vips_cache_table, operation); +} + +/* Remove an operation from the cache. + */ +static void +vips_cache_remove(VipsOperation *operation) +{ + g_hash_table_remove(vips_cache_table, operation); } static void * -vips_object_unref_arg(VipsObject *object, +vips_object_ref_arg(VipsObject *object, GParamSpec *pspec, VipsArgumentClass *argument_class, VipsArgumentInstance *argument_instance, void *a, void *b) { + VipsOperationCacheEntry *entry = a; + if ((argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && (argument_class->flags & VIPS_ARGUMENT_OUTPUT) && argument_instance->assigned && @@ -503,111 +615,86 @@ vips_object_unref_arg(VipsObject *object, g_object_get(G_OBJECT(object), g_param_spec_get_name(pspec), &value, NULL); - /* Drop the ref we just got, then drop the ref we make when we - * added to the cache. + /* This object has been made by this cache entry. */ - g_object_unref(value); - g_object_unref(value); + g_object_set_data(value, "libvips-cache-entry", entry); } return NULL; } static void -vips_cache_unref(VipsOperation *operation) -{ -#ifdef DEBUG - printf("vips_cache_unref: "); - vips_object_print_summary(VIPS_OBJECT(operation)); -#endif /*DEBUG*/ - - (void) vips_argument_map(VIPS_OBJECT(operation), - vips_object_unref_arg, NULL, NULL); - g_object_unref(operation); -} - -static VipsOperationCacheEntry * -vips_cache_operation_get(VipsOperation *operation) +vips_entry_touch(VipsOperationCacheEntry *entry) { - return g_hash_table_lookup(vips_cache_table, operation); + /* Don't up the time for invalid items -- we want them to fall out of + * cache. + */ + if (!entry->invalid) + entry->time = vips_cache_time; } -/* Remove an operation from the cache. - */ -static void -vips_cache_remove(VipsOperation *operation) +static void * +vips_image_touch_cb(VipsImage *image, void *a, void *b) { - VipsOperationCacheEntry *entry = vips_cache_operation_get(operation); + VipsOperationCacheEntry *entry = + g_object_get_data(G_OBJECT(image), "libvips-cache-entry"); -#ifdef DEBUG - printf("vips_cache_remove: "); - vips_object_print_summary(VIPS_OBJECT(operation)); -#endif /*DEBUG*/ - - g_assert(entry); - - if (entry->invalidate_id) { - g_signal_handler_disconnect(operation, entry->invalidate_id); - entry->invalidate_id = 0; - } - - g_hash_table_remove(vips_cache_table, operation); - vips_cache_unref(operation); + if (entry) + vips_entry_touch(entry); - g_free(entry); + return NULL; } static void * -vips_object_ref_arg(VipsObject *object, +vips_object_touch_arg(VipsObject *object, GParamSpec *pspec, VipsArgumentClass *argument_class, VipsArgumentInstance *argument_instance, void *a, void *b) { if ((argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && - (argument_class->flags & VIPS_ARGUMENT_OUTPUT) && + (argument_class->flags & VIPS_ARGUMENT_INPUT) && argument_instance->assigned && - G_IS_PARAM_SPEC_OBJECT(pspec)) { - GObject *value; + g_type_is_a(G_PARAM_SPEC_VALUE_TYPE(pspec), VIPS_TYPE_IMAGE)) { + VipsImage *image; - /* This will up the ref count for us. - */ g_object_get(G_OBJECT(object), - g_param_spec_get_name(pspec), &value, NULL); - } - - return NULL; -} + g_param_spec_get_name(pspec), &image, NULL); -static void -vips_operation_touch(VipsOperation *operation) -{ - VipsOperationCacheEntry *entry = vips_cache_operation_get(operation); + (void) vips__link_map(image, TRUE, + (VipsSListMap2Fn) vips_image_touch_cb, NULL, NULL); - vips_cache_time += 1; + VIPS_UNREF(image); + } - /* Don't up the time for invalid items -- we want them to fall out of - * cache. - */ - if (!entry->invalid) - entry->time = vips_cache_time; + return NULL; } /* Ref an operation for the cache. The operation itself, plus all the output * objects it makes. */ static void -vips_cache_ref(VipsOperation *operation) +vips_entry_ref(VipsOperationCacheEntry *entry) { #ifdef DEBUG printf("vips_cache_ref: "); - vips_object_print_summary(VIPS_OBJECT(operation)); + vips_object_print_summary(VIPS_OBJECT(entry->operation)); #endif /*DEBUG*/ - g_object_ref(operation); - (void) vips_argument_map(VIPS_OBJECT(operation), - vips_object_ref_arg, NULL, NULL); - vips_operation_touch(operation); + g_object_ref(entry->operation); + (void) vips_argument_map(VIPS_OBJECT(entry->operation), + vips_object_ref_arg, entry, NULL); + + vips_cache_time += 1; + + /* Touch the cache entries on the upstream trees on all input images. + */ + (void) vips_argument_map(VIPS_OBJECT(entry->operation), + vips_object_touch_arg, NULL, NULL); + + /* And this entry. + */ + vips_entry_touch(entry); } static void @@ -638,7 +725,7 @@ vips_cache_insert(VipsOperation *operation) entry->invalid = FALSE; g_hash_table_insert(vips_cache_table, operation, entry); - vips_cache_ref(operation); + vips_entry_ref(entry); /* If the operation signals "invalidate", we must tag this cache entry * for removal. @@ -647,32 +734,11 @@ vips_cache_insert(VipsOperation *operation) G_CALLBACK(vips_cache_invalidate_cb), entry); } -static void * -vips_cache_get_first_fn(void *value, void *a, void *b) -{ - return value; -} - -/* Return the first item. - */ -static VipsOperation * -vips_cache_get_first(void) -{ - VipsOperationCacheEntry *entry; - - if (vips_cache_table && - (entry = vips_hash_table_map(vips_cache_table, - vips_cache_get_first_fn, NULL, NULL))) - return VIPS_OPERATION(entry->operation); - - return NULL; -} - /** * vips_cache_drop_all: * * Drop the whole operation cache, handy for leak tracking. Also called - * automatically on vips_shutdown(). + * automatically on [func@shutdown]. */ void vips_cache_drop_all(void) @@ -681,25 +747,17 @@ vips_cache_drop_all(void) printf("vips_cache_drop_all:\n"); #endif /*VIPS_DEBUG*/ - g_mutex_lock(vips_cache_lock); + g_mutex_lock(&vips_cache_lock); if (vips_cache_table) { - VipsOperation *operation; - if (vips__cache_dump) vips_cache_print_nolock(); - /* We can't modify the hash in the callback from - * g_hash_table_foreach() and friends. Repeatedly drop the - * first item instead. - */ - while ((operation = vips_cache_get_first())) - vips_cache_remove(operation); - + g_hash_table_remove_all(vips_cache_table); VIPS_FREEF(g_hash_table_unref, vips_cache_table); } - g_mutex_unlock(vips_cache_lock); + g_mutex_unlock(&vips_cache_lock); } static void @@ -737,7 +795,7 @@ vips_cache_trim(void) { VipsOperation *operation; - g_mutex_lock(vips_cache_lock); + g_mutex_lock(&vips_cache_lock); while (vips_cache_table && (g_hash_table_size(vips_cache_table) > vips_cache_max || @@ -752,7 +810,7 @@ vips_cache_trim(void) vips_cache_remove(operation); } - g_mutex_unlock(vips_cache_lock); + g_mutex_unlock(&vips_cache_lock); } /** @@ -764,15 +822,16 @@ vips_cache_trim(void) * * If we miss, build and add @operation. * - * Operators that have been tagged as invalid by the `invalidate` signal are + * Operators that have been tagged as invalid by [signal@Image::invalidate] are * removed from cache. * - * Operators with the #VIPS_OPERATION_BLOCKED flag are never executed. + * Operators with the [flags@Vips.OperationFlags.BLOCKED] flag are never + * executed. * - * Operators with the #VIPS_OPERATION_REVALIDATE flag are always executed and - * any old cache value is replaced. + * Operators with the [flags@Vips.OperationFlags.REVALIDATE] flag are always + * executed and any old cache value is replaced. * - * Operators with the #VIPS_OPERATION_NOCACHE flag are never cached. + * Operators with the [flags@Vips.OperationFlags.NOCACHE] flag are never cached. * * Returns: 0 on success, or -1 on error. */ @@ -794,7 +853,7 @@ vips_cache_operation_buildp(VipsOperation **operation) vips_object_print_dump(VIPS_OBJECT(*operation)); #endif /*VIPS_DEBUG*/ - g_mutex_lock(vips_cache_lock); + g_mutex_lock(&vips_cache_lock); hit = vips_cache_operation_get(*operation); @@ -815,7 +874,7 @@ vips_cache_operation_buildp(VipsOperation **operation) * passed. */ if (hit) { - vips_cache_ref(hit->operation); + vips_entry_ref(hit); g_object_unref(*operation); *operation = hit->operation; @@ -825,21 +884,58 @@ vips_cache_operation_buildp(VipsOperation **operation) } } - g_mutex_unlock(vips_cache_lock); + g_mutex_unlock(&vips_cache_lock); /* If there was a miss, we need to build this operation and add - * it to the cache if appropriate. + * it to the cache, if appropriate. */ if (!hit) { + unsigned int hash_before = 0; + VipsOperation *operation_before = NULL; + + /* The _build method must not change the object hash. If it does, the + * finished operation won't detect hits with next identical call. + */ + if (vips__leak) { + hash_before = vips_operation_hash(*operation); + operation_before = vips_operation_copy(*operation); + } + if (vips_object_build(VIPS_OBJECT(*operation))) return -1; + if (vips__leak && + !(flags & VIPS_OPERATION_NOCACHE) && + hash_before != vips_operation_hash(*operation)) { + const char *name = (const char *) + vips_argument_map(VIPS_OBJECT(*operation), + vips_object_equal_arg, operation_before, NULL); + VipsObject *object = VIPS_OBJECT(*operation); + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); + + char txt[256]; + VipsBuf buf = VIPS_BUF_STATIC(txt); + + VIPS_UNREF(operation_before); + + vips_object_summary_class(class, &buf); + vips_buf_appends(&buf, ", "); + vips_object_summary(object, &buf); + vips_buf_appends(&buf, ", "); + vips_error(class->nickname, "arg \"%s\" changed during build, %s", + name, vips_buf_all(&buf)); + + return -1; + } + + VIPS_UNREF(operation_before); + /* Retrieve the flags again, as vips_foreign_load_build() may * set load->nocache. */ flags = vips_operation_get_flags(*operation); - g_mutex_lock(vips_cache_lock); + g_mutex_lock(&vips_cache_lock); /* If two threads build the same operation at the same time, * we can get multiple adds. Let the first one win. See @@ -853,15 +949,14 @@ vips_cache_operation_buildp(VipsOperation **operation) printf("vips cache : "); else printf("vips cache+: "); - vips_object_print_summary( - VIPS_OBJECT(*operation)); + vips_object_print_summary(VIPS_OBJECT(*operation)); } if (!(flags & VIPS_OPERATION_NOCACHE)) vips_cache_insert(*operation); } - g_mutex_unlock(vips_cache_lock); + g_mutex_unlock(&vips_cache_lock); } vips_cache_trim(); @@ -873,11 +968,11 @@ vips_cache_operation_buildp(VipsOperation **operation) * vips_cache_operation_build: * @operation: (transfer none): operation to lookup * - * A binding-friendly version of vips_cache_operation_buildp(). + * A binding-friendly version of [func@cache_operation_buildp]. * * After calling this, @operation has the same ref count as when it went in, - * and the result must be freed with vips_object_unref_outputs() and - * g_object_unref(). + * and the result must be freed with [method@Object.unref_outputs] and + * [method@GObject.Object.unref]. * * Returns: (transfer full): The built operation. */ @@ -917,13 +1012,14 @@ vips_cache_set_max(int max) * @max_mem: maximum amount of tracked memory we use * * Set the maximum amount of tracked memory we allow before we start dropping - * cached operations. See vips_tracked_get_mem(). + * cached operations. See [func@tracked_get_mem]. * * libvips only tracks memory it allocates, it can't track memory allocated by - * external libraries. If you use an operation like vips_magickload(), most of - * the memory it uses won't be included. + * external libraries. If you use an operation like [ctor@Image.magickload], + * most of the memory it uses won't be included. * - * See also: vips_tracked_get_mem(). + * ::: seealso + * [func@tracked_get_mem]. */ void vips_cache_set_max_mem(size_t max_mem) @@ -957,13 +1053,13 @@ vips_cache_get_size(void) { guint size; - g_mutex_lock(vips_cache_lock); + g_mutex_lock(&vips_cache_lock); size = 0; if (vips_cache_table) size = g_hash_table_size(vips_cache_table); - g_mutex_unlock(vips_cache_lock); + g_mutex_unlock(&vips_cache_lock); return size; } @@ -972,9 +1068,10 @@ vips_cache_get_size(void) * vips_cache_get_max_mem: * * Get the maximum amount of tracked memory we allow before we start dropping - * cached operations. See vips_tracked_get_mem(). + * cached operations. See [func@tracked_get_mem]. * - * See also: vips_tracked_get_mem(). + * ::: seealso + * [func@tracked_get_mem]. * * Returns: the maximum amount of tracked memory we allow */ @@ -988,13 +1085,14 @@ vips_cache_get_max_mem(void) * vips_cache_get_max_files: * * Get the maximum number of tracked files we allow before we start dropping - * cached operations. See vips_tracked_get_files(). + * cached operations. See [func@tracked_get_files]. * * libvips only tracks file descriptors it allocates, it can't track ones * allocated by external libraries. If you use an operation like - * vips_magickload(), most of the descriptors it uses won't be included. + * [ctor@Image.magickload], most of the descriptors it uses won't be included. * - * See also: vips_tracked_get_files(). + * ::: seealso + * [func@tracked_get_files]. * * Returns: the maximum number of tracked files we allow */ @@ -1009,9 +1107,10 @@ vips_cache_get_max_files(void) * @max_files: max open files we allow * * Set the maximum number of tracked files we allow before we start dropping - * cached operations. See vips_tracked_get_files(). + * cached operations. See [func@tracked_get_files]. * - * See also: vips_tracked_get_files(). + * ::: seealso + * [func@tracked_get_files]. */ void vips_cache_set_max_files(int max_files) @@ -1022,11 +1121,12 @@ vips_cache_set_max_files(int max_files) /** * vips_cache_set_dump: - * @dump: if %TRUE, dump the operation cache on exit + * @dump: if `TRUE`, dump the operation cache on exit * * Handy for debugging. Print the operation cache to stdout just before exit. * - * See also: vips_cache_set_trace(). + * ::: seealso + * [func@cache_set_trace]. */ void vips_cache_set_dump(gboolean dump) @@ -1036,14 +1136,15 @@ vips_cache_set_dump(gboolean dump) /** * vips_cache_set_trace: - * @trace: if %TRUE, trace the operation cache + * @trace: if `TRUE`, trace the operation cache * * Handy for debugging. Print operation cache actions to stdout as we run. * * You can set the environment variable `VIPS_TRACE` to turn this option on, or * use the command-line flag `--vips-cache-trace`. * - * See also: vips_cache_set_dump(). + * ::: seealso + * [func@cache_set_dump]. */ void vips_cache_set_trace(gboolean trace) diff --git a/libvips/iofuncs/connection.c b/libvips/iofuncs/connection.c index e0a5f75381..2c3e43c1d3 100644 --- a/libvips/iofuncs/connection.c +++ b/libvips/iofuncs/connection.c @@ -56,29 +56,21 @@ #include /** - * SECTION: connection - * @short_description: a source/sink of bytes, perhaps a network socket - * @stability: Stable - * @see_also: foreign - * @include: vips/vips.h - * @title: VipsConnection + * VipsConnection: * - * A #VipsConnection is a source or sink of bytes for something like jpeg - * loading, see for example vips_jpegload_source(). + * An abstract base class representing a source or sink of bytes. * * It can be connected to a network socket, for example, or perhaps - * a node.js stream, or to an area of memory. + * a Node.js stream, or to an area of memory. This allows it to support + * operations like JPEG loading, see for example [ctor@Image.jpegload_source]. * - * Subclass to add other input sources. Use #VipsSourceCustom and - * #VipsTargetCustom to make a source or target with action signals for - * ::read, ::write and ::seek. - */ - -/** - * VipsConnection: + * Subclass to add other input sources. Use [class@SourceCustom] and + * [class@TargetCustom] to make a source or target with action signals. + * These classes provide action signals such as: * - * A #VipsConnection is a source or sink of bytes for something like jpeg - * loading. It can be connected to a network socket, for example. + * - [signal@SourceCustom::read] for reading data from a custom source. + * - [signal@SourceCustom::seek] for seeking within a data stream. + * - [signal@TargetCustom::write] for writing data to a custom target. */ G_DEFINE_ABSTRACT_TYPE(VipsConnection, vips_connection, VIPS_TYPE_OBJECT); diff --git a/libvips/iofuncs/dbuf.c b/libvips/iofuncs/dbuf.c index 672061b4ab..bc87b500e3 100644 --- a/libvips/iofuncs/dbuf.c +++ b/libvips/iofuncs/dbuf.c @@ -48,7 +48,7 @@ * Initialize @dbuf. You can also just init to zero, eg. * `VipsDbuf buf = {0};`. * - * Destroy with vips_dbuf_destroy(). + * Destroy with [method@Dbuf.destroy]. */ void vips_dbuf_init(VipsDbuf *dbuf) @@ -66,7 +66,7 @@ vips_dbuf_init(VipsDbuf *dbuf) * * Make sure @dbuf is at least @size bytes. * - * Returns: %FALSE on out of memory, %TRUE otherwise. + * Returns: `FALSE` on out of memory, `TRUE` otherwise. */ gboolean vips_dbuf_minimum_size(VipsDbuf *dbuf, size_t size) @@ -96,7 +96,7 @@ vips_dbuf_minimum_size(VipsDbuf *dbuf, size_t size) * * Make sure @dbuf has at least @size bytes available after the write point. * - * Returns: %FALSE on out of memory, %TRUE otherwise. + * Returns: `FALSE` on out of memory, `TRUE` otherwise. */ gboolean vips_dbuf_allocate(VipsDbuf *dbuf, size_t size) @@ -133,11 +133,11 @@ vips_dbuf_read(VipsDbuf *dbuf, unsigned char *data, size_t size) * @size: (allow-none): optionally return length in bytes here * * Return a pointer to an area you can write to, return length of area in - * @size. Use vips_dbuf_allocate() before this call to set a minimum amount of + * @size. Use [method@Dbuf.allocate] before this call to set a minimum amount of * space to have available. * * The write point moves to just beyond the returned block. Use - * vips_dbuf_seek() to move it back again. + * [method@Dbuf.seek] to move it back again. * * Returns: (transfer none): start of write area. */ @@ -165,7 +165,7 @@ vips_dbuf_get_write(VipsDbuf *dbuf, size_t *size) * * Append @size bytes from @data. @dbuf expands if necessary. * - * Returns: %FALSE on out of memory, %TRUE otherwise. + * Returns: `FALSE` on out of memory, `TRUE` otherwise. */ gboolean vips_dbuf_write(VipsDbuf *dbuf, const unsigned char *data, size_t size) @@ -183,12 +183,12 @@ vips_dbuf_write(VipsDbuf *dbuf, const unsigned char *data, size_t size) /** * vips_dbuf_writef: * @dbuf: the buffer - * @fmt: printf()-style format string + * @fmt: `printf()`-style format string * @...: arguments to format string * * Format the string and write to @dbuf. * - * Returns: %FALSE on out of memory, %TRUE otherwise. + * Returns: `FALSE` on out of memory, `TRUE` otherwise. */ gboolean vips_dbuf_writef(VipsDbuf *dbuf, const char *fmt, ...) @@ -222,7 +222,7 @@ vips_dbuf_writef(VipsDbuf *dbuf, const char *fmt, ...) * - Don't escape \n, \t, \r * - Do escape the other ASCII codes. * - * Returns: %FALSE on out of memory, %TRUE otherwise. + * Returns: `FALSE` on out of memory, `TRUE` otherwise. */ gboolean vips_dbuf_write_amp(VipsDbuf *dbuf, const char *str) @@ -301,7 +301,7 @@ vips_dbuf_destroy(VipsDbuf *dbuf) * @offset: how to move the write point * @whence: from start, from end, from current * - * Move the write point. @whence can be %SEEK_SET, %SEEK_CUR, %SEEK_END, with + * Move the write point. @whence can be `SEEK_SET`, `SEEK_CUR`, `SEEK_END`, with * the usual meaning. */ gboolean @@ -380,7 +380,7 @@ vips_dbuf_tell(VipsDbuf *dbuf) * * This makes it safe to treat the dbuf contents as a C string. * - * Returns: %FALSE on out of memory, %TRUE otherwise. + * Returns: `FALSE` on out of memory, `TRUE` otherwise. */ static gboolean vips_dbuf_null_terminate(VipsDbuf *dbuf) @@ -399,7 +399,7 @@ vips_dbuf_null_terminate(VipsDbuf *dbuf) * @size: (allow-none): optionally return length in bytes here * * Destroy a buffer, but rather than freeing memory, a pointer is returned. - * This must be freed with g_free(). + * This must be freed with [func@GLib.free]. * * A `\0` is appended, but not included in the character count. This is so the * pointer can be safely treated as a C string. diff --git a/libvips/iofuncs/error.c b/libvips/iofuncs/error.c index 586f4ac625..e6bb0dd0fb 100644 --- a/libvips/iofuncs/error.c +++ b/libvips/iofuncs/error.c @@ -1,4 +1,4 @@ -/* error.c --- error message handling +/* error.c -- error message handling * * Copyright: N. Dessipris * Written on: 18/03/1991 @@ -62,7 +62,6 @@ #include #include #include -#include #include #ifdef G_OS_WIN32 @@ -70,64 +69,6 @@ #include #endif /*G_OS_WIN32*/ -/** - * SECTION: errors - * @short_description: error messages and error handling - * @stability: Stable - * @include: vips/vips.h - * - * VIPS maintains an error buffer (a log of localised text messages), - * a set of functions - * for adding messages, and a way to access and clear the buffer. - * - * The error buffer is global, that is, it is shared between all threads. You - * can add to the buffer from any thread (there is a lock to prevent - * corruption), but it's sensible to only read and clear the buffer from the - * main thread of execution. - * - * The general principle is: if you detect an error, log a message for the - * user. If a function you call detects an error, just propagate it and don't - * add another message. - * - * |[ - * VipsImage *im; - * - * if (!(im = vips_image_new_from_file(filename, NULL))) - * // vips_image_new_from_file() will set a message, we don't need to - * return -1; - * - * if (vips_image_get_width(im) < 100) { - * // we have detected an error, we must set a message - * vips_error("myprogram", "%s", _("width too small")); - * return -1; - * } - * ]| - * - * The domain argument most of these functions take is not localised and is - * supposed to indicate the component which failed. - * - * libvips uses g_warning() and g_info() to send warning and information - * messages to the user. You can use the usual glib mechanisms to display or - * divert these messages. For example, info messages are hidden by default, but - * you can see them with: - * - * |[ - * $ G_MESSAGES_DEBUG=VIPS vipsthumbnail k2.jpg - * VIPS-INFO: thumbnailing k2.jpg - * VIPS-INFO: selected loader is VipsForeignLoadJpegFile - * VIPS-INFO: input size is 1450 x 2048 - * VIPS-INFO: loading jpeg with factor 8 pre-shrink - * VIPS-INFO: converting to processing space srgb - * VIPS-INFO: residual reducev by 0.5 - * VIPS-INFO: 13 point mask - * VIPS-INFO: using vector path - * VIPS-INFO: residual reduceh by 0.5 - * VIPS-INFO: 13 point mask - * VIPS-INFO: thumbnailing k2.jpg as ./tn_k2.jpg - * ]| - * - */ - /* Make global array to keep the error message buffer. */ #define VIPS_MAX_ERROR (10240) @@ -138,16 +79,16 @@ static int vips_error_freeze_count = 0; /** * vips_error_freeze: * - * Stop errors being logged. Use vips_error_thaw() to unfreeze. You can + * Stop errors being logged. Use [func@error_thaw] to unfreeze. You can * nest freeze/thaw pairs. */ void vips_error_freeze(void) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); g_assert(vips_error_freeze_count >= 0); vips_error_freeze_count += 1; - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } /** @@ -158,10 +99,10 @@ vips_error_freeze(void) void vips_error_thaw(void) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips_error_freeze_count -= 1; g_assert(vips_error_freeze_count >= 0); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } /** @@ -170,7 +111,8 @@ vips_error_thaw(void) * Get a pointer to the start of the error buffer as a C string. * The string is owned by the error system and must not be freed. * - * See also: vips_error_clear(). + * ::: seealso + * [func@error_clear]. * * Returns: the error buffer as a C string which must not be freed */ @@ -179,9 +121,9 @@ vips_error_buffer(void) { const char *msg; - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); msg = vips_buf_all(&vips_error_buf); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); return msg; } @@ -198,10 +140,10 @@ vips_error_buffer_copy(void) { char *msg; - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); msg = g_strdup(vips_buf_all(&vips_error_buf)); vips_buf_rewind(&vips_error_buf); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); return msg; } @@ -218,12 +160,13 @@ vips_error_buffer_copy(void) /** * vips_verror: * @domain: the source of the error - * @fmt: printf()-style format string for the error + * @fmt: `printf()`-style format string for the error * @ap: arguments to the format string * * Append a message to the error buffer. * - * See also: vips_error(). + * ::: seealso + * [func@error]. */ void vips_verror(const char *domain, const char *fmt, va_list ap) @@ -242,7 +185,7 @@ vips_verror(const char *domain, const char *fmt, va_list ap) } #endif /*VIPS_DEBUG*/ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); g_assert(vips_error_freeze_count >= 0); if (!vips_error_freeze_count) { if (domain) @@ -250,7 +193,7 @@ vips_verror(const char *domain, const char *fmt, va_list ap) vips_buf_vappendf(&vips_error_buf, fmt, ap); vips_buf_appends(&vips_error_buf, "\n"); } - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); if (vips__fatal) vips_error_exit("vips__fatal"); @@ -259,12 +202,13 @@ vips_verror(const char *domain, const char *fmt, va_list ap) /** * vips_error: * @domain: the source of the error - * @fmt: printf()-style format string for the error + * @fmt: `printf()`-style format string for the error * @...: arguments to the format string * - * Format the string in the style of printf() and append to the error buffer. + * Format the string in the style of [`printf()`](man:printf(3)) and append to the error buffer. * - * See also: vips_error_system(), vips_verror(). + * ::: seealso + * [func@error_system], [func@verror]. */ void vips_error(const char *domain, const char *fmt, ...) @@ -280,14 +224,15 @@ vips_error(const char *domain, const char *fmt, ...) * vips_verror_system: * @err: the system error code * @domain: the source of the error - * @fmt: printf()-style format string for the error + * @fmt: `printf()`-style format string for the error * @ap: arguments to the format string * - * Format the string in the style of printf() and append to the error buffer. + * Format the string in the style of [`printf()`](man:printf(3)) and append to the error buffer. * Then create and append a localised message based on the system error code, * usually the value of errno. * - * See also: vips_error_system(). + * ::: seealso + * [func@error_system]. */ void vips_verror_system(int err, const char *domain, const char *fmt, va_list ap) @@ -300,14 +245,15 @@ vips_verror_system(int err, const char *domain, const char *fmt, va_list ap) * vips_error_system: * @err: the system error code * @domain: the source of the error - * @fmt: printf()-style format string for the error + * @fmt: `printf()`-style format string for the error * @...: arguments to the format string * - * Format the string in the style of printf() and append to the error buffer. + * Format the string in the style of [`printf()`](man:printf(3)) and append to the error buffer. * Then create and append a localised message based on the system error code, * usually the value of errno. * - * See also: vips_verror_system(). + * ::: seealso + * [func@verror_system]. */ void vips_error_system(int err, const char *domain, const char *fmt, ...) @@ -326,9 +272,10 @@ vips_error_system(int err, const char *domain, const char *fmt, ...) * This function sets the glib error pointer from the vips error buffer and * clears it. It's handy for returning errors to glib functions from vips. * - * See vips_g_error() for the inverse operation. + * See [func@g_error] for the inverse operation. * - * See also: g_set_error(), vips_g_error(). + * ::: seealso + * [func@GLib.set_error], [func@g_error]. */ void vips_error_g(GError **error) @@ -340,9 +287,9 @@ vips_error_g(GError **error) /* glib does not expect a trailing '\n' and vips always has one. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips_buf_removec(&vips_error_buf, '\n'); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); g_set_error(error, vips_domain, -1, "%s", vips_error_buffer()); vips_error_clear(); @@ -352,10 +299,11 @@ vips_error_g(GError **error) * vips_g_error: * @error: glib error pointer * - * This function adds the %GError to the vips error buffer and clears it. It's - * the opposite of vips_error_g(). + * This function adds the [struct@GLib.Error] to the vips error buffer and clears it. It's + * the opposite of [func@error_g]. * - * See also: vips_error_g(). + * ::: seealso + * [func@error_g]. */ void vips_g_error(GError **error) @@ -374,29 +322,31 @@ vips_g_error(GError **error) * Clear and reset the error buffer. This is typically called after presenting * an error to the user. * - * See also: vips_error_buffer(). + * ::: seealso + * [func@error_buffer]. */ void vips_error_clear(void) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips_buf_rewind(&vips_error_buf); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } /** * vips_error_exit: - * @fmt: printf()-style format string for the message + * @fmt: `printf()`-style format string for the message * @...: arguments to the format string * * Sends a formatted error message to stderr, then sends the contents of the * error buffer, if any, then shuts down vips and terminates the program with * an error code. * - * @fmt may be %NULL, in which case only the error buffer is printed before + * @fmt may be `NULL`, in which case only the error buffer is printed before * exiting. * - * See also: vips_error(). + * ::: seealso + * [func@error]. */ void vips_error_exit(const char *fmt, ...) @@ -432,7 +382,8 @@ vips_error_exit(const char *fmt, ...) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 on OK, or -1 on error. */ @@ -456,7 +407,8 @@ vips_check_uncoded(const char *domain, VipsImage *im) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 on OK, or -1 on error. */ @@ -484,7 +436,8 @@ vips_check_coding_noneorlabq(const char *domain, VipsImage *im) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 on OK, or -1 on error. */ @@ -513,7 +466,8 @@ vips_check_coding_known(const char *domain, VipsImage *im) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 on OK, or -1 on error. */ @@ -538,7 +492,8 @@ vips_check_coding(const char *domain, VipsImage *im, VipsCoding coding) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -563,7 +518,8 @@ vips_check_mono(const char *domain, VipsImage *im) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -587,7 +543,8 @@ vips_check_bands(const char *domain, VipsImage *im, int bands) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -613,7 +570,8 @@ vips_check_bands_1or3(const char *domain, VipsImage *im) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -640,7 +598,8 @@ vips_check_bands_atleast(const char *domain, VipsImage *im, int bands) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 on OK, or -1 on error. */ @@ -665,11 +624,12 @@ vips_check_bands_1orn(const char *domain, VipsImage *im1, VipsImage *im2) * @n: number of bands, or 1 * * Check that an image has 1 or @n bands. Handy for unary operations, cf. - * vips_check_bands_1orn(). + * [func@check_bands_1orn]. * If not, set an error message * and return non-zero. * - * See also: vips_check_bands_1orn(). + * ::: seealso + * [func@check_bands_1orn]. * * Returns: 0 on OK, or -1 on error. */ @@ -693,7 +653,8 @@ vips_check_bands_1orn_unary(const char *domain, VipsImage *im, int n) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -717,7 +678,8 @@ vips_check_noncomplex(const char *domain, VipsImage *im) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -742,7 +704,8 @@ vips_check_complex(const char *domain, VipsImage *im) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -769,7 +732,8 @@ vips_check_twocomponents(const char *domain, VipsImage *im) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -795,7 +759,8 @@ vips_check_format(const char *domain, VipsImage *im, VipsBandFormat fmt) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -819,7 +784,8 @@ vips_check_int(const char *domain, VipsImage *im) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -844,7 +810,8 @@ vips_check_uint(const char *domain, VipsImage *im) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -872,7 +839,8 @@ vips_check_8or16(const char *domain, VipsImage *im) * Otherwise set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -897,7 +865,8 @@ vips_check_u8or16(const char *domain, VipsImage *im) * Check that the image is 8 or 16-bit unsigned integer, or float. * Otherwise set an error message and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -923,7 +892,8 @@ vips_check_u8or16orf(const char *domain, VipsImage *im) * Check that the image is unsigned int or float. * Otherwise set an error message and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -952,7 +922,8 @@ vips_check_uintorf(const char *domain, VipsImage *im) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -977,7 +948,8 @@ vips_check_size_same(const char *domain, VipsImage *im1, VipsImage *im2) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1004,7 +976,8 @@ vips_check_oddsquare(const char *domain, VipsImage *im) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1031,7 +1004,8 @@ vips_check_bands_same(const char *domain, VipsImage *im1, VipsImage *im2) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1058,7 +1032,8 @@ vips_check_bandno(const char *domain, VipsImage *im, int bandno) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1084,7 +1059,8 @@ vips_check_format_same(const char *domain, VipsImage *im1, VipsImage *im2) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1108,7 +1084,8 @@ vips_check_coding_same(const char *domain, VipsImage *im1, VipsImage *im2) * * Check that @n == @len. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1133,7 +1110,8 @@ vips_check_vector_length(const char *domain, int n, int len) * the same number of elements as there are bands in the image, or a 1-band * image and a many-element vector. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1170,7 +1148,8 @@ vips_check_vector(const char *domain, int n, VipsImage *im) * 65536 elements. Return 0 if the image will pass as a histogram, or -1 and * set an error message otherwise. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1204,11 +1183,12 @@ vips_check_hist(const char *domain, VipsImage *im) * message otherwise. * * @out is set to be @im cast to double and stored in memory. Use - * VIPS_MATRIX() to address values in @out. + * [func@MATRIX] to address values in @out. * * You must unref @out when you are done with it. * - * See also: VIPS_MATRIX(), vips_object_local() + * ::: seealso + * [func@MATRIX]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1250,7 +1230,8 @@ vips_check_matrix(const char *domain, VipsImage *im, VipsImage **out) * Return 0 if the image will pass, or -1 and * set an error message otherwise. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 if OK, -1 otherwise. */ @@ -1276,7 +1257,8 @@ vips_check_separable(const char *domain, VipsImage *im) * If not, set an error message * and return non-zero. * - * See also: vips_error(). + * ::: seealso + * [func@error]. * * Returns: 0 on OK, or -1 on error. */ diff --git a/libvips/iofuncs/gate.c b/libvips/iofuncs/gate.c index ea9f914b90..7282ffd23c 100644 --- a/libvips/iofuncs/gate.c +++ b/libvips/iofuncs/gate.c @@ -1,4 +1,4 @@ -/* gate.c --- thread profiling +/* gate.c -- thread profiling * * Written on: 18 nov 13 */ @@ -70,8 +70,6 @@ typedef struct _VipsThreadGate { */ typedef struct _VipsThreadProfile { - /*< private >*/ - const char *name; GThread *thread; GHashTable *gates; @@ -88,7 +86,7 @@ static FILE *vips__thread_fp = NULL; /** * vips_profile_set: - * @profile: %TRUE to enable profile recording + * @profile: `TRUE` to enable profile recording * * If set, vips will record profiling information, and dump it on program * exit. These profiles can be analysed with the `vipsprofile` program. @@ -136,7 +134,7 @@ vips_thread_profile_save_cb(gpointer key, gpointer value, gpointer data) static void vips_thread_profile_save(VipsThreadProfile *profile) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); VIPS_DEBUG_MSG("vips_thread_profile_save: %s\n", profile->name); @@ -144,7 +142,7 @@ vips_thread_profile_save(VipsThreadProfile *profile) vips__thread_fp = vips__file_open_write("vips-profile.txt", TRUE); if (!vips__thread_fp) { - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); g_warning("unable to create profile log"); return; } @@ -157,7 +155,7 @@ vips_thread_profile_save(VipsThreadProfile *profile) vips_thread_profile_save_cb, vips__thread_fp); vips_thread_profile_save_gate(profile->memory, vips__thread_fp); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } static void @@ -207,7 +205,7 @@ thread_profile_destroy_notify(gpointer data) * been called. */ if (vips__thread_profile) - g_warning("discarding unsaved state for thread %p --- " + g_warning("discarding unsaved state for thread %p -- " "call vips_thread_shutdown() for this thread", profile->thread); @@ -252,7 +250,7 @@ vips_thread_profile_get(void) /* This usually happens automatically when a thread shuts down, but that will * not happen for the main thread. * - * Shut down any stats on the main thread with this, see vips_shutdown() + * Shut down any stats on the main thread with this, see vips_shutdown(). */ void vips__thread_profile_detach(void) diff --git a/libvips/iofuncs/generate.c b/libvips/iofuncs/generate.c index 8941762f75..f860d37992 100644 --- a/libvips/iofuncs/generate.c +++ b/libvips/iofuncs/generate.c @@ -108,21 +108,8 @@ #include #include -#include #include -/** - * SECTION: generate - * @short_description: calculate pixels and pixel buffers - * @stability: Stable - * @see_also: VipsImage, - * VipsRegion - * @include: vips/vips.h - * - * These functions let you attach generate functions to images - * and ask for regions of images to be calculated. - */ - /* Max number of images we can handle. */ #define MAX_IMAGES (1000) @@ -181,7 +168,7 @@ vips__link_break_rev(VipsImage *image_down, VipsImage *image_up, void *b) void vips__link_break_all(VipsImage *image) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips_slist_map2(image->upstream, (VipsSListMap2Fn) vips__link_break, image, NULL); @@ -191,7 +178,7 @@ vips__link_break_all(VipsImage *image) g_assert(!image->upstream); g_assert(!image->downstream); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } typedef struct _LinkMap { @@ -261,7 +248,7 @@ vips__link_map(VipsImage *image, gboolean upstream, * member. There will be intense confusion if two threads try to do * this at the same time. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); serial += 1; map.serial = serial; @@ -271,7 +258,7 @@ vips__link_map(VipsImage *image, gboolean upstream, for (p = images; p; p = p->next) g_object_ref(p->data); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); result = vips_slist_map2(images, fn, a, b); @@ -330,10 +317,10 @@ vips__demand_hint_array(VipsImage *image, /* im depends on all these ims. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); for (i = 0; i < len; i++) vips__link_make(in[i], image); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); /* Set a flag on the image to say we remembered to call this thing. * vips_image_generate() and friends check this. @@ -345,7 +332,7 @@ vips__demand_hint_array(VipsImage *image, * vips_image_pipeline_array: * @image: (out): output image * @hint: demand hint for @image - * @in: (array zero-terminated=1): %NULL-terminated array of input images + * @in: (array zero-terminated=1): `NULL`-terminated array of input images * * Add an image to a pipeline. @image depends on all of the images in @in, * @image prefers to supply pixels according to @hint. @@ -353,8 +340,8 @@ vips__demand_hint_array(VipsImage *image, * Operations can set demand hints, that is, hints to the VIPS IO system about * the type of region geometry they work best with. For example, * operations which transform coordinates will usually work best with - * %VIPS_DEMAND_STYLE_SMALLTILE, operations which work on local windows of - * pixels will like %VIPS_DEMAND_STYLE_FATSTRIP. + * [enum@Vips.DemandStyle.SMALLTILE], operations which work on local windows of + * pixels will like [enum@Vips.DemandStyle.FATSTRIP]. * * Header fields in @image are set from the fields in @in, with lower-numbered * images in @in taking priority. @@ -369,7 +356,8 @@ vips__demand_hint_array(VipsImage *image, * VIPS uses the list of input images to build the tree of operations it needs * for the cache invalidation system. * - * See also: vips_image_pipelinev(), vips_image_generate(). + * ::: seealso + * [method@Image.pipelinev], [method@Image.generate]. * * Returns: 0 on success, -1 on error. */ @@ -401,11 +389,12 @@ vips_image_pipeline_array(VipsImage *image, * vips_image_pipelinev: * @image: output image of pipeline * @hint: hint for this image - * @...: %NULL-terminated list of input images + * @...: `NULL`-terminated list of input images * - * Build an array and call vips_image_pipeline_array(). + * Build an array and call [func@Image.pipeline_array]. * - * See also: vips_image_generate(). + * ::: seealso + * [method@Image.generate]. */ int vips_image_pipelinev(VipsImage *image, VipsDemandStyle hint, ...) @@ -421,7 +410,7 @@ vips_image_pipelinev(VipsImage *image, VipsDemandStyle hint, ...) ; va_end(ap); if (i == MAX_IMAGES) { - g_warning("%s", _("too many images")); + g_warning("too many images"); /* Make sure we have a sentinel there. */ @@ -439,7 +428,8 @@ vips_image_pipelinev(VipsImage *image, VipsDemandStyle hint, ...) * * Start function for one image in. Input image is @a. * - * See also: vips_image_generate(). + * ::: seealso + * [method@Image.generate]. */ void * vips_start_one(VipsImage *out, void *a, void *b) @@ -457,7 +447,8 @@ vips_start_one(VipsImage *out, void *a, void *b) * * Stop function for one image in. Input image is @a. * - * See also: vips_image_generate(). + * ::: seealso + * [method@Image.generate]. */ int vips_stop_one(void *seq, void *a, void *b) @@ -476,9 +467,10 @@ vips_stop_one(void *seq, void *a, void *b) * @b: user data * * Stop function for many images in. @a is a pointer to - * a %NULL-terminated array of input images. + * a `NULL`-terminated array of input images. * - * See also: vips_image_generate(). + * ::: seealso + * [method@Image.generate]. */ int vips_stop_many(void *seq, void *a, void *b) @@ -503,9 +495,10 @@ vips_stop_many(void *seq, void *a, void *b) * @b: user data * * Start function for many images in. @a is a pointer to - * a %NULL-terminated array of input images. + * a `NULL`-terminated array of input images. * - * See also: vips_image_generate(), vips_allocate_input_array() + * ::: seealso + * [method@Image.generate], [func@allocate_input_array] */ void * vips_start_many(VipsImage *out, void *a, void *b) @@ -540,14 +533,16 @@ vips_start_many(VipsImage *out, void *a, void *b) /** * vips_allocate_input_array: * @out: free array when this image closes - * @...: %NULL-terminated list of input images + * @...: `NULL`-terminated list of input images * - * Convenience function --- make a %NULL-terminated array of input images. - * Use with vips_start_many(). + * Convenience function -- make a `NULL`-terminated array of input images. + * Use with [func@start_many]. * - * See also: vips_image_generate(), vips_start_many(). + * ::: seealso + * [method@Image.generate], [func@start_many]. * - * Returns: %NULL-terminated array of images. Do not free the result. + * Returns: (transfer none) (nullable): `NULL`-terminated array of images. + * Do not free the result. */ VipsImage ** vips_allocate_input_array(VipsImage *out, ...) @@ -588,23 +583,25 @@ vips_allocate_input_array(VipsImage *out, ...) * Start a new processing sequence for this generate function. This allocates * per-thread state, such as an input region. * - * See also: vips_start_one(), vips_start_many(). + * ::: seealso + * [func@start_one], [func@start_many]. * * Returns: a new sequence value */ /** * VipsGenerateFn: - * @out: #VipsRegion to fill + * @out: [class@Region] to fill * @seq: sequence value * @a: user data * @b: user data * @stop: set this to stop processing * * Fill @out->valid with pixels. @seq contains per-thread state, such as the - * input regions. Set @stop to %TRUE to stop processing. + * input regions. Set @stop to `TRUE` to stop processing. * - * See also: vips_image_generate(), vips_stop_many(). + * ::: seealso + * [method@Image.generate], [func@stop_many]. * * Returns: 0 on success, -1 on error. */ @@ -618,7 +615,8 @@ vips_allocate_input_array(VipsImage *out, ...) * Stop a processing sequence. This frees * per-thread state, such as an input region. * - * See also: vips_stop_one(), vips_stop_many(). + * ::: seealso + * [func@stop_one], [func@stop_many]. * * Returns: 0 on success, -1 on error. */ @@ -656,26 +654,27 @@ write_vips(VipsRegion *region, VipsRect *area, void *a) /** * vips_image_generate: * @image: generate this image - * @start_fn: start sequences with this function - * @generate_fn: generate pixels with this function - * @stop_fn: stop sequences with this function + * @start_fn: (scope async): start sequences with this function + * @generate_fn: (scope async): generate pixels with this function + * @stop_fn: (scope async): stop sequences with this function * @a: user data * @b: user data * * Generates an image. The action depends on the image type. * - * For images created with vips_image_new(), vips_image_generate() just + * For images created with [ctor@Image.new], [method@Image.generate] just * attaches the start/generate/stop callbacks and returns. * - * For images created with vips_image_new_memory(), memory is allocated for - * the whole image and it is entirely generated using vips_sink_memory(). + * For images created with [ctor@Image.new_memory], memory is allocated for + * the whole image and it is entirely generated using [func@sink_memory]. * - * For images created with vips_image_new_temp_file() and friends, memory for + * For images created with [ctor@Image.new_temp_file] and friends, memory for * a few scanlines is allocated and - * vips_sink_disc() used to generate the image in small chunks. As each + * [method@Image.sink_disc] used to generate the image in small chunks. As each * chunk is generated, it is written to disc. * - * See also: vips_sink(), vips_image_new(), vips_region_prepare(). + * ::: seealso + * [func@sink_memory], [ctor@Image.new], [method@Region.prepare]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/iofuncs/ginputsource.c b/libvips/iofuncs/ginputsource.c index c6862d3a60..6ec91b120c 100644 --- a/libvips/iofuncs/ginputsource.c +++ b/libvips/iofuncs/ginputsource.c @@ -287,10 +287,14 @@ vips_g_input_stream_init(VipsGInputStream *gstream) * vips_g_input_stream_new_from_source: * @source: vips source to wrap * - * Create a new #GInputStream wrapping a #VipsSource. This is useful for - * loaders like SVG and PDF which support GInput methods. + * Create a new [class@Gio.InputStream] wrapping a [class@Source]. This is + * useful for loaders like SVG and PDF which support [class@Gio.InputStream] + * methods. * - * Returns: a new #GInputStream + * ::: seealso + * [func@Source.g_input_stream_new] + * + * Returns: (transfer full): a new [class@Gio.InputStream] */ GInputStream * vips_g_input_stream_new_from_source(VipsSource *source) diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index 8aca9821eb..6e090b5de5 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -86,57 +86,10 @@ #include #include -/** - * SECTION: header - * @short_description: get, set and walk image headers - * @stability: Stable - * @see_also: type - * @include: vips/vips.h - * - * These functions let you get at image header data (including metadata) in a - * uniform way. - * - * Use vips_image_get_typeof() to test for the - * existence and #GType of a header field. - * - * You can attach arbitrary metadata to images. Metadata is copied as images - * are processed, so all images which used this image as input, directly or - * indirectly, will have this same bit of metadata attached to them. Copying - * is implemented with reference-counted pointers, so it is efficient, even for - * large items of data. This does however mean that metadata items need to be - * immutable. Metadata is handy for things like ICC profiles or EXIF data. - * - * Various convenience functions (eg. vips_image_set_int()) let you easily - * attach - * simple types like - * numbers, strings and memory blocks to images. Use vips_image_map() to loop - * over an image's fields, including all metadata. - * - * Items of metadata are identified by strings. Some strings are reserved, for - * example the ICC profile for an image is known by convention as - * "icc-profile-data". - * - * If you save an image in VIPS format, all metadata (with a restriction, see - * below) is automatically saved for you in a block of XML at the end of the - * file. When you load a VIPS image, the metadata is restored. You can use the - * `vipsedit` command-line tool to extract or replace this block of XML. - * - * VIPS metadata is based on %GValue. See the docs for that system if you want - * to do fancy stuff such as defining a new metadata type. - * VIPS defines a new %GValue called `vips_save_string`, a variety of string, - * see vips_value_set_save_string(). - * If your %GValue can be transformed to `vips_save_string`, it will be - * saved and loaded to and from VIPS files for you. - * - * VIPS provides a couple of base classes which implement - * reference-counted areas of memory. If you base your metadata on one of - * these types, it can be copied between images efficiently. - */ - /* Use in various small places where we need a mutex and it's not worth * making a private one. */ -static GMutex *vips__meta_lock = NULL; +static GMutex vips__meta_lock; /* We have to keep the gtype as a string, since we statically init this. */ @@ -219,7 +172,7 @@ vips_format_sizeof(VipsBandFormat format) * vips_format_sizeof_unsafe: (skip) * @format: format type * - * A fast but dangerous version of vips_format_sizeof(). You must have + * A fast but dangerous version of [func@format_sizeof]. You must have * previously range-checked @format or you'll crash. * * Returns: number of bytes for a band format. @@ -480,12 +433,12 @@ vips_image_get_format_max(VipsBandFormat format) * vips_image_guess_format: * @image: image to guess for * - * Return the #VipsBandFormat for an image, guessing a sane value if + * Return the [enum@BandFormat] for an image, guessing a sane value if * the set value looks crazy. * * For example, for a float image tagged as rgb16, we'd return ushort. * - * Returns: a sensible #VipsBandFormat for the image. + * Returns: a sensible [enum@BandFormat] for the image. */ VipsBandFormat vips_image_guess_format(const VipsImage *image) @@ -497,12 +450,6 @@ vips_image_guess_format(const VipsImage *image) format = VIPS_FORMAT_UCHAR; switch (image->Type) { - case VIPS_INTERPRETATION_B_W: - case VIPS_INTERPRETATION_HISTOGRAM: - case VIPS_INTERPRETATION_MULTIBAND: - format = image->BandFmt; - break; - case VIPS_INTERPRETATION_FOURIER: if (image->BandFmt == VIPS_FORMAT_DOUBLE || image->BandFmt == VIPS_FORMAT_DPCOMPLEX) @@ -553,8 +500,12 @@ vips_image_guess_format(const VipsImage *image) format = VIPS_FORMAT_FLOAT; break; + case VIPS_INTERPRETATION_B_W: + case VIPS_INTERPRETATION_HISTOGRAM: + case VIPS_INTERPRETATION_MULTIBAND: default: - format = VIPS_FORMAT_NOTSET; + // for eg. INTERPRETATION_ERROR, stick with the format we have + format = image->BandFmt; break; } @@ -565,7 +516,7 @@ vips_image_guess_format(const VipsImage *image) * vips_image_get_coding: * @image: image to get from * - * Returns: the image coding + * Returns: the [enum@Coding] from the image header. */ VipsCoding vips_image_get_coding(const VipsImage *image) @@ -577,10 +528,10 @@ vips_image_get_coding(const VipsImage *image) * vips_image_get_interpretation: * @image: image to get from * - * Return the #VipsInterpretation set in the image header. - * Use vips_image_guess_interpretation() if you want a sanity-checked value. + * Return the [enum@Interpretation] set in the image header. + * Use [method@Image.guess_format] if you want a sanity-checked value. * - * Returns: the #VipsInterpretation from the image header. + * Returns: the [enum@Interpretation] from the image header. */ VipsInterpretation vips_image_get_interpretation(const VipsImage *image) @@ -664,10 +615,10 @@ vips_image_default_interpretation(const VipsImage *image) * vips_image_guess_interpretation: * @image: image to guess for * - * Return the #VipsInterpretation for an image, guessing a sane value if + * Return the [enum@Interpretation] for an image, guessing a sane value if * the set value looks crazy. * - * Returns: a sensible #VipsInterpretation for the image. + * Returns: a sensible [enum@Interpretation] for the image. */ VipsInterpretation vips_image_guess_interpretation(const VipsImage *image) @@ -841,8 +792,8 @@ vips_image_get_yoffset(const VipsImage *image) * vips_image_get_filename: * @image: image to get from * - * Returns: the name of the file the image was loaded from, or NULL if there - * is no filename. + * Returns: the name of the file the image was loaded from, or `NULL` if + * there is no filename. */ const char * vips_image_get_filename(const VipsImage *image) @@ -936,8 +887,8 @@ vips_image_get_page_height(VipsImage *image) * vips_image_get_n_pages: * @image: image to get from * - * Fetch and sanity-check #VIPS_META_N_PAGES. Default to 1 if not present or - * crazy. + * Fetch and sanity-check [const@META_N_PAGES]. Default to 1 if not present + * or crazy. * * This is the number of pages in the image file, not the number of pages that * have been loaded into @image. @@ -962,8 +913,8 @@ vips_image_get_n_pages(VipsImage *image) * vips_image_get_concurrency: * @image: image to get from * - * Fetch and sanity-check #VIPS_CONCURRENCY. Default to 1 if not present or - * crazy. + * Fetch and sanity-check [const@META_CONCURRENCY]. Default to 1 if not + * present or crazy. * * Returns: the suggested concurrency for this image */ @@ -986,8 +937,8 @@ vips_image_get_concurrency(VipsImage *image, int default_concurrency) * vips_image_get_n_subifds: * @image: image to get from * - * Fetch and sanity-check #VIPS_META_N_SUBIFDS. Default to 0 if not present or - * crazy. + * Fetch and sanity-check [const@META_N_SUBIFDS]. Default to 0 if not + * present or crazy. * * Returns: the number of subifds in the image file */ @@ -1009,7 +960,7 @@ vips_image_get_n_subifds(VipsImage *image) * vips_image_get_orientation: * @image: image to get from * - * Fetch and sanity-check #VIPS_META_ORIENTATION. Default to 1 (no rotate, + * Fetch and sanity-check [const@META_ORIENTATION]. Default to 1 (no rotate, * no flip) if not present or crazy. * * Returns: the image orientation. @@ -1033,7 +984,7 @@ vips_image_get_orientation(VipsImage *image) * vips_image_get_orientation_swap: * @image: image to get from * - * Return %TRUE if applying the orientation would swap width and height. + * Return `TRUE` if applying the orientation would swap width and height. * * Returns: if width/height will swap */ @@ -1057,9 +1008,10 @@ vips_image_get_orientation_swap(VipsImage *image) * Since this function modifies @image, it is not threadsafe. Only call it on * images which you are sure have not been shared with another thread. * - * See also: vips_image_wio_input(), vips_image_copy_memory(). + * ::: seealso + * [method@Image.wio_input], [method@Image.copy_memory]. * - * Returns: (transfer none): a pointer to pixel data, if possible. + * Returns: (nullable) (transfer none): a pointer to pixel data, if possible. */ const void * vips_image_get_data(VipsImage *image) @@ -1084,12 +1036,13 @@ vips_image_get_data(VipsImage *image) * * A convenience function to set the header fields after creating an image. * Normally you copy the fields from your input images with - * vips_image_pipelinev() and then make - * any adjustments you need, but if you are creating an image from scratch, - * for example vips_black() or vips_jpegload(), you do need to set all the + * [method.Image.pipelinev] and then make any adjustments you need, + * but if you are creating an image from scratch, for example + * [ctor@Image.black] or [ctor@Image.jpegload], you do need to set all the * fields yourself. * - * See also: vips_image_pipelinev(). + * ::: seealso + * [method.Image.pipelinev]. */ void vips_image_init_fields(VipsImage *image, @@ -1143,11 +1096,11 @@ vips__image_meta_copy(VipsImage *dst, const VipsImage *src) /* We lock with vips_image_set() to stop races in highly- * threaded applications. */ - g_mutex_lock(vips__meta_lock); + g_mutex_lock(&vips__meta_lock); meta_init(dst); vips_slist_map2(src->meta_traverse, (VipsSListMap2Fn) meta_cp_field, dst, NULL); - g_mutex_unlock(vips__meta_lock); + g_mutex_unlock(&vips__meta_lock); } return 0; @@ -1209,25 +1162,26 @@ vips__image_copy_fields_array(VipsImage *out, VipsImage *in[]) * vips_image_set: * @image: image to set the metadata on * @name: the name to give the metadata - * @value: the %GValue to copy into the image + * @value: the [struct@GObject.Value] to copy into the image * * Set a piece of metadata on @image. Any old metadata with that name is - * destroyed. The %GValue is copied into the image, so you need to unset the + * destroyed. The [struct@GObject.Value] is copied into the image, so you need to unset the * value when you're done with it. * * For example, to set an integer on an image (though you would use the - * convenience function vips_image_set_int() in practice), you would do: + * convenience function [method@Image.set_int] in practice), you would do: * - * |[ + * ```c * GValue value = G_VALUE_INIT; * * g_value_init(&value, G_TYPE_INT); * g_value_set_int(&value, 42); * vips_image_set(image, name, &value); * g_value_unset(&value); - * ]| + * ``` * - * See also: vips_image_get(). + * ::: seealso + * [method@Image.get]. */ void vips_image_set(VipsImage *image, const char *name, GValue *value) @@ -1242,10 +1196,10 @@ vips_image_set(VipsImage *image, const char *name, GValue *value) * metadata copy on another -- this can lead to crashes in * highly-threaded applications. */ - g_mutex_lock(vips__meta_lock); + g_mutex_lock(&vips__meta_lock); meta_init(image); (void) meta_new(image, name, value); - g_mutex_unlock(vips__meta_lock); + g_mutex_unlock(&vips__meta_lock); /* If we're setting an EXIF data block, we need to automatically expand * out all the tags. This will set things like xres/yres too. @@ -1294,21 +1248,22 @@ vips_set_value_from_pointer(GValue *value, void *data) /** * vips_image_get: - * @image: image to get the field from from + * @image: image to get the field from * @name: the name to fetch - * @value_copy: (transfer full) (out caller-allocates): the %GValue is copied into this + * @value_copy: (transfer full) (out caller-allocates): the + * [struct@GObject.Value] is copied into this * * Fill @value_copy with a copy of the header field. @value_copy must be zeroed * but uninitialised. * * This will return -1 and add a message to the error buffer if the field - * does not exist. Use vips_image_get_typeof() to test for the + * does not exist. Use [method@Image.get_typeof] to test for the * existence of a field first if you are not certain it will be there. * * For example, to read a double from an image (though of course you would use - * vips_image_get_double() in practice): + * [method@Image.get_double] in practice): * - * |[ + * ```c * GValue value = G_VALUE_INIT; * double d; * @@ -1326,9 +1281,10 @@ vips_set_value_from_pointer(GValue *value, void *data) * * d = g_value_get_double(&value); * g_value_unset(&value); - * ]| + * ``` * - * See also: vips_image_get_typeof(), vips_image_get_double(). + * ::: seealso + * [method@Image.get_typeof], [method@Image.get_double]. * * Returns: (skip): 0 on success, -1 otherwise. */ @@ -1387,13 +1343,14 @@ vips_image_get(const VipsImage *image, const char *name, GValue *value_copy) * @image: image to test * @name: the name to search for * - * Read the %GType for a header field. Returns zero if there is no - * field of that name. + * Read the [alias@GObject.Type] for a header field. Returns zero if there + * is no field of that name. * - * See also: vips_image_get(). + * ::: seealso + * [method@Image.get]. * - * Returns: the %GType of the field, or zero if there is no - * field of that name. + * Returns: the [alias@GObject.Type] of the field, or zero if there is no + * field of that name. */ GType vips_image_get_typeof(const VipsImage *image, const char *name) @@ -1431,12 +1388,13 @@ vips_image_get_typeof(const VipsImage *image, const char *name) * @image: image to test * @name: the name to search for * - * Find and remove an item of metadata. Return %FALSE if no metadata of that + * Find and remove an item of metadata. Return `FALSE` if no metadata of that * name was found. * - * See also: vips_image_set(), vips_image_get_typeof(). + * ::: seealso + * [method@Image.set], [method@Image.get_typeof]. * - * Returns: %TRUE if an item of metadata of that name was found and removed + * Returns: `TRUE` if an item of metadata of that name was found and removed */ gboolean vips_image_remove(VipsImage *image, const char *name) @@ -1453,9 +1411,9 @@ vips_image_remove(VipsImage *image, const char *name) * racing with metadata copy on another -- this can lead to * crashes in highly-threaded applications. */ - g_mutex_lock(vips__meta_lock); + g_mutex_lock(&vips__meta_lock); result = g_hash_table_remove(image->meta, name); - g_mutex_unlock(vips__meta_lock); + g_mutex_unlock(&vips__meta_lock); } return result; @@ -1488,18 +1446,20 @@ vips_image_map_fn(VipsMeta *meta, VipsImageMapFn fn, void *a) /** * vips_image_map: * @image: image to map over - * @fn: (scope call): function to call for each header field - * @a: (closure fn): user data for function + * @fn: (scope call) (closure a): function to call for each header field + * @a: user data for @fn * * This function calls @fn for every header field, including every item of * metadata. * - * Like all _map functions, the user function should return %NULL to continue - * iteration, or a non-%NULL pointer to indicate early termination. + * Like all _map functions, the user function should return `NULL` to continue + * iteration, or a non-`NULL` pointer to indicate early termination. * - * See also: vips_image_get_typeof(), vips_image_get(). + * ::: seealso + * [method@Image.get_typeof], [method@Image.get]. * - * Returns: (transfer none): %NULL on success, the failing pointer otherwise. + * Returns: (nullable) (transfer none): `NULL` on success, the failing + * pointer otherwise. */ void * vips_image_map(VipsImage *image, VipsImageMapFn fn, void *a) @@ -1552,14 +1512,14 @@ add_fields(VipsImage *image, const char *field, GValue *value, void *a) * vips_image_get_fields: * @image: image to get fields from * - * Get a %NULL-terminated array listing all the metadata field names on @image. - * Free the return result with g_strfreev(). + * Get a `NULL`-terminated array listing all the metadata field names on @image. + * Free the return result with [func@GLib.strfreev]. * * This is handy for language bindings. From C, it's usually more convenient to - * use vips_image_map(). + * use [method@Image.map]. * - * Returns: (transfer full): metadata fields in image, as a %NULL-terminated - * array. + * Returns: (transfer full): metadata fields in image, as a `NULL`-terminated + * array. */ gchar ** vips_image_get_fields(VipsImage *image) @@ -1587,7 +1547,8 @@ vips_image_get_fields(VipsImage *image) * Attaches @data as a metadata item on @image under the name @name. When * VIPS no longer needs the metadata, it will be freed with @free_fn. * - * See also: vips_image_get_double(), vips_image_set() + * ::: seealso + * [method@Image.get_double], [method@Image.set]. */ void vips_image_set_area(VipsImage *image, const char *name, @@ -1631,11 +1592,12 @@ meta_get_value(const VipsImage *image, * @data: (out): return metadata value * * Gets @data from @image under the name @name. A convenience - * function over vips_image_get(). Use vips_image_get_typeof() to test for - * the existence of a piece of metadata. + * function over [method@Image.get]. Use [method@Image.get_typeof] to + * test for the existence of a piece of metadata. * - * See also: vips_image_set_area(), vips_image_get(), - * vips_image_get_typeof() + * ::: seealso + * [method@Image.set_area], [method@Image.get], + * [method@Image.get_typeof]. * * Returns: 0 on success, -1 otherwise. */ @@ -1660,12 +1622,13 @@ vips_image_get_area(const VipsImage *image, * @name: metadata name * @free_fn: (scope async) (nullable): free function for @data * @data: (array length=length) (element-type guint8) (transfer full): pointer to area of - * memory + * memory * @length: length of memory area * * Attaches @data as a metadata item on @image under the name @name. * - * See also: vips_image_get_blob(), vips_image_set(). + * ::: seealso + * [method@Image.get_blob], [method@Image.set]. */ void vips_image_set_blob(VipsImage *image, const char *name, @@ -1689,7 +1652,8 @@ vips_image_set_blob(VipsImage *image, const char *name, * Attaches @data as a metadata item on @image under the name @name, taking * a copy of the memory area. * - * See also: vips_image_get_blob(), vips_image_set(). + * ::: seealso + * [method@Image.get_blob], [method@Image.set]. */ void vips_image_set_blob_copy(VipsImage *image, @@ -1721,14 +1685,17 @@ vips_image_set_blob_copy(VipsImage *image, * vips_image_get_blob: * @image: image to get the metadata from * @name: metadata name - * @data: (out) (array length=length) (element-type guint8): pointer to area of memory + * @data: (out) (array length=length) (element-type guint8): pointer to area + * of memory * @length: (out): return the blob length here, optionally * * Gets @data from @image under the name @name, optionally returns its - * length in @length. Use vips_image_get_typeof() to test for the existence + * length in @length. Use [method@Image.get_typeof] to test for the existence * of a piece of metadata. * - * See also: vips_image_get(), vips_image_get_typeof(), vips_blob_get(), + * ::: seealso + * [method@Image.get], [method@Image.get_typeof], + * [method@Blob.get]. * * Returns: 0 on success, -1 otherwise. */ @@ -1754,10 +1721,10 @@ vips_image_get_blob(const VipsImage *image, const char *name, * @out: (out): return field value * * Gets @out from @im under the name @name. - * The value will be transformed into - * an int, if possible. + * The value will be transformed into an int, if possible. * - * See also: vips_image_get(), vips_image_get_typeof() + * ::: seealso + * [method@Image.get], [method@Image.get_typeof]. * * Returns: 0 on success, -1 otherwise. */ @@ -1781,10 +1748,10 @@ vips_image_get_int(const VipsImage *image, const char *name, int *out) * @i: metadata value * * Attaches @i as a metadata item on @image under the name @name. A - * convenience - * function over vips_image_set(). + * convenience function over [method@Image.set]. * - * See also: vips_image_get_int(), vips_image_set() + * ::: seealso + * [method@Image.get_int], [method@Image.set]. */ void vips_image_set_int(VipsImage *image, const char *name, int i) @@ -1804,10 +1771,10 @@ vips_image_set_int(VipsImage *image, const char *name, int i) * @out: (out): return field value * * Gets @out from @im under the name @name. - * The value will be transformed into - * a double, if possible. + * The value will be transformed into a double, if possible. * - * See also: vips_image_get(), vips_image_get_typeof() + * ::: seealso + * [method@Image.get], [method@Image.get_typeof]. * * Returns: 0 on success, -1 otherwise. */ @@ -1831,10 +1798,10 @@ vips_image_get_double(const VipsImage *image, const char *name, double *out) * @d: metadata value * * Attaches @d as a metadata item on @image as @name. A - * convenience - * function over vips_image_set(). + * convenience function over [method@Image.set]. * - * See also: vips_image_get_double(), vips_image_set() + * ::: seealso + * [method@Image.get_double], [method@Image.set]. */ void vips_image_set_double(VipsImage *image, const char *name, double d) @@ -1854,14 +1821,14 @@ vips_image_set_double(VipsImage *image, const char *name, double d) * @out: (out) (transfer none): return field value * * Gets @out from @im under the name @name. - * The field must be of type - * G_TYPE_STRING, VIPS_TYPE_REF_STRING. + * The field must be of type `G_TYPE_STRING` or `VIPS_TYPE_REF_STRING`. * * Do not free @out. * - * Use vips_image_get_as_string() to fetch any field as a string. + * Use [method@Image.get_as_string] to fetch any field as a string. * - * See also: vips_image_get(), vips_image_get_typeof() + * ::: seealso + * [method@Image.get], [method@Image.get_typeof]. * * Returns: 0 on success, -1 otherwise. */ @@ -1906,9 +1873,10 @@ vips_image_get_string(const VipsImage *image, const char *name, * * Attaches @str as a metadata item on @image as @name. * A convenience - * function over vips_image_set() using #VIPS_TYPE_REF_STRING. + * function over [method@Image.set] using `VIPS_TYPE_REF_STRING`. * - * See also: vips_image_get_double(), vips_image_set(). + * ::: seealso + * [method@Image.get_double], [method@Image.set]. */ void vips_image_set_string(VipsImage *image, const char *name, const char *str) @@ -1929,12 +1897,14 @@ vips_image_set_string(VipsImage *image, const char *name, const char *str) * * Returns @name from @image in @out. * This function will read any field, returning it as a printable string. - * You need to free the string with g_free() when you are done with it. + * You need to free the string with [func@GLib.free] when you are done with it. * - * This will base64-encode BLOBs, for example. Use vips_buf_appendgv() to + * This will base64-encode BLOBs, for example. Use [method@Buf.appendg] to * make a string that's for humans. * - * See also: vips_image_get(), vips_image_get_typeof(), vips_buf_appendgv(). + * ::: seealso + * [method@Image.get], [method@Image.get_typeof], + * [method@Buf.appendg]. * * Returns: 0 on success, -1 otherwise. */ @@ -1998,13 +1968,14 @@ vips_image_print_field(const VipsImage *image, const char *name) * @out: (out) (transfer full): return metadata value * * Gets @out from @im under the name @name. - * The field must be of type - * #VIPS_TYPE_IMAGE. You must unref @out with g_object_unref(). + * The field must be of type `VIPS_TYPE_IMAGE`. + * You must unref @out with [method@GObject.Object.unref]. * - * Use vips_image_get_typeof() to test for the + * Use [method@Image.get_typeof] to test for the * existence of a piece of metadata. * - * See also: vips_image_get(), vips_image_set_image() + * ::: seealso + * [method@Image.get], [method@Image.set_image] * * Returns: 0 on success, -1 otherwise. */ @@ -2029,9 +2000,10 @@ vips_image_get_image(const VipsImage *image, * @im: metadata value * * Attaches @im as a metadata item on @image as @name. - * A convenience function over vips_image_set(). + * A convenience function over [method@Image.set]. * - * See also: vips_image_get_image(), vips_image_set(). + * ::: seealso + * [method@Image.get_image], [method@Image.set]. */ void vips_image_set_image(VipsImage *image, const char *name, VipsImage *im) @@ -2052,15 +2024,15 @@ vips_image_set_image(VipsImage *image, const char *name, VipsImage *im) * @n: (out) (optional): return the number of elements here, optionally * * Gets @out from @im under the name @name. - * The field must be of type - * #VIPS_TYPE_ARRAY_INT. + * The field must be of type `VIPS_TYPE_ARRAY_INT`. * * Do not free @out. @out is valid as long as @image is valid. * - * Use vips_image_get_typeof() to test for the + * Use [method@Image.get_typeof] to test for the * existence of a piece of metadata. * - * See also: vips_image_get(), vips_image_set_image() + * ::: seealso + * [method@Image.get], [method@Image.set_image] * * Returns: 0 on success, -1 otherwise. */ @@ -2086,9 +2058,10 @@ vips_image_get_array_int(VipsImage *image, const char *name, * @n: the number of elements * * Attaches @array as a metadata item on @image as @name. - * A convenience function over vips_image_set(). + * A convenience function over [method@Image.set]. * - * See also: vips_image_get_image(), vips_image_set(). + * ::: seealso + * [method@Image.get_image], [method@Image.set]. */ void vips_image_set_array_int(VipsImage *image, const char *name, @@ -2110,15 +2083,15 @@ vips_image_set_array_int(VipsImage *image, const char *name, * @n: (out) (optional): return the number of elements here, optionally * * Gets @out from @im under the name @name. - * The field must be of type - * #VIPS_TYPE_ARRAY_INT. + * The field must be of type `VIPS_TYPE_ARRAY_INT`. * * Do not free @out. @out is valid as long as @image is valid. * - * Use vips_image_get_typeof() to test for the + * Use [method@Image.get_typeof] to test for the * existence of a piece of metadata. * - * See also: vips_image_get(), vips_image_set_image() + * ::: seealso + * [method@Image.get], [method@Image.set_image] * * Returns: 0 on success, -1 otherwise. */ @@ -2144,9 +2117,10 @@ vips_image_get_array_double(VipsImage *image, const char *name, * @n: the number of elements * * Attaches @array as a metadata item on @image as @name. - * A convenience function over vips_image_set(). + * A convenience function over [method@Image.set]. * - * See also: vips_image_get_image(), vips_image_set(). + * ::: seealso + * [method@Image.get_image], [method@Image.set]. */ void vips_image_set_array_double(VipsImage *image, const char *name, @@ -2163,7 +2137,7 @@ vips_image_set_array_double(VipsImage *image, const char *name, /** * vips_image_history_printf: * @image: add history line to this image - * @format: printf() format string + * @format: `printf()`-style format string * @...: arguments to format string * * Add a line to the image history. The @format and arguments are expanded, the @@ -2172,16 +2146,16 @@ vips_image_set_array_double(VipsImage *image, const char *name, * * For example: * - * |[ + * ```c * vips_image_history_printf(image, "vips invert %s %s", * in->filename, out->filename); - * ]| + * ``` * * Might add the string * - * |[ + * ```bash * "vips invert /home/john/fred.v /home/john/jim.v # Fri Apr 3 23:30:35 2009\n" - * ]| + * ``` * * VIPS operations don't add history lines for you because a single action at * the application level might involve many VIPS operations. History must be @@ -2228,10 +2202,11 @@ vips_image_history_printf(VipsImage *image, const char *fmt, ...) * @argv: (array length=argc) (element-type char*): program arguments * * Formats the name/argv as a single string and calls - * vips_image_history_printf(). A - * convenience function for command-line prorams. + * [method@Image.history_printf]. A convenience function for + * command-line programs. * - * See also: vips_image_get_history(). + * ::: seealso + * [method@Image.get_history]. * * Returns: 0 on success, -1 on error. */ @@ -2265,10 +2240,11 @@ vips_image_history_args(VipsImage *image, * * VIPS tracks the history of each image, that is, the sequence of operations * that generated that image. Applications built on VIPS need to call - * vips_image_history_printf() for each action they perform, setting the + * [method@Image.history_printf] for each action they perform, setting the * command-line equivalent for the action. * - * See also: vips_image_history_printf(). + * ::: seealso + * [method@Image.history_printf]. * * Returns: (transfer none): The history of @image as a C string. Do not free! */ @@ -2280,12 +2256,3 @@ vips_image_get_history(VipsImage *image) return image->Hist ? image->Hist : ""; } - -/* Called during vips_init(). - */ -void -vips__meta_init(void) -{ - if (!vips__meta_lock) - vips__meta_lock = vips_g_mutex_new(); -} diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 7794a0bf1c..0521cc11dd 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -19,7 +19,7 @@ * 9/10/18 * - fix up vips_image_dump(), it was still using ints not enums * 10/12/19 - * - add vips_image_new_from_source() / vips_image_write_to_target() + * - add vips_image_new_from_source / vips_image_write_to_target() */ /* @@ -72,72 +72,65 @@ #include /** - * SECTION: image - * @short_description: the VIPS image class - * @stability: Stable - * @see_also: header - * VipsRegion - * generate - * VipsOperation - * @include: vips/vips.h + * VipsImage: * - * The image class and associated types and macros. + * The [class@Image] class and associated types and macros. * * Images can be created from formatted files on disc, from C-style arrays on * disc, from formatted areas of memory, or from C-style arrays in memory. See - * vips_image_new_from_file() and friends. - * Creating an image is fast. VIPS reads just enough of + * [ctor@Image.new_from_file] and friends. + * Creating an image is fast. libvips reads just enough of * the image to be able to get the various properties, such as width in * pixels. It delays reading any pixels until they are really needed. * * Once you have an image, you can get properties from it in the usual way. - * You can use projection functions, like vips_image_get_width() or - * g_object_get(), to get %GObject properties. + * You can use projection functions, like [method@Image.get_width] or + * [method@GObject.Object.get], to get [class@GObject.Object] properties. * - * VIPS images are three-dimensional arrays, the dimensions being width, + * `.v` images are three-dimensional arrays, the dimensions being width, * height and bands. Each dimension can be up to 2 ** 31 pixels (or band * elements). An image has a format, meaning the machine number type used - * to represent each value. VIPS supports 10 formats, from 8-bit unsigned - * integer up to 128-bit double complex, see vips_image_get_format(). + * to represent each value. libvips supports 10 formats, from 8-bit unsigned + * integer up to 128-bit double complex, see [method@Image.get_format]. * - * In VIPS, images are uninterpreted arrays, meaning that from the point of - * view of most operations, they are just large collections of numbers. + * In libvips, images are uninterpreted arrays, meaning that from the point + * of view of most operations, they are just large collections of numbers. * There's no difference between an RGBA (RGB with alpha) image and a CMYK * image, for example, they are both just four-band images. It's up to the * user of the library to pass the right sort of image to each operation. * - * To take an example, VIPS has vips_Lab2XYZ(), an operation to transform - * an image from CIE LAB colour space to CIE XYZ space. It assumes the - * first three bands represent pixels in LAB colour space and returns an + * To take an example, libvips has [method@Image.Lab2XYZ], an operation to + * transform an image from CIE LAB colour space to CIE XYZ space. It assumes + * the first three bands represent pixels in LAB colour space and returns an * image where the first three bands are transformed to XYZ and any - * remaining bands are just copied. Pass it a RGB image by mistake and + * remaining bands are just copied. Pass it an RGB image by mistake and * you'll just get nonsense. * - * VIPS has a feature to help (a little) with this: it sets a - * #VipsInterpretation hint for each image (see - * vips_image_get_interpretation()); a hint which says how pixels should - * be interpreted. For example, vips_Lab2XYZ() will set the - * interpretation of the output image to #VIPS_INTERPRETATION_XYZ. A - * few utility operations will also use interpretation as a guide. For - * example, you can give vips_colourspace() an input image and a desired - * colourspace and it will use the input's interpretation hint to apply - * the best sequence of colourspace transforms to get to the desired space. - * - * Use things like vips_invert() to manipulate your images. When you are done, - * you can write images to disc files (with vips_image_write_to_file()), - * to formatted memory buffers (with vips_image_write_to_buffer()) and to - * C-style memory arrays (with vips_image_write_to_memory(). + * libvips has a feature to help (a little) with this: it sets a + * [enum@Interpretation] hint for each image (see + * [method@Image.get_interpretation]); a hint which says how pixels should + * be interpreted. For example, [method@Image.Lab2XYZ] will set the + * interpretation of the output image to [enum@Vips.Interpretation.XYZ]. + * A few utility operations will also use interpretation as a guide. For + * example, you can give [method@Image.colourspace] an input image and a + * desired colourspace and it will use the input's interpretation hint to + * apply the best sequence of colourspace transforms to get to the desired + * space. + * + * Use things like [method@Image.invert] to manipulate your images. When you + * are done, you can write images to disc files (with + * [method@Image.write_to_file]), to formatted memory buffers (with + * [method@Image.write_to_buffer]) and to C-style memory arrays (with + * [method@Image.write_to_memory]). * * You can also write images to other images. Create, for example, a temporary - * disc image with vips_image_new_temp_file(), then write your image to that - * with vips_image_write(). You can create several other types of image and - * write to them, see vips_image_new_memory(), for example. + * disc image with [ctor@Image.new_temp_file], then write your image to that + * with [method@Image.write]. You can create several other types of image and + * write to them, see [ctor@Image.new_memory], for example. * - * See operation for an introduction to - * running operations on images, see header for getting and setting image - * metadata. See object for a discussion of - * the lower levels. + * See [class@Operation] for an introduction to running operations on images, + * see [Image headers](libvips-header.html) for getting and setting image + * metadata. See [class@Object] for a discussion of the lower levels. */ /** @@ -157,12 +150,12 @@ * @VIPS_ACCESS_RANDOM: can read anywhere * @VIPS_ACCESS_SEQUENTIAL: top-to-bottom reading only, but with a small buffer * - * The type of access an operation has to supply. See vips_tilecache() - * and #VipsForeign. + * The type of access an operation has to supply. See [method@Image.tilecache] + * and [class@Foreign]. * - * @VIPS_ACCESS_RANDOM means requests can come in any order. + * [enum@Vips.Access.RANDOM] means requests can come in any order. * - * @VIPS_ACCESS_SEQUENTIAL means requests will be top-to-bottom, but with some + * [enum@Vips.Access.SEQUENTIAL] means requests will be top-to-bottom, but with some * amount of buffering behind the read point for small non-local accesses. */ @@ -173,34 +166,35 @@ * @VIPS_DEMAND_STYLE_THINSTRIP: demand in thin (typically 1 pixel high) strips * @VIPS_DEMAND_STYLE_ANY: demand geometry does not matter * - * See vips_image_pipelinev(). Operations can hint + * See [method@Image.pipelinev]. Operations can hint * the kind of demand geometry they prefer * to the VIPS image IO system. * * These demand styles are given below in order of increasing * specialisation. When demanding output from a pipeline, - * vips_image_generate() + * [method@Image.generate] * will use the most general style requested by the operations * in the pipeline. * - * #VIPS_DEMAND_STYLE_SMALLTILE --- This is the most general demand format. + * [enum@Vips.DemandStyle.SMALLTILE] -- This is the most general demand format. * Output is demanded in small (around 100x100 pel) sections. This style works * reasonably efficiently, even for bizarre operations like 45 degree rotate. * - * #VIPS_DEMAND_STYLE_FATSTRIP --- This operation would like to output strips + * [enum@Vips.DemandStyle.FATSTRIP] -- This operation would like to output strips * the width of the image and as high as possible. This option is suitable * for area operations which do not violently transform coordinates, such - * as vips_conv(). + * as [method@Image.conv]. * - * #VIPS_DEMAND_STYLE_THINSTRIP --- This operation would like to output strips + * [enum@Vips.DemandStyle.THINSTRIP] -- This operation would like to output strips * the width of the image and a few pels high. This option is suitable for * point-to-point operations, such as those in the arithmetic package. * - * #VIPS_DEMAND_STYLE_ANY --- This image is not being demand-read from a disc + * [enum@Vips.DemandStyle.ANY] -- This image is not being demand-read from a disc * file (even indirectly) so any demand style is OK. It's used for things like - * vips_black() where the pixels are calculated. + * [ctor@Image.black] where the pixels are calculated. * - * See also: vips_image_pipelinev(). + * ::: seealso + * [method@Image.pipelinev]. */ /** @@ -212,7 +206,7 @@ * @VIPS_INTERPRETATION_XYZ: the first three bands are CIE XYZ * @VIPS_INTERPRETATION_LAB: pixels are in CIE Lab space * @VIPS_INTERPRETATION_CMYK: the first four bands are in CMYK space - * @VIPS_INTERPRETATION_LABQ: implies #VIPS_CODING_LABQ + * @VIPS_INTERPRETATION_LABQ: implies [enum@Vips.Coding.LABQ] * @VIPS_INTERPRETATION_RGB: generic RGB space * @VIPS_INTERPRETATION_CMC: a uniform colourspace based on CMC(1:1) * @VIPS_INTERPRETATION_LCH: pixels are in CIE LCh space @@ -226,7 +220,7 @@ * @VIPS_INTERPRETATION_MATRIX: a matrix * * How the values in an image should be interpreted. For example, a - * three-band float image of type #VIPS_INTERPRETATION_LAB should have its + * three-band float image of type [enum@Vips.Interpretation.LAB] should have its * pixels interpreted as coordinates in CIE Lab space. * * RGB and sRGB are treated in the same way. Use the colourspace functions if @@ -253,7 +247,7 @@ * The format used for each band element. * * Each corresponds to a native C type for the current machine. For example, - * #VIPS_FORMAT_USHORT is unsigned short. + * [enum@Vips.BandFormat.USHORT] is `unsigned short`. */ /** @@ -282,85 +276,78 @@ * @start: Start time * * A structure available to eval callbacks giving information on evaluation - * progress. See #VipsImage::eval. - */ - -/** - * VipsImage: - * - * An image. These can represent an image on disc, a memory buffer, an image - * in the process of being written to disc or a partially evaluated image - * in memory. + * progress. See [signal@Image::eval]. */ /** * VIPS_IMAGE_SIZEOF_ELEMENT: - * @I: a #VipsImage + * @I: a [class@Image] * - * Returns: sizeof() a band element. + * Returns: `sizeof()` a band element. */ /** * VIPS_IMAGE_SIZEOF_PEL: - * @I: a #VipsImage + * @I: a [class@Image] * - * Returns: sizeof() a pixel. + * Returns: `sizeof()` a pixel. */ /** * VIPS_IMAGE_SIZEOF_LINE: - * @I: a #VipsImage + * @I: a [class@Image] * - * Returns: sizeof() a scanline of pixels. + * Returns: `sizeof()` a scanline of pixels. */ /** * VIPS_IMAGE_N_ELEMENTS: - * @I: a #VipsImage + * @I: a [class@Image] * * Returns: The number of band elements in a scanline. */ /** * VIPS_IMAGE_N_PELS: - * @I: a #VipsImage + * @I: a [class@Image] * * Returns: The number of pels in an image. A 64-bit unsigned int. */ /** * VIPS_IMAGE_ADDR: - * @I: a #VipsImage + * @I: a [class@Image] * @X: x coordinate * @Y: y coordinate * - * This macro returns a pointer to a pixel in an image, cast to a #VipsPel *. - * It only works for - * images which are fully available in memory, so memory buffers and small - * mapped images only. + * This macro returns a pointer to a pixel in an image, cast to a [alias@Pel]*. + * It only works for images which are fully available in memory, so memory + * buffers and small mapped images only. * * If VIPS_DEBUG is defined, you get a version that checks bounds for you. * - * See also: vips_image_wio_input(), vips_image_inplace(), VIPS_REGION_ADDR(). + * ::: seealso + * [method@Image.wio_input], [method@Image.inplace], [func@REGION_ADDR]. * * Returns: The address of pixel (@X,@Y) in @I. */ /** * VIPS_MATRIX: - * @I: a #VipsImage + * @I: a [class@Image] * @X: x coordinate * @Y: y coordinate * * This macro returns a pointer to a pixel in an image, cast to a double*. The - * image must have a single band, be #VIPS_FORMAT_DOUBLE and be + * image must have a single band, be [enum@Vips.BandFormat.DOUBLE] and be * fully available in memory, so memory buffers and small * mapped images only. * * If VIPS_DEBUG is defined, you get a version that checks bounds and image * type for you. * - * See also: vips_image_wio_input(), vips_image_inplace(), vips_check_matrix(). + * ::: seealso + * [method@Image.wio_input], [method@Image.inplace], [func@check_matrix]. * * Returns: The address of pixel (@X,@Y) in @I. */ @@ -388,7 +375,7 @@ char *vips__disc_threshold = NULL; /* Minimise needs a lock. */ -static GMutex *vips__minimise_lock = NULL; +static GMutex vips__minimise_lock; static guint vips_image_signals[SIG_LAST] = { 0 }; @@ -396,7 +383,7 @@ G_DEFINE_TYPE(VipsImage, vips_image, VIPS_TYPE_OBJECT); /** * vips_progress_set: - * @progress: %TRUE to enable progress messages + * @progress: `TRUE` to enable progress messages * * If set, vips will print messages about the progress of computation to * stdout. This can also be enabled with the --vips-progress option, or by @@ -471,7 +458,7 @@ vips_image_finalize(GObject *gobject) */ vips_image_delete(image); - VIPS_FREEF(vips_g_mutex_free, image->sslock); + g_mutex_clear(&image->sslock); VIPS_FREE(image->Hist); VIPS_FREEF(vips__gslist_gvalue_free, image->history_list); @@ -600,8 +587,7 @@ vips_image_dump(VipsObject *object, VipsBuf *buf) vips_image_get_bands(image)), vips_image_get_width(image), vips_image_get_height(image), - vips_enum_nick(VIPS_TYPE_BAND_FORMAT, - vips_image_get_format(image)), + vips_enum_nick(VIPS_TYPE_BAND_FORMAT, vips_image_get_format(image)), vips_image_get_bands(image), vips_enum_nick(VIPS_TYPE_INTERPRETATION, vips_image_get_interpretation(image))); @@ -632,8 +618,7 @@ vips_image_summary(VipsObject *object, VipsBuf *buf) " %s, %d band, %s", " %s, %d bands, %s", vips_image_get_bands(image)), - vips_enum_nick(VIPS_TYPE_BAND_FORMAT, - vips_image_get_format(image)), + vips_enum_nick(VIPS_TYPE_BAND_FORMAT, vips_image_get_format(image)), vips_image_get_bands(image), vips_enum_nick(VIPS_TYPE_INTERPRETATION, vips_image_get_interpretation(image))); @@ -698,7 +683,7 @@ vips_image_sanity(VipsObject *object, VipsBuf *buf) /* Must lock around inter-image links. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); if (vips_slist_map2(image->upstream, (VipsSListMap2Fn) vips_image_sanity_upstream, image, NULL)) @@ -707,7 +692,7 @@ vips_image_sanity(VipsObject *object, VipsBuf *buf) (VipsSListMap2Fn) vips_image_sanity_downstream, image, NULL)) vips_buf_appends(buf, "downstream broken\n"); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); VIPS_OBJECT_CLASS(vips_image_parent_class)->sanity(object, buf); } @@ -803,7 +788,7 @@ vips_image_add_progress(VipsImage *image) { if (vips__progress || g_getenv("VIPS_PROGRESS") -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED || g_getenv("IM_PROGRESS") #endif ) { @@ -1025,14 +1010,14 @@ vips_image_real_invalidate(VipsImage *image, void *data) VIPS_GATE_START("vips_image_real_invalidate: wait"); - g_mutex_lock(image->sslock); + g_mutex_lock(&image->sslock); VIPS_GATE_STOP("vips_image_real_invalidate: wait"); (void) vips_slist_map2(image->regions, (VipsSListMap2Fn) vips_image_real_invalidate_cb, NULL, NULL); - g_mutex_unlock(image->sslock); + g_mutex_unlock(&image->sslock); } static void @@ -1215,12 +1200,12 @@ vips_image_class_init(VipsImageClass *class) /** * VipsImage::preeval: * @image: the image to be calculated - * @progress: (type VipsProgress): #VipsProgress for this image + * @progress: (type VipsProgress): [struct@Progress] for this image * - * The ::preeval signal is emitted once before computation of @image + * This signal is emitted once before computation of @image * starts. It's a good place to set up evaluation feedback. * - * Use vips_image_set_progress() to turn on progress reporting for an + * Use [method@Image.set_progress] to turn on progress reporting for an * image. */ vips_image_signals[SIG_PREEVAL] = g_signal_new("preeval", @@ -1235,16 +1220,16 @@ vips_image_class_init(VipsImageClass *class) /** * VipsImage::eval: * @image: the image being calculated - * @progress: (type VipsProgress): #VipsProgress for this image + * @progress: (type VipsProgress): [struct@Progress] for this image * - * The ::eval signal is emitted once per work unit (typically a 128 x + * This signal is emitted once per work unit (typically a 128 x * 128 area of pixels) during image computation. * * You can use this signal to update user-interfaces with progress * feedback. Beware of updating too frequently: you will usually * need some throttling mechanism. * - * Use vips_image_set_progress() to turn on progress reporting for an + * Use [method@Image.set_progress] to turn on progress reporting for an * image. */ vips_image_signals[SIG_EVAL] = g_signal_new("eval", @@ -1259,12 +1244,12 @@ vips_image_class_init(VipsImageClass *class) /** * VipsImage::posteval: * @image: the image that was calculated - * @progress: (type VipsProgress): #VipsProgress for this image + * @progress: (type VipsProgress): [struct@Progress] for this image * - * The ::posteval signal is emitted once at the end of the computation + * This signal is emitted once at the end of the computation * of @image. It's a good place to shut down evaluation feedback. * - * Use vips_image_set_progress() to turn on progress reporting for an + * Use [method@Image.set_progress] to turn on progress reporting for an * image. */ vips_image_signals[SIG_POSTEVAL] = g_signal_new("posteval", @@ -1281,7 +1266,7 @@ vips_image_class_init(VipsImageClass *class) * @image: the image that was calculated * @result: (out) (type gint): set to non-zero to indicate error * - * The ::written signal is emitted just after an image has been + * This signal is emitted just after an image has been * written to. It is * used by vips to implement things like write to foreign file * formats. @@ -1299,9 +1284,9 @@ vips_image_class_init(VipsImageClass *class) * VipsImage::invalidate: * @image: the image that has changed * - * The ::invalidate signal is emitted when an image or one of it's + * This signal is emitted when an image or one of it's * upstream data sources has been destructively modified. See - * vips_image_invalidate_all(). + * [method@Image.invalidate_all]. */ vips_image_signals[SIG_INVALIDATE] = g_signal_new("invalidate", G_TYPE_FROM_CLASS(class), @@ -1315,9 +1300,9 @@ vips_image_class_init(VipsImageClass *class) * VipsImage::minimise: * @image: the image that is being minimised * - * The ::minimise signal is emitted when an image has been asked to + * This signal is emitted when an image has been asked to * minimise memory usage. All non-essential caches are dropped. - * See vips_image_minimise_all(). + * See [method@Image.minimise_all]. */ vips_image_signals[SIG_MINIMISE] = g_signal_new("minimise", G_TYPE_FROM_CLASS(class), @@ -1326,8 +1311,6 @@ vips_image_class_init(VipsImageClass *class) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - vips__minimise_lock = vips_g_mutex_new(); } static void @@ -1349,7 +1332,7 @@ vips_image_init(VipsImage *image) image->Yres = 1.0; image->fd = -1; /* since 0 is stdout */ - image->sslock = vips_g_mutex_new(); + g_mutex_init(&image->sslock); image->sizeof_header = VIPS_SIZEOF_HEADER; @@ -1392,18 +1375,19 @@ vips_image_invalidate_all_cb(VipsImage *image, void *a, void *b) /** * vips_image_invalidate_all: - * @image: #VipsImage to invalidate + * @image: [class@Image] to invalidate * * Invalidate all pixel caches on @image and any downstream images, that * is, images which depend on this image. Additionally, all operations which * depend upon this image are dropped from the VIPS operation cache. * - * You should call this function after - * destructively modifying an image with something like vips_draw_circle(). + * You should call this function after destructively modifying an image with + * something like [method@Image.draw_circle]. * - * The #VipsImage::invalidate signal is emitted for all invalidated images. + * The [signal@Image::invalidate] signal is emitted for all invalidated images. * - * See also: vips_region_invalidate(). + * ::: seealso + * [method@Region.invalidate]. */ void vips_image_invalidate_all(VipsImage *image) @@ -1432,37 +1416,42 @@ vips_image_minimise_all_cb(VipsImage *image, void *a, void *b) /** * vips_image_minimise_all: - * @image: #VipsImage to minimise + * @image: [class@Image] to minimise * * Minimise memory use on this image and any upstream images, that is, images * which this image depends upon. This function is called automatically at the * end of a computation, but it might be useful to call at other times. * - * The #VipsImage::minimise signal is emitted for all minimised images. + * The [signal@Image::minimise] signal is emitted for all minimised images. */ void vips_image_minimise_all(VipsImage *image) { + /* Just like the eval callbacks, don't minimise for sub-evaluations. + */ + if (vips_image_get_typeof(image, "hide-progress")) + return; + /* Minimisation will modify things like sources, so we can't run it * from many threads. */ - g_mutex_lock(vips__minimise_lock); + g_mutex_lock(&vips__minimise_lock); (void) vips__link_map(image, TRUE, (VipsSListMap2Fn) vips_image_minimise_all_cb, NULL, NULL); - g_mutex_unlock(vips__minimise_lock); + g_mutex_unlock(&vips__minimise_lock); } /** * vips_image_is_sequential: - * @image: #VipsImage to minimise + * @image: [class@Image] to minimise * * TRUE if any of the images upstream from @image were opened in sequential * mode. Some operations change behaviour slightly in sequential mode to * optimize memory behaviour. * - * Returns: %TRUE if @image is in sequential mode. + * Returns: `TRUE` if @image is in sequential mode. */ gboolean vips_image_is_sequential(VipsImage *image) @@ -1564,8 +1553,7 @@ vips_image_eval(VipsImage *image, guint64 processed) * the image we are actually generating. */ if (image->progress_signal->time != image->time) - vips_progress_update(image->progress_signal->time, - processed); + vips_progress_update(image->progress_signal->time, processed); if (!vips_image_get_typeof(image, "hide-progress")) g_signal_emit(image->progress_signal, @@ -1611,10 +1599,10 @@ vips_image_posteval(VipsImage *image) * @image: image to signal progress on * @progress: turn progress reporting on or off * - * vips signals evaluation progress via the #VipsImage::preeval, - * #VipsImage::eval and #VipsImage::posteval + * vips signals evaluation progress via the [signal@Image::preeval], + * [signal@Image::eval] and [signal@Image::posteval] * signals. Progress is signalled on the most-downstream image for which - * vips_image_set_progress() was called. + * [method@Image.set_progress] was called. */ void vips_image_set_progress(VipsImage *image, gboolean progress) @@ -1633,14 +1621,15 @@ vips_image_set_progress(VipsImage *image, gboolean progress) * vips_image_iskilled: * @image: image to test * - * If @image has been killed (see vips_image_set_kill()), set an error message, - * clear the #VipsImage.kill flag and return %TRUE. Otherwise return %FALSE. + * If @image has been killed (see [method@Image.set_kill]), set an error message, + * clear the [class@Image].kill flag and return `TRUE`. Otherwise return `FALSE`. * * Handy for loops which need to run sets of threads which can fail. * - * See also: vips_image_set_kill(). + * ::: seealso + * [method@Image.set_kill]. * - * Returns: %TRUE if @image has been killed. + * Returns: `TRUE` if @image has been killed. */ gboolean vips_image_iskilled(VipsImage *image) @@ -1675,10 +1664,11 @@ vips_image_iskilled(VipsImage *image) * @image: image to test * @kill: the kill state * - * Set the #VipsImage.kill flag on an image. Handy for stopping sets of + * Set the [class@Image].kill flag on an image. Handy for stopping sets of * threads. * - * See also: vips_image_iskilled(). + * ::: seealso + * [method@Image.iskilled]. */ void vips_image_set_kill(VipsImage *image, gboolean kill) @@ -1710,15 +1700,15 @@ vips_image_temp_name(char *name, int size) /** * vips_image_new: (constructor) * - * vips_image_new() creates a new, empty #VipsImage. + * [ctor@Image.new] creates a new, empty [class@Image]. * If you write to one of these images, vips will just attach some callbacks, * no pixels will be generated. * - * Write pixels to an image with vips_image_generate() or - * vips_image_write_line(). Write a whole image to another image with - * vips_image_write(). + * Write pixels to an image with [method@Image.generate] or + * [method@Image.write_line]. Write a whole image to another image with + * [method@Image.write]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new(void) @@ -1769,12 +1759,13 @@ vips_image_new_mode(const char *filename, const char *mode) /** * vips_image_new_memory: (skip) * - * vips_image_new_memory() creates a new #VipsImage which, when written to, will + * [ctor@Image.new_memory] creates a new [class@Image] which, when written to, will * create a memory image. * - * See also: vips_image_new(). + * ::: seealso + * [ctor@Image.new]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_memory(void) @@ -1788,12 +1779,13 @@ vips_image_new_memory(void) /** * vips_image_memory: (constructor) * - * A renamed vips_image_new_memory() ... Some gobject binding systems do not - * like more than one _new() method. + * A renamed [ctor@Image.new_memory] ... Some gobject binding systems do not + * like more than one `_new()` method. * - * See also: vips_image_new_memory(). + * ::: seealso + * [ctor@Image.new_memory]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_memory(void) @@ -1810,7 +1802,8 @@ vips_image_memory(void) * * Useful for language bindings. * - * See also: vips_filename_get_options(). + * ::: seealso + * [func@filename_get_options]. * * Returns: transfer full: just the filename component. */ @@ -1834,7 +1827,8 @@ vips_filename_get_filename(const char *vips_filename) * * Useful for language bindings. * - * See also: vips_filename_get_filename(). + * ::: seealso + * [func@filename_get_filename]. * * Returns: transfer full: just the options component. */ @@ -1852,44 +1846,43 @@ vips_filename_get_options(const char *vips_filename) /** * vips_image_new_from_file: (constructor) * @name: file to open - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * ::: tip "Optional arguments" + * * @access: hint [enum@Access] mode to loader + * * @memory: `gboolean`, force load via memory * - * * @access: hint #VipsAccess mode to loader - * * @memory: force load via memory - * - * vips_image_new_from_file() opens @name for reading. It can load files + * [ctor@Image.new_from_file] opens @name for reading. It can load files * in many image formats, including VIPS, TIFF, PNG, JPEG, FITS, Matlab, * OpenEXR, CSV, WebP, Radiance, RAW, PPM and others. * - * Load options may be appended to @filename as "[name=value,...]" or given as + * Load options may be appended to @filename as `[name=value,...]` or given as * a NULL-terminated list of name-value pairs at the end of the arguments. * Options given in the function call override options given in the filename. - * Many loaders add extra options, see vips_jpegload(), for example. + * Many loaders add extra options, see [ctor@Image.jpegload], for example. * - * vips_image_new_from_file() always returns immediately with the header + * [ctor@Image.new_from_file] always returns immediately with the header * fields filled in. No pixels are actually read until you first access them. * - * @access lets you set a #VipsAccess hint giving the expected access pattern + * @access lets you set a [enum@Access] hint giving the expected access pattern * for this file. - * #VIPS_ACCESS_RANDOM means you can fetch pixels randomly from the image. - * This is the default mode. #VIPS_ACCESS_SEQUENTIAL means you will read the - * whole image exactly once, top-to-bottom. In this mode, vips can avoid - * converting the whole image in one go, for a large memory saving. You are - * allowed to make small non-local references, so area operations like + * [enum@Vips.Access.RANDOM] means you can fetch pixels randomly from the image. + * This is the default mode. [enum@Vips.Access.SEQUENTIAL] means you will + * read the whole image exactly once, top-to-bottom. In this mode, libvips + * can avoid converting the whole image in one go, for a large memory saving. + * You are allowed to make small non-local references, so area operations like * convolution will work. * - * In #VIPS_ACCESS_RANDOM mode, small images are decompressed to memory and - * then processed from there. Large images are decompressed to temporary + * In [enum@Vips.Access.RANDOM] mode, small images are decompressed to memory + * and then processed from there. Large images are decompressed to temporary * random-access files on disc and then processed from there. * - * Set @memory to %TRUE to force loading via memory. The default is to load + * Set @memory to `TRUE` to force loading via memory. The default is to load * large random access images via temporary disc files. See - * vips_image_new_temp_file() for an + * [ctor@Image.new_temp_file] for an * explanation of how VIPS selects a location for the temporary file. * - * The disc threshold can be set with the "--vips-disc-threshold" + * The disc threshold can be set with the `--vips-disc-threshold` * command-line argument, or the `VIPS_DISC_THRESHOLD` environment variable. * The value is a simple integer, but can take a unit postfix of "k", * "m" or "g" to indicate kilobytes, megabytes or gigabytes. @@ -1897,30 +1890,30 @@ vips_filename_get_options(const char *vips_filename) * * For example: * - * |[ + * ```c * VipsImage *image = vips_image_new_from_file("fred.tif", * "page", 12, * NULL); - * ]| + * ``` * * Will open "fred.tif", reading page 12. * - * |[ - * VipsImage *image = vips_image_new_from_file("fred.jpg[shrink=2]", - * NULL); - * ]| + * ```c + * VipsImage *image = vips_image_new_from_file("fred.jpg[shrink=2]", NULL); + * ``` * - * Will open "fred.jpg", downsampling by a factor of two. + * Will open `fred.jpg`, downsampling by a factor of two. * - * Use vips_foreign_find_load() or vips_foreign_is_a() to see what format a + * Use [func@Foreign.find_load] or [func@Foreign.is_a] to see what format a * file is in and therefore what options are available. If you need more * control over the loading process, you can call loaders directly, see - * vips_jpegload(), for example. + * [ctor@Image.jpegload], for example. * - * See also: vips_foreign_find_load(), vips_foreign_is_a(), - * vips_image_write_to_file(). + * ::: seealso + * [func@Foreign.find_load], [func@Foreign.is_a], + * [method@Image.write_to_file]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_file(const char *name, ...) @@ -1958,9 +1951,10 @@ vips_image_new_from_file(const char *name, ...) * work for VIPS files in a format native to your machine. It is only for * paintbox-type applications. * - * See also: vips_draw_circle(). + * ::: seealso + * [method@Image.draw_circle]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_file_RW(const char *filename) @@ -1976,15 +1970,16 @@ vips_image_new_from_file_RW(const char *filename) * @bands: image bands (or bytes per pixel) * @offset: bytes to skip at start of file * - * This function maps the named file and returns a #VipsImage you can use to + * This function maps the named file and returns a [class@Image] you can use to * read it. * * It returns an 8-bit image with @bands bands. If the image is not 8-bit, use - * vips_copy() to transform the descriptor after loading it. + * [method@Image.copy] to transform the descriptor after loading it. * - * See also: vips_copy(), vips_rawload(), vips_image_new_from_file(). + * ::: seealso + * [method@Image.copy], [ctor@Image.rawload], [ctor@Image.new_from_file]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_file_raw(const char *filename, @@ -2020,26 +2015,27 @@ vips_image_new_from_file_raw(const char *filename, * @bands: image bands (or bytes per pixel) * @format: image format * - * This function wraps a #VipsImage around a memory area. The memory area + * This function wraps a [class@Image] around a memory area. The memory area * must be a simple array, for example RGBRGBRGB, left-to-right, - * top-to-bottom. Use vips_image_new_from_buffer() to load an area of memory + * top-to-bottom. Use [ctor@Image.new_from_buffer] to load an area of memory * containing an image in a format. * * VIPS does not take * responsibility for the area of memory, it's up to you to make sure it's - * freed when the image is closed. See for example #VipsObject::close. + * freed when the image is closed. See for example [signal@Object::close]. * * Because VIPS is "borrowing" @data from the caller, this function is * extremely dangerous. Unless you are very careful, you will get crashes or - * memory corruption. Use vips_image_new_from_memory_copy() instead if you are + * memory corruption. Use [ctor@Image.new_from_memory_copy] instead if you are * at all unsure. * - * Use vips_copy() to set other image properties. + * Use [method@Image.copy] to set other image properties. * - * See also: vips_image_new(), vips_image_write_to_memory(), - * vips_image_new_from_memory_copy(). + * ::: seealso + * [ctor@Image.new], [method@Image.write_to_memory], + * [ctor@Image.new_from_memory_copy]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_memory(const void *data, size_t size, @@ -2068,7 +2064,7 @@ vips_image_new_from_memory(const void *data, size_t size, if (size < VIPS_IMAGE_SIZEOF_IMAGE(image)) { vips_error("VipsImage", - _("memory area too small --- " + _("memory area too small -- " "should be %" G_GINT64_FORMAT " bytes, you passed %zd"), VIPS_IMAGE_SIZEOF_IMAGE(image), size); VIPS_UNREF(image); @@ -2093,13 +2089,14 @@ vips_image_new_from_memory_copy_cb(VipsImage *image, void *data_copy) * @bands: image bands (or bytes per pixel) * @format: image format * - * Like vips_image_new_from_memory(), but VIPS will make a copy of the memory + * Like [ctor@Image.new_from_memory], but VIPS will make a copy of the memory * area. This means more memory use and an extra copy operation, but is much * simpler and safer. * - * See also: vips_image_new_from_memory(). + * ::: seealso + * [ctor@Image.new_from_memory]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_memory_copy(const void *data, size_t size, @@ -2130,24 +2127,25 @@ vips_image_new_from_memory_copy(const void *data, size_t size, * @buf: (array length=len) (element-type guint8) (transfer none): image data * @len: (type gsize): length of memory buffer * @option_string: set of extra options as a string - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Loads an image from the formatted area of memory @buf, @len using the - * loader recommended by vips_foreign_find_load_buffer(). + * loader recommended by [func@Foreign.find_load_buffer]. * To load an unformatted area of memory, use - * vips_image_new_from_memory(). + * [ctor@Image.new_from_memory]. * * VIPS does not take * responsibility for the area of memory, it's up to you to make sure it's - * freed when the image is closed. See for example #VipsObject::close. + * freed when the image is closed. See for example [signal@Object::close]. * - * Load options may be given in @option_string as "[name=value,...]" or given as + * Load options may be given in @option_string as `[name=value,...]` or given as * a NULL-terminated list of name-value pairs at the end of the arguments. * Options given in the function call override options given in the filename. * - * See also: vips_image_write_to_buffer(). + * ::: seealso + * [method@Image.write_to_buffer]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_buffer(const void *buf, size_t len, @@ -2185,18 +2183,19 @@ vips_image_new_from_buffer(const void *buf, size_t len, * vips_image_new_from_source: (constructor) * @source: (transfer none): source to fetch image from * @option_string: set of extra options as a string - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Loads an image from the formatted source @input, - * loader recommended by vips_foreign_find_load_source(). + * loader recommended by [func@Foreign.find_load_source]. * - * Load options may be given in @option_string as "[name=value,...]" or given as + * Load options may be given in @option_string as `[name=value,...]` or given as * a NULL-terminated list of name-value pairs at the end of the arguments. * Options given in the function call override options given in the string. * - * See also: vips_image_write_to_target(). + * ::: seealso + * [method@Image.write_to_target]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_source(VipsSource *source, @@ -2273,15 +2272,16 @@ vips_image_new_from_source(VipsSource *source, * @height: image height * * This convenience function makes an image which is a matrix: a one-band - * #VIPS_FORMAT_DOUBLE image held in memory. + * [enum@Vips.BandFormat.DOUBLE] image held in memory. * - * Use VIPS_IMAGE_ADDR(), or VIPS_MATRIX() to address pixels in the image. + * Use [func@IMAGE_ADDR], or [func@MATRIX] to address pixels in the image. * - * Use vips_image_set_double() to set "scale" and "offset", if required. + * Use [method@Image.set_double] to set "scale" and "offset", if required. * - * See also: vips_image_new_matrixv() + * ::: seealso + * [ctor@Image.new_matrixv] * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_matrix(int width, int height) @@ -2319,13 +2319,14 @@ vips_image_new_matrix(int width, int height) * @height: image height * @...: matrix coefficients * - * As vips_image_new_matrix(), but initialise the matrix from the argument + * As [ctor@Image.new_matrix], but initialise the matrix from the argument * list. After @height should be @width * @height double constants which are * used to set the matrix elements. * - * See also: vips_image_new_matrix() + * ::: seealso + * [ctor@Image.new_matrix] * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_matrixv(int width, int height, ...) @@ -2354,9 +2355,9 @@ vips_image_new_matrixv(int width, int height, ...) * @array: (array length=size) (transfer none): array of elements * @size: (type gsize): number of elements * - * A binding-friendly version of vips_image_new_matrixv(). + * A binding-friendly version of [ctor@Image.new_matrixv]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_matrix_from_array(int width, int height, @@ -2368,7 +2369,7 @@ vips_image_new_matrix_from_array(int width, int height, if (size != width * height) { vips_error("VipsImage", - _("bad array length --- should be %d, you passed %d"), + _("bad array length -- should be %d, you passed %d"), width * height, size); return NULL; } @@ -2392,10 +2393,10 @@ vips_image_new_matrix_from_array(int width, int height, * @array: (array length=size) (transfer none): array of elements * @size: (type gsize): number of elements * - * A renamed vips_image_new_matrix_from_array(). Some gobject bindings do not + * A renamed [ctor@Image.new_matrix_from_array]. Some gobject bindings do not * like more than one _new method. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_matrix_from_array(int width, int height, @@ -2415,9 +2416,10 @@ vips_image_matrix_from_array(int width, int height, * and offset taken from @image, but with number of bands taken from @n and the * value of each band element set from @c. * - * See also: vips_image_new_from_image1() + * ::: seealso + * [ctor@Image.new_from_image1] * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_image(VipsImage *image, const double *c, int n) @@ -2469,9 +2471,10 @@ vips_image_new_from_image(VipsImage *image, const double *c, int n) * and offset taken from @image, but with one band and each pixel having the * value @c. * - * See also: vips_image_new_from_image() + * ::: seealso + * [ctor@Image.new_from_image] * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_from_image1(VipsImage *image, double c) @@ -2490,7 +2493,8 @@ vips_image_new_from_image1(VipsImage *image, double c) * * This function is clearly extremely dangerous, use with great caution. * - * See also: vips_image_new_temp_file(). + * ::: seealso + * [ctor@Image.new_temp_file]. */ void vips_image_set_delete_on_close(VipsImage *image, gboolean delete_on_close) @@ -2510,7 +2514,7 @@ vips_image_set_delete_on_close(VipsImage *image, gboolean delete_on_close) * Return the number of bytes at which we flip between open via memory and * open via disc. This defaults to 100mb, but can be changed with the * VIPS_DISC_THRESHOLD environment variable or the --vips-disc-threshold - * command-line flag. See vips_image_new_from_file(). + * command-line flag. See [ctor@Image.new_from_file]. * * Returns: disc threshold in bytes. */ @@ -2530,7 +2534,7 @@ vips_get_disc_threshold(void) threshold = 100 * 1024 * 1024; if ((env = g_getenv("VIPS_DISC_THRESHOLD")) -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED || (env = g_getenv("IM_DISC_THRESHOLD")) #endif ) @@ -2551,18 +2555,19 @@ vips_get_disc_threshold(void) * vips_image_new_temp_file: (constructor) * @format: format of file * - * Make a #VipsImage which, when written to, will create a temporary file on + * Make a [class@Image] which, when written to, will create a temporary file on * disc. The file will be automatically deleted when the image is destroyed. * @format is something like "%s.v" for a vips file. * * The file is created in the temporary directory. This is set with the * environment variable TMPDIR. If this is not set, then on Unix systems, vips - * will default to /tmp. On Windows, vips uses GetTempPath() to find the + * will default to /tmp. On Windows, vips uses `GetTempPath()` to find the * temporary directory. * - * See also: vips_image_new(). + * ::: seealso + * [ctor@Image.new]. * - * Returns: the new #VipsImage, or %NULL on error. + * Returns: the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_new_temp_file(const char *format) @@ -2615,10 +2620,11 @@ vips_image_write_gen(VipsRegion *out_region, * @image: image to write * @out: (out): write to this image * - * Write @image to @out. Use vips_image_new() and friends to create the - * #VipsImage you want to write to. + * Write @image to @out. Use [ctor@Image.new] and friends to create the + * [class@Image] you want to write to. * - * See also: vips_image_new(), vips_copy(), vips_image_write_to_file(). + * ::: seealso + * [ctor@Image.new], [method@Image.copy], [method@Image.write_to_file]. * * Returns: 0 on success, or -1 on error. */ @@ -2667,16 +2673,17 @@ vips_image_write(VipsImage *image, VipsImage *out) * vips_image_write_to_file: * @image: image to write * @name: write to this file - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Writes @in to @name using the saver recommended by - * vips_foreign_find_save(). + * [func@Foreign.find_save]. * - * Save options may be appended to @filename as "[name=value,...]" or given as + * Save options may be appended to @filename as `[name=value,...]` or given as * a NULL-terminated list of name-value pairs at the end of the arguments. * Options given in the function call override options given in the filename. * - * See also: vips_image_new_from_file(). + * ::: seealso + * [ctor@Image.new_from_file]. * * Returns: 0 on success, or -1 on error. */ @@ -2731,20 +2738,21 @@ vips_image_write_to_file(VipsImage *image, const char *name, ...) * @suffix: format to write * @buf: (array length=size) (element-type guint8) (transfer full): return buffer start here * @size: (type gsize): return buffer length here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Writes @in to a memory buffer in a format specified by @suffix. * - * Save options may be appended to @suffix as "[name=value,...]" or given as + * Save options may be appended to @suffix as `[name=value,...]` or given as * a NULL-terminated list of name-value pairs at the end of the arguments. * Options given in the function call override options given in the filename. * * Currently only TIFF, JPEG and PNG formats are supported. * * You can call the various save operations directly if you wish, see - * vips_jpegsave_buffer(), for example. + * [method@Image.jpegsave_buffer], for example. * - * See also: vips_image_write_to_memory(), vips_image_new_from_buffer(). + * ::: seealso + * [method@Image.write_to_memory], [ctor@Image.new_from_buffer]. * * Returns: 0 on success, -1 on error */ @@ -2785,9 +2793,7 @@ vips_image_write_to_buffer(VipsImage *in, g_object_get(target, "blob", &blob, NULL); VIPS_UNREF(target); } - else if ((operation_name = - vips_foreign_find_save_buffer(filename))) { - + else if ((operation_name = vips_foreign_find_save_buffer(filename))) { va_start(ap, size); result = vips_call_split_option_string(operation_name, option_string, ap, in, &blob); @@ -2822,18 +2828,19 @@ vips_image_write_to_buffer(VipsImage *in, * @in: image to write * @suffix: format to write * @target: target to write to - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Writes @in to @output in format @suffix. * - * Save options may be appended to @suffix as "[name=value,...]" or given as + * Save options may be appended to @suffix as `[name=value,...]` or given as * a NULL-terminated list of name-value pairs at the end of the arguments. * Options given in the function call override options given in the filename. * * You can call the various save operations directly if you wish, see - * vips_jpegsave_target(), for example. + * [method@Image.jpegsave_target], for example. * - * See also: vips_image_write_to_file(). + * ::: seealso + * [method@Image.write_to_file]. * * Returns: 0 on success, -1 on error */ @@ -2869,9 +2876,10 @@ vips_image_write_to_target(VipsImage *in, * * Writes @in to memory as a simple, unformatted C-style array. * - * The caller is responsible for freeing this memory with g_free(). + * The caller is responsible for freeing this memory with [func@GLib.free]. * - * See also: vips_image_write_to_buffer(). + * ::: seealso + * [method@Image.write_to_buffer]. * * Returns: (array length=size) (element-type guint8) (transfer full): return buffer start here */ @@ -2885,9 +2893,9 @@ vips_image_write_to_memory(VipsImage *in, size_t *size_out) size = VIPS_IMAGE_SIZEOF_IMAGE(in); if (!(buf = g_try_malloc(size))) { vips_error("vips_image_write_to_memory", - _("out of memory --- size == %dMB"), + _("out of memory -- size == %dMB"), (int) (size / (1024.0 * 1024.0))); - g_warning(_("out of memory --- size == %dMB"), + g_warning(_("out of memory -- size == %dMB"), (int) (size / (1024.0 * 1024.0))); return NULL; } @@ -2913,12 +2921,13 @@ vips_image_write_to_memory(VipsImage *in, size_t *size_out) * @out: (out): write to this image * * A convenience function to unpack to a format that we can compute with. - * @out.coding is always #VIPS_CODING_NONE. + * @out.coding is always [enum@Vips.Coding.NONE]. * - * This unpacks LABQ to plain LAB. Use vips_LabQ2LabS() for a bit more speed - * if you need it. + * This unpacks LABQ to plain LAB. Use [method@Image.LabQ2LabS] for a bit + * more speed if you need it. * - * See also: vips_image_encode(), vips_LabQ2Lab(), vips_rad2float(). + * ::: seealso + * [method@Image.encode], [method@Image.LabQ2Lab], [method@Image.rad2float]. * * Returns: 0 on success, or -1 on error. */ @@ -2952,7 +2961,8 @@ vips_image_decode(VipsImage *in, VipsImage **out) * We often need to know what an image will decode to without actually * decoding it, for example, in arg checking. * - * See also: vips_image_decode(). + * ::: seealso + * [method@Image.decode]. */ int vips_image_decode_predict(VipsImage *in, @@ -2989,9 +2999,10 @@ vips_image_decode_predict(VipsImage *in, * @coding: coding to apply * * A convenience function to pack to a coding. The inverse of - * vips_image_decode(). + * [method@Image.decode]. * - * See also: vips_image_decode(). + * ::: seealso + * [method@Image.decode]. * * Returns: 0 on success, or -1 on error. */ @@ -3018,7 +3029,7 @@ vips_image_encode(VipsImage *in, VipsImage **out, VipsCoding coding) * vips_image_isMSBfirst: * @image: image to test * - * Return %TRUE if @image is in most-significant- + * Return `TRUE` if @image is in most-significant- * byte first form. This is the byte order used on the SPARC * architecture and others. */ @@ -3035,7 +3046,7 @@ vips_image_isMSBfirst(VipsImage *image) * vips_image_isfile: * @image: image to test * - * Return %TRUE if @image represents a file on disc in some way. + * Return `TRUE` if @image represents a file on disc in some way. */ gboolean vips_image_isfile(VipsImage *image) @@ -3063,7 +3074,7 @@ vips_image_isfile(VipsImage *image) * vips_image_ispartial: * @image: image to test * - * Return %TRUE if @im represents a partial image (a delayed calculation). + * Return `TRUE` if @im represents a partial image (a delayed calculation). */ gboolean vips_image_ispartial(VipsImage *image) @@ -3079,10 +3090,10 @@ vips_image_ispartial(VipsImage *image) * @image: image to check * * Look at an image's interpretation and see if it has extra alpha bands. For - * example, a 4-band #VIPS_INTERPRETATION_sRGB would, but a six-band - * #VIPS_INTERPRETATION_MULTIBAND would not. + * example, a 4-band [enum@Vips.Interpretation.sRGB] would, but a six-band + * [enum@Vips.Interpretation.MULTIBAND] would not. * - * Return %TRUE if @image has an alpha channel. + * Return `TRUE` if @image has an alpha channel. */ gboolean vips_image_hasalpha(VipsImage *image) @@ -3128,8 +3139,8 @@ vips_image_hasalpha(VipsImage *image) * Call this after setting header fields (width, height, and so on) to * allocate resources ready for writing. * - * Normally this function is called for you by vips_image_generate() or - * vips_image_write_line(). You will need to call it yourself if you plan to + * Normally this function is called for you by [method@Image.generate] or + * [method@Image.write_line]. You will need to call it yourself if you plan to * write directly to the ->data member of a memory image. * * Returns: 0 on success, or -1 on error. @@ -3192,10 +3203,11 @@ vips_image_write_prepare(VipsImage *image) * @linebuffer: scanline of pixels * * Write a line of pixels to an image. This function must be called repeatedly - * with @ypos increasing from 0 to #VipsImage::height . - * @linebuffer must be VIPS_IMAGE_SIZEOF_LINE() bytes long. + * with @ypos increasing from 0 to [property@Image:height]. + * @linebuffer must be [func@IMAGE_SIZEOF_LINE] bytes long. * - * See also: vips_image_generate(). + * ::: seealso + * [method@Image.generate]. * * Returns: 0 on success, or -1 on error. */ @@ -3241,7 +3253,7 @@ vips_image_write_line(VipsImage *image, int ypos, VipsPel *linebuffer) /* Trigger evaluation callbacks for this image. */ - vips_image_eval(image, ypos * image->Xsize); + vips_image_eval(image, (guint64) ypos * image->Xsize); if (vips_image_iskilled(image)) return -1; @@ -3331,17 +3343,18 @@ vips_image_rewind_output(VipsImage *image) * Call this before using the draw operations to make sure you have a * memory image that can be modified. * - * vips_copy() adds a null "copy" node to a pipeline. Use that + * [method@Image.copy] adds a null "copy" node to a pipeline. Use that * instead if you want to change metadata and not pixels. * - * This operation is thread-safe, unlike vips_image_wio_input(). + * This operation is thread-safe, unlike [method@Image.wio_input]. * * If you are sure that @image is not shared with another thread (perhaps you - * have made it yourself), use vips_image_wio_input() instead. + * have made it yourself), use [method@Image.wio_input] instead. * - * See also: vips_image_wio_input(). + * ::: seealso + * [method@Image.wio_input]. * - * Returns: (transfer full): the new #VipsImage, or %NULL on error. + * Returns: (transfer full): the new [class@Image], or `NULL` on error. */ VipsImage * vips_image_copy_memory(VipsImage *image) @@ -3382,18 +3395,19 @@ vips_image_copy_memory(VipsImage *image) * vips_image_wio_input: * @image: image to transform * - * Check that an image is readable via the VIPS_IMAGE_ADDR() macro, that is, + * Check that an image is readable via the [func@IMAGE_ADDR] macro, that is, * that the entire image is in memory and all pixels can be read with - * VIPS_IMAGE_ADDR(). If it - * isn't, try to transform it so that VIPS_IMAGE_ADDR() can work. + * [func@IMAGE_ADDR]. If it + * isn't, try to transform it so that [func@IMAGE_ADDR] can work. * * Since this function modifies @image, it is not thread-safe. Only call it on * images which you are sure have not been shared with another thread. If the * image might have been shared, use the less efficient - * vips_image_copy_memory() instead. + * [method@Image.copy_memory] instead. * - * See also: vips_image_copy_memory(), vips_image_pio_input(), - * vips_image_inplace(), VIPS_IMAGE_ADDR(). + * ::: seealso + * [method@Image.copy_memory], [method@Image.pio_input], + * [method@Image.inplace], [func@IMAGE_ADDR]. * * Returns: 0 on success, or -1 on error. */ @@ -3557,9 +3571,9 @@ vips__image_wio_output(VipsImage *image) * vips_image_inplace: * @image: image to make read-write * - * Gets @image ready for an in-place operation, such as vips_draw_circle(). - * After calling this function you can both read and write the image with - * VIPS_IMAGE_ADDR(). + * Gets @image ready for an in-place operation, such as + * [method@Image.draw_circle]. After calling this function you can both read + * and write the image with [func@IMAGE_ADDR]. * * This method is called for you by the base class of the draw operations, * there's no need to call it yourself. @@ -3569,7 +3583,8 @@ vips__image_wio_output(VipsImage *image) * All in-place operations are inherently not thread-safe, so you need to take * great care in any case. * - * See also: vips_draw_circle(), vips_image_wio_input(). + * ::: seealso + * [method@Image.draw_circle], [method@Image.wio_input]. * * Returns: 0 on success, or -1 on error. */ @@ -3617,11 +3632,12 @@ vips_image_inplace(VipsImage *image) * vips_image_pio_input: * @image: image to check * - * Check that an image is readable with vips_region_prepare() and friends. - * If it isn't, try to transform the image so that vips_region_prepare() can + * Check that an image is readable with [method@Region.prepare] and friends. + * If it isn't, try to transform the image so that [method@Region.prepare] can * work. * - * See also: vips_image_pio_output(), vips_region_prepare(). + * ::: seealso + * [method@Image.pio_output], [method@Region.prepare]. * * Returns: 0 on success, or -1 on error. */ @@ -3689,10 +3705,11 @@ vips_image_pio_input(VipsImage *image) * vips_image_pio_output: * @image: image to check * - * Check that an image is writeable with vips_image_generate(). If it isn't, - * try to transform the image so that vips_image_generate() can work. + * Check that an image is writeable with [method@Image.generate]. If it isn't, + * try to transform the image so that [method@Image.generate] can work. * - * See also: vips_image_pio_input(). + * ::: seealso + * [method@Image.pio_input]. * * Returns: 0 on success, or -1 on error. */ @@ -3740,7 +3757,7 @@ vips_image_pio_output(VipsImage *image) * vips_band_format_isint: * @format: format to test * - * Return %TRUE if @format is one of the integer types. + * Return `TRUE` if @format is one of the integer types. */ gboolean vips_band_format_isint(VipsBandFormat format) @@ -3770,7 +3787,7 @@ vips_band_format_isint(VipsBandFormat format) * vips_band_format_isuint: * @format: format to test * - * Return %TRUE if @format is one of the unsigned integer types. + * Return `TRUE` if @format is one of the unsigned integer types. */ gboolean vips_band_format_isuint(VipsBandFormat format) @@ -3800,7 +3817,7 @@ vips_band_format_isuint(VipsBandFormat format) * vips_band_format_is8bit: * @format: format to test * - * Return %TRUE if @format is uchar or schar. + * Return `TRUE` if @format is uchar or schar. */ gboolean vips_band_format_is8bit(VipsBandFormat format) @@ -3830,7 +3847,7 @@ vips_band_format_is8bit(VipsBandFormat format) * vips_band_format_isfloat: * @format: format to test * - * Return %TRUE if @format is one of the float types. + * Return `TRUE` if @format is one of the float types. */ gboolean vips_band_format_isfloat(VipsBandFormat format) @@ -3860,7 +3877,7 @@ vips_band_format_isfloat(VipsBandFormat format) * vips_band_format_iscomplex: * @format: format to test * - * Return %TRUE if @fmt is one of the complex types. + * Return `TRUE` if @fmt is one of the complex types. */ gboolean vips_band_format_iscomplex(VipsBandFormat format) diff --git a/libvips/iofuncs/init.c b/libvips/iofuncs/init.c index 5df713b8c6..7a0cb913ed 100644 --- a/libvips/iofuncs/init.c +++ b/libvips/iofuncs/init.c @@ -97,7 +97,6 @@ #define VIPS_DISABLE_DEPRECATION_WARNINGS #include #include -#include #include /* abort() on the first warning or error. @@ -107,7 +106,7 @@ int vips__fatal = 0; /* Use in various small places where we need a mutex and it's not worth * making a private one. */ -GMutex *vips__global_lock = NULL; +GMutex vips__global_lock; /* A debugging timer, zero at library init. */ @@ -168,11 +167,11 @@ vips_max_coord_get(void) /** * vips_get_argv0: * - * See also: VIPS_INIT(). + * ::: seealso + * [func@INIT]. * * Returns: (transfer none): a pointer to an internal copy of the - * argv0 string passed to - * VIPS_INIT(). Do not free this value + * argv0 string passed to [func@INIT]. Do not free this value */ const char * vips_get_argv0(void) @@ -183,9 +182,10 @@ vips_get_argv0(void) /** * vips_get_prgname: * - * Return the program name. This can be useful for the user tio see,. + * Return the program name. * - * See also: VIPS_INIT(). + * ::: seealso + * [func@INIT]. * * Returns: (transfer none): a pointer to an internal copy of the program * name. Do not free this value @@ -205,9 +205,9 @@ vips_get_prgname(void) * VIPS_INIT: * @ARGV0: name of application * - * VIPS_INIT() starts up the world of VIPS. You should call this on + * [func@INIT] starts up the world of VIPS. You should call this on * program startup before using any other VIPS operations. If you do not call - * VIPS_INIT(), VIPS will call it for you when you use your first VIPS + * [func@INIT], VIPS will call it for you when you use your first VIPS * operation, but it may not be able to get hold of @ARGV0 and VIPS may * therefore be unable to find its data files. It is much better to call * this macro yourself. @@ -216,23 +216,23 @@ vips_get_prgname(void) * relocated. If you don't need a relocatable package, you can just pass `""` * and it'll be fine. * - * Additionally, VIPS_INIT() can be run from any thread, but it must not be + * Additionally, [func@INIT] can be run from any thread, but it must not be * called from more than one thread at the same time. This is much easier to * guarantee if you call it yourself. * - * VIPS_INIT() is a macro, since it tries to check ABI compatibility - * between the caller and the library. You can also call vips_init(), the + * [func@INIT] is a macro, since it tries to check ABI compatibility + * between the caller and the library. You can also call [func@init], the * non-macro version, if macros are not available to you. * - * You may call VIPS_INIT() many times and vips_shutdown() many times, but you - * must not call VIPS_INIT() after vips_shutdown(). In other words, you cannot + * You may call [func@INIT] many times and [func@shutdown] many times, but you + * must not call [func@INIT] after [func@shutdown]. In other words, you cannot * stop and restart vips. * * Use the environment variable `VIPS_MIN_STACK_SIZE` to set the minimum stack * size. For example, `2m` for a minimum of two megabytes of stack. This can * be important for systems like musl where the default stack is very small. * - * VIPS_INIT() does approximately the following: + * [func@INIT] does approximately the following: * * + checks that the libvips your program is expecting is * binary-compatible with the vips library you're running against @@ -243,16 +243,16 @@ vips_get_prgname(void) * and the threading system, if necessary * * + guesses where the VIPS data files are and sets up - * internationalisation --- see vips_guess_prefix() + * internationalisation -- see [func@guess_prefix] * - * + creates the main vips types, including #VipsImage and friends + * + creates the main vips types, including [class@Image] and friends * * + loads any plugins from $libdir/vips-x.y/, where x and y are the * major and minor version numbers for this VIPS. * * Example: * - * |[ + * ```c * int main(int argc, char **argv) * { * if (VIPS_INIT(argv[0])) @@ -262,10 +262,11 @@ vips_get_prgname(void) * * return 0; * } - * ]| + * ``` * - * See also: vips_shutdown(), vips_add_option_entries(), vips_version(), - * vips_guess_prefix(), vips_guess_libdir(). + * ::: seealso + * [func@shutdown], [func@add_option_entries], [func@version], + * [func@guess_prefix], [func@guess_libdir]. * * Returns: 0 on success, -1 otherwise */ @@ -287,7 +288,7 @@ vips_load_plugins(const char *fmt, ...) return; va_start(ap, fmt); - (void) g_vsnprintf(dir_name, VIPS_PATH_MAX - 1, fmt, ap); + (void) g_vsnprintf(dir_name, VIPS_PATH_MAX, fmt, ap); va_end(ap); g_info("searching \"%s\"", dir_name); @@ -301,7 +302,7 @@ vips_load_plugins(const char *fmt, ...) char path[VIPS_PATH_MAX]; GModule *module; - g_snprintf(path, VIPS_PATH_MAX - 1, + g_snprintf(path, VIPS_PATH_MAX, "%s" G_DIR_SEPARATOR_S "%s", dir_name, name); g_info("loading \"%s\"", path); @@ -363,24 +364,17 @@ set_stacksize(guint64 size) #endif /*HAVE_PTHREAD_DEFAULT_NP*/ } +/* Equivalent to setting the `G_MESSAGES_DEBUG=VIPS` environment variable. + */ static void vips_verbose(void) { - const char *old; - - old = g_getenv("G_MESSAGES_DEBUG"); - - if (!old) - g_setenv("G_MESSAGES_DEBUG", G_LOG_DOMAIN, TRUE); - else if (!g_str_equal(old, "all") && - !g_strrstr(old, G_LOG_DOMAIN)) { - char *new; - - new = g_strconcat(old, " ", G_LOG_DOMAIN, NULL); - g_setenv("G_MESSAGES_DEBUG", new, TRUE); - - g_free(new); - } +#if GLIB_CHECK_VERSION(2, 80, 0) + const char *domains[] = { G_LOG_DOMAIN, NULL }; + g_log_writer_default_set_debug_domains(domains); +#else + g_setenv("G_MESSAGES_DEBUG", G_LOG_DOMAIN, TRUE); +#endif } static int @@ -397,6 +391,9 @@ vips_leak(void) n_leaks += vips_tracked_get_allocs(); n_leaks += vips_tracked_get_mem(); n_leaks += vips_tracked_get_files(); +#if defined(HAVE_OPENSLIDE) && !defined(OPENSLIDE_MODULE) + n_leaks += vips__openslideconnection_leak(); +#endif /*defined(HAVE_OPENSLIDE) && !defined(OPENSLIDE_MODULE)*/ if (vips_tracked_get_allocs() || vips_tracked_get_mem() || @@ -412,8 +409,7 @@ vips_leak(void) vips_buf_appends(&buf, "\n"); if (strlen(vips_error_buffer()) > 0) { - vips_buf_appendf(&buf, "error buffer: %s", - vips_error_buffer()); + vips_buf_appendf(&buf, "error buffer: %s", vips_error_buffer()); n_leaks += strlen(vips_error_buffer()); } @@ -432,12 +428,13 @@ vips_leak(void) * vips_init: * @argv0: name of application * - * This function starts up libvips, see VIPS_INIT(). + * This function starts up libvips, see [func@INIT]. * * This function is for bindings which need to start up vips. C programs - * should use the VIPS_INIT() macro, which does some extra checks. + * should use the [func@INIT] macro, which does some extra checks. * - * See also: VIPS_INIT(). + * ::: seealso + * [func@INIT]. * * Returns: 0 on success, -1 otherwise */ @@ -488,7 +485,7 @@ vips_init(const char *argv0) (void) set_stacksize(min_stack_size); if (g_getenv("VIPS_INFO") -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED || g_getenv("IM_INFO") #endif ) @@ -517,10 +514,6 @@ vips_init(const char *argv0) vips__thread_init(); vips__threadpool_init(); vips__buffer_init(); - vips__meta_init(); - - if (!vips__global_lock) - vips__global_lock = vips_g_mutex_new(); if (!vips__global_timer) vips__global_timer = g_timer_new(); @@ -575,7 +568,7 @@ vips_init(const char *argv0) vips__meta_init_types(); vips__interpolate_init(); -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED im__format_init(); #endif @@ -589,7 +582,7 @@ vips_init(const char *argv0) /* Start up packages. */ - (void) vips_system_get_type(); + vips_system_get_type(); vips_arithmetic_operation_init(); vips_conversion_operation_init(); vips_create_operation_init(); @@ -615,7 +608,7 @@ vips_init(const char *argv0) vips_load_plugins("%s/vips-modules-%d.%d", libdir, VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION); -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED /* We had vips8 plugins for a while. */ vips_load_plugins("%s/vips-plugins-%d.%d", @@ -657,7 +650,7 @@ vips_init(const char *argv0) * env var hack as a workaround. */ if (g_getenv("VIPS_WARNING") -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED || g_getenv("IM_WARNING") #endif ) @@ -695,8 +688,8 @@ vips_check_init(void) * Free any thread-private data and flush any profiling information. * * This function needs to be called when a thread that has been using vips - * exits. It is called for you by vips_shutdown() and for any threads created - * within the #VipsThreadPool. + * exits. It is called for you by [func@shutdown] and for any threads created + * within the thread pool. * * You will need to call it from threads created in * other ways or there will be memory leaks. If you do not call it, vips @@ -718,15 +711,16 @@ vips_thread_shutdown(void) * Call this to drop caches, close plugins, terminate background threads, and * finalize any internal library testing. * - * vips_shutdown() is optional. If you don't call it, your platform will + * [func@shutdown] is optional. If you don't call it, your platform will * clean up for you. The only negative consequences are that the leak checker * and the profiler will not work. * - * You may call VIPS_INIT() many times and vips_shutdown() many times, but you - * must not call VIPS_INIT() after vips_shutdown(). In other words, you cannot + * You may call [func@INIT] many times and [func@shutdown] many times, but you + * must not call [func@INIT] after [func@shutdown]. In other words, you cannot * stop and restart libvips. * - * See also: vips_profile_set(), vips_leak_set(). + * ::: seealso + * [func@profile_set], [func@leak_set]. */ void vips_shutdown(void) @@ -737,7 +731,7 @@ vips_shutdown(void) vips_cache_drop_all(); -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED im_close_plugins(); #endif @@ -756,10 +750,6 @@ vips_shutdown(void) vips__thread_profile_stop(); vips__threadpool_shutdown(); - /* Don't free vips__global_lock -- we want to be able to use - * vips_error_buffer() after vips_shutdown(), since vips_leak() can - * call it. - */ VIPS_FREE(vips__argv0); VIPS_FREE(vips__prgname); VIPS_FREEF(g_timer_destroy, vips__global_timer); @@ -932,9 +922,11 @@ static GOptionEntry option_entries[] = { * vips_add_option_entries: * @option_group: group to add to * - * Add the standard vips %GOptionEntry to a %GOptionGroup. + * Add the standard vips [struct@GLib.OptionEntry] to a + * [struct@GLib.OptionGroup]. * - * See also: g_option_group_new(). + * ::: seealso + * [ctor@GLib.OptionGroup.new]. */ void vips_add_option_entries(GOptionGroup *option_group) @@ -1143,17 +1135,18 @@ guess_prefix(const char *argv0, const char *name) * @argv0: program name (typically argv[0]) * @env_name: save prefix in this environment variable * - * vips_guess_prefix() tries to guess the install directory. You should pass + * [func@guess_prefix] tries to guess the install directory. You should pass * in the value of argv[0] (the name your program was run as) as a clue to * help it out, plus the name of the environment variable you let the user * override your package install area with (eg. "VIPSHOME"). * - * On success, vips_guess_prefix() returns the prefix it discovered, and as a + * On success, [func@guess_prefix] returns the prefix it discovered, and as a * side effect, sets the environment variable (if it's not set). * * Don't free the return string! * - * See also: vips_guess_libdir(). + * ::: seealso + * [func@guess_libdir]. * * Returns: (transfer none): the install prefix as a static string, do not free. */ @@ -1189,18 +1182,19 @@ vips_guess_prefix(const char *argv0, const char *env_name) * @argv0: program name (typically argv[0]) * @env_name: save prefix in this environment variable * - * vips_guess_libdir() tries to guess the install directory (usually the + * [func@guess_libdir] tries to guess the install directory (usually the * configure libdir, or $prefix/lib). You should pass * in the value of argv[0] (the name your program was run as) as a clue to * help it out, plus the name of the environment variable you let the user * override your package install area with (eg. "VIPSHOME"). * - * On success, vips_guess_libdir() returns the libdir it discovered, and as a + * On success, [func@guess_libdir] returns the libdir it discovered, and as a * side effect, sets the prefix environment variable (if it's not set). * * Don't free the return string! * - * See also: vips_guess_prefix(). + * ::: seealso + * [func@guess_prefix]. * * Returns: (transfer none): the libdir as a static string, do not free. */ @@ -1291,8 +1285,8 @@ vips_version(int flag) * vips_leak_set: * @leak: turn leak checking on or off * - * Turn on or off vips leak checking. See also --vips-leak, - * vips_add_option_entries() and the `VIPS_LEAK` environment variable. + * Turn on or off vips leak checking. See also `--vips-leak`, + * [func@add_option_entries] and the `VIPS_LEAK` environment variable. * * You should call this very early in your program. */ @@ -1320,9 +1314,9 @@ vips_block_untrusted_set_operation(VipsOperationClass *class, gboolean *state) * * Set the block state on all untrusted operations. * - * |[ + * ```c * vips_block_untrusted_set(TRUE); - * ]| + * ``` * * Will block all untrusted operations from running. * @@ -1330,7 +1324,7 @@ vips_block_untrusted_set_operation(VipsOperationClass *class, gboolean *state) * operations are marked as untrusted. * * Set the environment variable `VIPS_BLOCK_UNTRUSTED` to block all untrusted - * operations on vips_init(). + * operations on [func@init]. */ void vips_block_untrusted_set(gboolean state) diff --git a/libvips/iofuncs/memory.c b/libvips/iofuncs/memory.c index ac9e517e6f..6e1a17cfaf 100644 --- a/libvips/iofuncs/memory.c +++ b/libvips/iofuncs/memory.c @@ -16,7 +16,7 @@ * 20/10/09 * - gtkdoc comment * 6/11/09 - * - im_malloc()/im_free() now call g_try_malloc()/g_free() ... removes + * - im_malloc()/im_free() now call g_try_malloc/g_free() ... removes * confusion over whether to use im_free() or g_free() for things like * im_header_string() * 21/9/11 @@ -74,29 +74,6 @@ #endif #include -#include - -/** - * SECTION: memory - * @short_description: memory utilities - * @stability: Stable - * @include: vips/vips.h - * - * These functions cover two main areas. - * - * First, some simple utility functions over the underlying - * g_malloc()/g_free() functions. Memory allocated and freeded using these - * functions is interchangeable with any other glib library. - * - * Second, a pair of functions, vips_tracked_malloc() and vips_tracked_free(), - * which are NOT compatible. If you g_free() memory that has been allocated - * with vips_tracked_malloc() you will see crashes. - * - * The tracked functions are - * only suitable for large allocations internal to the library, for example - * pixel buffers. libvips watches the total amount of live tracked memory and - * uses this information to decide when to trim caches. - */ /* g_assert_not_reached() on memory errors. #define DEBUG @@ -115,37 +92,39 @@ static int vips_tracked_allocs = 0; static size_t vips_tracked_mem = 0; static int vips_tracked_files = 0; static size_t vips_tracked_mem_highwater = 0; -static GMutex *vips_tracked_mutex = NULL; +static GMutex vips_tracked_mutex; /** * VIPS_NEW: - * @OBJ: allocate memory local to @OBJ, or %NULL for no auto-free + * @OBJ: allocate memory local to @OBJ, or `NULL` for no auto-free * @T: type of thing to allocate * * Allocate memory for a thing of type @T. The memory is not * cleared. * - * This macro cannot fail. See vips_tracked_malloc() if you are + * This macro cannot fail. See [func@tracked_malloc] if you are * allocating large amounts of memory. * - * See also: vips_malloc(). + * ::: seealso + * [func@malloc]. * * Returns: A pointer of type @T *. */ /** * VIPS_ARRAY: - * @OBJ: allocate memory local to @OBJ, or %NULL for no auto-free + * @OBJ: allocate memory local to @OBJ, or `NULL` for no auto-free * @N: number of @T 's to allocate * @T: type of thing to allocate * * Allocate memory for an array of objects of type @T. The memory is not * cleared. * - * This macro cannot fail. See vips_tracked_malloc() if you are + * This macro cannot fail. See [func@tracked_malloc] if you are * allocating large amounts of memory. * - * See also: vips_malloc(). + * ::: seealso + * [func@malloc]. * * Returns: A pointer of type @T *. */ @@ -158,17 +137,18 @@ vips_malloc_cb(VipsObject *object, char *buf) /** * vips_malloc: - * @object: (nullable): allocate memory local to this #VipsObject, or %NULL + * @object: (nullable): allocate memory local to this [class@Object], or `NULL` * @size: number of bytes to allocate * - * g_malloc() local to @object, that is, the memory will be automatically - * freed for you when the object is closed. If @object is %NULL, you need to - * free the memory explicitly with g_free(). + * [func@GLib.malloc] local to @object, that is, the memory will be automatically + * freed for you when the object is closed. If @object is `NULL`, you need to + * free the memory explicitly with [func@GLib.free]. * - * This function cannot fail. See vips_tracked_malloc() if you are + * This function cannot fail. See [func@tracked_malloc] if you are * allocating large amounts of memory. * - * See also: vips_tracked_malloc(). + * ::: seealso + * [func@tracked_malloc]. * * Returns: (transfer full): a pointer to the allocated memory. */ @@ -190,16 +170,17 @@ vips_malloc(VipsObject *object, size_t size) /** * vips_strdup: - * @object: (nullable): allocate memory local to this #VipsObject, or %NULL + * @object: (nullable): allocate memory local to this [class@Object], or `NULL` * @str: string to copy * - * g_strdup() a string. When @object is freed, the string will be freed for - * you. If @object is %NULL, you need to - * free the memory yourself with g_free(). + * [func@GLib.strdup] a string. When @object is freed, the string will be freed for + * you. If @object is `NULL`, you need to + * free the memory yourself with [func@GLib.free]. * * This function cannot fail. * - * See also: vips_malloc(). + * ::: seealso + * [func@malloc]. * * Returns: (transfer full): a pointer to the allocated memory */ @@ -224,10 +205,11 @@ vips_strdup(VipsObject *object, const char *str) * @s: (transfer full): memory to free * * Only use it to free memory that was - * previously allocated with vips_tracked_malloc() - * with a %NULL first argument. + * previously allocated with [func@tracked_malloc] + * with a `NULL` first argument. * - * See also: vips_tracked_malloc(). + * ::: seealso + * [func@tracked_malloc]. */ void vips_tracked_free(void *s) @@ -238,21 +220,21 @@ vips_tracked_free(void *s) void *start = (void *) ((char *) s - 16); size_t size = *((size_t *) start); - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); #ifdef DEBUG_VERBOSE_MEM printf("vips_tracked_free: %p, %zd bytes\n", s, size); #endif /*DEBUG_VERBOSE_MEM*/ if (vips_tracked_allocs <= 0) - g_warning("%s", _("vips_free: too many frees")); + g_warning("vips_free: too many frees"); if (vips_tracked_mem < size) - g_warning("%s", _("vips_free: too much free")); + g_warning("vips_free: too much free"); vips_tracked_mem -= size; vips_tracked_allocs -= 1; - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); g_free(start); @@ -264,10 +246,11 @@ vips_tracked_free(void *s) * @s: (transfer full): memory to free * * Only use it to free memory that was - * previously allocated with vips_tracked_aligned_alloc() - * with a %NULL first argument. + * previously allocated with [func@tracked_aligned_alloc] + * with a `NULL` first argument. * - * See also: vips_tracked_aligned_alloc(). + * ::: seealso + * [func@tracked_aligned_alloc]. */ void vips_tracked_aligned_free(void *s) @@ -275,21 +258,21 @@ vips_tracked_aligned_free(void *s) void *start = (size_t *) s - 1; size_t size = *((size_t *) start); - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); #ifdef DEBUG_VERBOSE printf("vips_tracked_aligned_free: %p, %zd bytes\n", s, size); #endif /*DEBUG_VERBOSE*/ if (vips_tracked_allocs <= 0) - g_warning("%s", _("vips_free: too many frees")); + g_warning("vips_free: too many frees"); if (vips_tracked_mem < size) - g_warning("%s", _("vips_free: too much free")); + g_warning("vips_free: too much free"); vips_tracked_mem -= size; vips_tracked_allocs -= 1; - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); #ifdef HAVE__ALIGNED_MALLOC _aligned_free(start); @@ -300,46 +283,28 @@ vips_tracked_aligned_free(void *s) VIPS_GATE_FREE(size); } -static void * -vips_tracked_init_mutex(void *data) -{ - vips_tracked_mutex = vips_g_mutex_new(); - - return NULL; -} - -static void -vips_tracked_init(void) -{ - static GOnce vips_tracked_once = G_ONCE_INIT; - - VIPS_ONCE(&vips_tracked_once, - vips_tracked_init_mutex, NULL); -} - /** * vips_tracked_malloc: * @size: number of bytes to allocate * - * Allocate an area of memory that will be tracked by vips_tracked_get_mem() + * Allocate an area of memory that will be tracked by [func@tracked_get_mem] * and friends. * - * If allocation fails, vips_tracked_malloc() returns %NULL and + * If allocation fails, [func@tracked_malloc] returns `NULL` and * sets an error message. * - * You must only free the memory returned with vips_tracked_free(). + * You must only free the memory returned with [func@tracked_free]. * - * See also: vips_tracked_free(), vips_malloc(). + * ::: seealso + * [func@tracked_free], [func@malloc]. * - * Returns: (transfer full): a pointer to the allocated memory, or %NULL on error. + * Returns: (transfer full): a pointer to the allocated memory, or `NULL` on error. */ void * vips_tracked_malloc(size_t size) { void *buf; - vips_tracked_init(); - /* Need an extra sizeof(size_t) bytes to track * size of this block. Ask for an extra 16 to make sure we don't break * alignment rules. @@ -352,15 +317,15 @@ vips_tracked_malloc(size_t size) #endif /*DEBUG*/ vips_error("vips_tracked", - _("out of memory --- size == %dMB"), + _("out of memory -- size == %dMB"), (int) (size / (1024.0 * 1024.0))); - g_warning(_("out of memory --- size == %dMB"), + g_warning(_("out of memory -- size == %dMB"), (int) (size / (1024.0 * 1024.0))); return NULL; } - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); *((size_t *) buf) = size; buf = (void *) ((char *) buf + 16); @@ -374,7 +339,7 @@ vips_tracked_malloc(size_t size) printf("vips_tracked_malloc: %p, %zd bytes\n", buf, size); #endif /*DEBUG_VERBOSE_MEM*/ - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); VIPS_GATE_MALLOC(size); @@ -387,25 +352,24 @@ vips_tracked_malloc(size_t size) * @align: specifies the alignment * * Allocate an area of memory aligned on a boundary specified - * by @align that will be tracked by vips_tracked_get_mem() + * by @align that will be tracked by [func@tracked_get_mem] * and friends. * - * If allocation fails, vips_tracked_aligned_alloc() returns %NULL + * If allocation fails, [func@tracked_aligned_alloc] returns `NULL` * and sets an error message. * - * You must only free the memory returned with vips_tracked_aligned_free(). + * You must only free the memory returned with [func@tracked_aligned_free]. * - * See also: vips_tracked_malloc(), vips_tracked_aligned_free(), vips_malloc(). + * ::: seealso + * [func@tracked_malloc], [func@tracked_aligned_free], [func@malloc]. * - * Returns: (transfer full): a pointer to the allocated memory, or %NULL on error. + * Returns: (transfer full): a pointer to the allocated memory, or `NULL` on error. */ void * vips_tracked_aligned_alloc(size_t size, size_t align) { void *buf; - vips_tracked_init(); - g_assert(!(align & (align - 1))); /* Need an extra sizeof(size_t) bytes to track @@ -427,9 +391,9 @@ vips_tracked_aligned_alloc(size_t size, size_t align) #endif /*DEBUG*/ vips_error("vips_tracked", - _("out of memory --- size == %dMB"), + _("out of memory -- size == %dMB"), (int) (size / (1024.0 * 1024.0))); - g_warning(_("out of memory --- size == %dMB"), + g_warning(_("out of memory -- size == %dMB"), (int) (size / (1024.0 * 1024.0))); return NULL; @@ -437,7 +401,7 @@ vips_tracked_aligned_alloc(size_t size, size_t align) memset(buf, 0, size); - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); *((size_t *) buf) = size; @@ -450,7 +414,7 @@ vips_tracked_aligned_alloc(size_t size, size_t align) printf("vips_tracked_aligned_alloc: %p, %zd bytes\n", buf, size); #endif /*DEBUG_VERBOSE*/ - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); VIPS_GATE_MALLOC(size); @@ -460,19 +424,20 @@ vips_tracked_aligned_alloc(size_t size, size_t align) /** * vips_tracked_open: * @pathname: name of file to open - * @flags: flags for open() + * @flags: flags for `open()` * @mode: open mode * - * Exactly as open(2), but the number of files currently open via - * vips_tracked_open() is available via vips_tracked_get_files(). This is used + * Exactly as [`open()`](man:open(2)), but the number of files currently open via + * [func@tracked_open] is available via [func@tracked_get_files]. This is used * by the vips operation cache to drop cache when the number of files * available is low. * - * You must only close the file descriptor with vips_tracked_close(). + * You must only close the file descriptor with [func@tracked_close]. * * @pathname should be utf8. * - * See also: vips_tracked_close(), vips_tracked_get_files(). + * ::: seealso + * [func@tracked_close], [func@tracked_get_files]. * * Returns: a file descriptor, or -1 on error. */ @@ -484,9 +449,7 @@ vips_tracked_open(const char *pathname, int flags, int mode) if ((fd = vips__open(pathname, flags, mode)) == -1) return -1; - vips_tracked_init(); - - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); vips_tracked_files += 1; #ifdef DEBUG_VERBOSE_FD @@ -494,23 +457,24 @@ vips_tracked_open(const char *pathname, int flags, int mode) pathname, fd, vips_tracked_files); #endif /*DEBUG_VERBOSE_FD*/ - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); return fd; } /** * vips_tracked_close: - * @fd: file to close() + * @fd: file to `close()` * - * Exactly as close(2), but update the number of files currently open via - * vips_tracked_get_files(). This is used + * Exactly as [`close()`](man:close(2)), but update the number of files currently open via + * [func@tracked_get_files]. This is used * by the vips operation cache to drop cache when the number of files * available is low. * - * You must only close file descriptors opened with vips_tracked_open(). + * You must only close file descriptors opened with [func@tracked_open]. * - * See also: vips_tracked_open(), vips_tracked_get_files(). + * ::: seealso + * [func@tracked_open], [func@tracked_get_files]. * * Returns: a file descriptor, or -1 on error. */ @@ -519,7 +483,7 @@ vips_tracked_close(int fd) { int result; - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); /* libvips uses fd -1 to mean invalid descriptor. */ @@ -532,7 +496,7 @@ vips_tracked_close(int fd) printf(" from thread %p\n", g_thread_self()); #endif /*DEBUG_VERBOSE_FD*/ - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); result = close(fd); @@ -542,9 +506,9 @@ vips_tracked_close(int fd) /** * vips_tracked_get_mem: * - * Returns the number of bytes currently allocated via vips_malloc() and + * Returns the number of bytes currently allocated via [func@malloc] and * friends. vips uses this figure to decide when to start dropping cache, see - * #VipsOperation. + * [class@Operation]. * * Returns: the number of currently allocated bytes */ @@ -553,13 +517,11 @@ vips_tracked_get_mem(void) { size_t mem; - vips_tracked_init(); - - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); mem = vips_tracked_mem; - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); return mem; } @@ -568,7 +530,7 @@ vips_tracked_get_mem(void) * vips_tracked_get_mem_highwater: * * Returns the largest number of bytes simultaneously allocated via - * vips_tracked_malloc(). Handy for estimating max memory requirements for a + * [func@tracked_malloc]. Handy for estimating max memory requirements for a * program. * * Returns: the largest number of currently allocated bytes @@ -578,13 +540,11 @@ vips_tracked_get_mem_highwater(void) { size_t mx; - vips_tracked_init(); - - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); mx = vips_tracked_mem_highwater; - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); return mx; } @@ -601,13 +561,11 @@ vips_tracked_get_allocs(void) { int n; - vips_tracked_init(); - - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); n = vips_tracked_allocs; - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); return n; } @@ -624,13 +582,11 @@ vips_tracked_get_files(void) { int n; - vips_tracked_init(); - - g_mutex_lock(vips_tracked_mutex); + g_mutex_lock(&vips_tracked_mutex); n = vips_tracked_files; - g_mutex_unlock(vips_tracked_mutex); + g_mutex_unlock(&vips_tracked_mutex); return n; } diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index e0c017d673..593d76a671 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -58,108 +58,105 @@ #include "vipsmarshal.h" /** - * SECTION: object - * @short_description: the VIPS base object class - * @stability: Stable - * @see_also: operation - * @include: vips/vips.h + * VipsObject: * - * The #VipsObject class and associated types and macros. + * An abstract base class for all objects in libvips. * - * #VipsObject is the base class for all objects in libvips. It has the - * following major features: + * It has the following major features: * - * Functional class creation Vips objects have a very - * regular lifecycle: initialise, build, use, destroy. They behave rather like - * function calls and are free of side-effects. + * - **Functional class creation**: libvips objects have a very regular + * lifecycle: initialise, build, use, destroy. They behave rather like + * function calls and are free of side-effects. * - * Run-time introspection Vips objects can be fully - * introspected at run-time. There is no need for separate source-code - * analysis. + * - **Run-time introspection**: libvips objects can be fully introspected + * at run-time. There is no need for separate source-code analysis. * - * Command-line interface Any vips object can be run from - * the command-line with the `vips` driver program. + * - **Command-line interface**: Any vips object can be run from the + * command-line with the `vips` driver program. * - * ## The #VipsObject lifecycle + * ## The [class@Object] lifecycle * - * #VipsObject s have a strictly defined lifecycle, split broadly as construct - * and then use. In detail, the stages are: + * [class@Object]'s have a strictly defined lifecycle, split broadly as + * construct and then use. In detail, the stages are: * - * 1. g_object_new(). The #VipsObject is created with g_object_new(). Objects - * in this state are blank slates and need to have their various parameters - * set. + * 1. [ctor@GObject.Object.new]. The [class@Object] is created with + * [ctor@GObject.Object.new]. Objects in this state are blank slates and + * need to have their various parameters set. * - * 2. g_object_set(). You loop over the #VipsArgument that the object has - * defined with vips_argument_map(). Arguments have a set of flags attached to - * them for required, optional, input, output, type, and so on. You must set - * all required arguments. + * 2. [method@GObject.Object.set]. You loop over the [struct@Argument] that + * the object has defined with [func@Argument.map]. Arguments have a set of + * flags attached to them for required, optional, input, output, type, and + * so on. You must set all required arguments. * - * 3. vips_object_build(). Call this to construct the object and get it ready - * for use. Building an object happens in four stages, see below. + * 3. [method@Object.build]. Call this to construct the object and get it + * ready for use. Building an object happens in four stages, see below. * - * 4. g_object_get(). The object has now been built. You can read out any - * computed values. + * 4. [method@GObject.Object.get]. The object has now been built. You can + * read out any computed values. * - * 5. g_object_unref(). When you are done with an object, you can unref it. - * See the section on reference counting for an explanation of the convention - * that #VipsObject uses. When the last ref to an object is released, the - * object is closed. Objects close in three stages, see below. + * 5. [method@GObject.Object.unref]. When you are done with an object, you + * can unref it. See the section on reference counting for an explanation + * of the convention that [class@Object] uses. When the last ref to an + * object is released, the object is closed. Objects close in three stages, + * see below. * - * The stages inside vips_object_build() are: + * The stages inside [method@Object.build] are: * - * 1. Chain up through the object's @build class methods. At each stage, - * each class does any initial setup and checking, then chains up to its - * superclass. + * 1. Chain up through the object's `build` class methods. At each stage, + * each class does any initial setup and checking, then chains up to its + * superclass. * - * 2. The innermost @build method inside #VipsObject itself checks that all - * input arguments have been set and then returns. + * 2. The innermost `build` method inside [class@Object] itself checks that + * all input arguments have been set and then returns. * - * 3. All object @build methods now finish executing, from innermost to - * outermost. They know all input arguments have been checked and supplied, so - * now they set all output arguments. + * 3. All object `build` methods now finish executing, from innermost to + * outermost. They know all input arguments have been checked and supplied, + * so now they set all output arguments. * - * 4. vips_object_build() finishes the process by checking that all output - * objects have been set, and then triggering the #VipsObject::postbuild - * signal. #VipsObject::postbuild only runs if the object has constructed - * successfully. + * 4. [method@Object.build] finishes the process by checking that all output + * objects have been set, and then triggering the [signal@Object::postbuild] + * signal. [signal@Object::postbuild] only runs if the object has constructed + * successfully. * - * #VipsOperation has a cache of recent operation objects, see that class for - * an explanation of vips_cache_operation_build(). + * [class@Operation] has a cache of recent operation objects, see that class for + * an explanation of [func@cache_operation_build]. * - * Finally the stages inside close are: + * Finally, the stages inside close are: * - * 1. #VipsObject::preclose. This is emitted at the start of - * the #VipsObject dispose. The object is still functioning. + * 1. [signal@Object::preclose]. This is emitted at the start of the + * [class@Object] dispose. The object is still functioning. * - * 2. #VipsObject::close. This runs just after all #VipsArgument held by - * the object have been released. + * 2. [signal@Object::close]. This runs just after all [struct@Argument] held + * by the object have been released. * - * 3. #VipsObject::postclose. This runs right at the end. The object - * pointer is still valid, but nothing else is. + * 3. [signal@Object::postclose]. This runs right at the end. The object + * pointer is still valid, but nothing else is. * - * ## #VipsArgument + * ## The [class@Object] reference counting convention * - * libvips has a simple mechanism for automating at least some aspects of - * %GObject properties. You add a set of macros to your _class_init() which - * describe the arguments, and set the get and set functions to the vips ones. - * - * See extending for a complete example. - * - * ## The #VipsObject reference counting convention + * [class@Object] has a set of conventions to simplify reference counting. * - * #VipsObject has a set of conventions to simplify reference counting. + * 1. All input [class@GObject.Object] have a ref added to them, owned by the + * object. When a [class@Object] is unreffed, all of these refs to input + * objects are automatically dropped. * - * 1. All input %GObject have a ref added to them, owned by the object. When a - * #VipsObject is unreffed, all of these refs to input objects are - * automatically dropped. + * 2. All output [class@GObject.Object] hold a ref to the object. When a + * [class@GObject.Object] which is an output of a [class@Object] is + * disposed, it must drop this reference. [class@Object] which are outputs + * of other [class@Object]'s will do this automatically. * - * 2. All output %GObject hold a ref to the object. When a %GObject which is an - * output of a #VipsObject is disposed, it must drop this reference. - * #VipsObject which are outputs of other #VipsObject will do this - * automatically. + * See [class@Operation] for an example of [class@Object] reference counting. + */ + +/** + * VipsArgument: * - * See #VipsOperation for an example of #VipsObject reference counting. + * libvips has a simple mechanism for automating at least some aspects of + * [class@GObject.Object] properties. You add a set of macros to your + * `_class_init()` which describe the arguments, and set the get and set + * functions to the libvips ones. * + * See [extending](extending.html) for a complete example. */ /** @@ -182,20 +179,20 @@ * Input gobjects are automatically reffed, output gobjects automatically ref * us. We also automatically watch for "destroy" and unlink. * - * @VIPS_ARGUMENT_SET_ALWAYS is handy for arguments which are set from C. For + * [flags@Vips.ArgumentFlags.SET_ALWAYS] is handy for arguments which are set from C. For * example, VipsImage::width is a property that gives access to the Xsize * member of struct _VipsImage. We default its 'assigned' to TRUE * since the field is always set directly by C. * - * @VIPS_ARGUMENT_DEPRECATED arguments are not shown in help text, are not + * [flags@Vips.ArgumentFlags.DEPRECATED] arguments are not shown in help text, are not * looked for if required, are not checked for "have-been-set". You can * deprecate a required argument, but you must obviously add a new required * argument if you do. * - * Input args with @VIPS_ARGUMENT_MODIFY will be modified by the operation. + * Input args with [flags@Vips.ArgumentFlags.MODIFY] will be modified by the operation. * This is used for things like the in-place drawing operations. * - * @VIPS_ARGUMENT_NON_HASHABLE stops the argument being used in hash and + * [flags@Vips.ArgumentFlags.NON_HASHABLE] stops the argument being used in hash and * equality tests. It's useful for arguments like `revalidate` which * control the behaviour of the operator cache. */ @@ -213,7 +210,7 @@ enum { /* Table of all objects, handy for debugging. */ static GHashTable *vips__object_all = NULL; -static GMutex *vips__object_all_lock = NULL; +static GMutex vips__object_all_lock; static guint vips_object_signals[SIG_LAST] = { 0 }; @@ -230,7 +227,8 @@ G_DEFINE_ABSTRACT_TYPE(VipsObject, vips_object, G_TYPE_OBJECT); /** * vips_argument_get_id: (skip) * - * Allocate a new property id. See g_object_class_install_property(). + * Allocate a new property id. See + * [method@GObject.ObjectClass.install_property]. * * Returns: a new property id > 0 */ @@ -354,12 +352,11 @@ vips_object_check_required(VipsObject *object, GParamSpec *pspec, int vips_object_build(VipsObject *object) { - VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS(object); + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); /* Input and output args must both be set. */ - VipsArgumentFlags iomask = - VIPS_ARGUMENT_INPUT | VIPS_ARGUMENT_OUTPUT; + VipsArgumentFlags iomask = VIPS_ARGUMENT_INPUT | VIPS_ARGUMENT_OUTPUT; int result; @@ -369,7 +366,7 @@ vips_object_build(VipsObject *object) printf("\n"); #endif /*DEBUG*/ - if (object_class->build(object)) + if (class->build(object)) return -1; /* Check all required arguments have been supplied, don't stop on 1st @@ -559,9 +556,9 @@ vips__argument_table_lookup(VipsArgumentTable *table, GParamSpec *pspec) { VipsArgument *argument; - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); argument = (VipsArgument *) g_hash_table_lookup(table, pspec); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); return argument; } @@ -579,17 +576,17 @@ vips_argument_table_destroy(VipsArgumentTable *table) } /** - * vips_argument_map: (skip) + * vips_argument_map: * @object: object whose args should be enumerated - * @fn: call this function for every argument + * @fn: (scope call) (closure a): call this function for every argument * @a: client data * @b: client data * - * Loop over the vips_arguments to an object. Stop when @fn returns non-%NULL + * Loop over the vips_arguments to an object. Stop when @fn returns non-`NULL` * and return that value. * - * Returns: %NULL if @fn returns %NULL for all arguments, otherwise the first - * non-%NULL value from @fn. + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. */ void * vips_argument_map(VipsObject *object, @@ -805,7 +802,7 @@ vips_object_get_argument(VipsObject *object, const char *name, * * Convenience: has an argument been assigned. Useful for bindings. * - * Returns: %TRUE if the argument has been assigned. + * Returns: `TRUE` if the argument has been assigned. */ gboolean vips_object_argument_isset(VipsObject *object, const char *name) @@ -828,7 +825,7 @@ vips_object_argument_isset(VipsObject *object, const char *name) * * Convenience: get the flags for an argument. Useful for bindings. * - * Returns: The #VipsArgumentFlags for this argument. + * Returns: The [flags@ArgumentFlags] for this argument. */ VipsArgumentFlags vips_object_get_argument_flags(VipsObject *object, const char *name) @@ -1047,9 +1044,9 @@ vips_object_finalize(GObject *gobject) * from finalize, sadly. */ - g_mutex_lock(vips__object_all_lock); + g_mutex_lock(&vips__object_all_lock); g_hash_table_remove(vips__object_all, object); - g_mutex_unlock(vips__object_all_lock); + g_mutex_unlock(&vips__object_all_lock); G_OBJECT_CLASS(vips_object_parent_class)->finalize(gobject); } @@ -1406,7 +1403,7 @@ vips_object_get_property(GObject *gobject, argument_class->offset); /* Copy the boxed into our pointer (will use eg. - * vips__object_vector_dup ()). + * vips__object_vector_dup()). */ g_value_set_boxed(value, *member); } @@ -1564,11 +1561,8 @@ vips_object_class_init(VipsObjectClass *class) */ vips_check_init(); - if (!vips__object_all) { - vips__object_all = g_hash_table_new( - g_direct_hash, g_direct_equal); - vips__object_all_lock = vips_g_mutex_new(); - } + if (!vips__object_all) + vips__object_all = g_hash_table_new(g_direct_hash, g_direct_equal); gobject_class->dispose = vips_object_dispose; gobject_class->finalize = vips_object_finalize; @@ -1682,9 +1676,9 @@ vips_object_init(VipsObject *object) printf("\n"); #endif /*DEBUG*/ - g_mutex_lock(vips__object_all_lock); + g_mutex_lock(&vips__object_all_lock); g_hash_table_insert(vips__object_all, object, object); - g_mutex_unlock(vips__object_all_lock); + g_mutex_unlock(&vips__object_all_lock); } static void * @@ -1728,7 +1722,7 @@ vips_object_class_install_argument(VipsObjectClass *object_class, /* object_class->argument* is shared, so we must lock. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); /* Must be a new one. */ @@ -1827,7 +1821,7 @@ vips_object_class_install_argument(VipsObjectClass *object_class, } #endif /*DEBUG*/ - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } static void @@ -2307,14 +2301,14 @@ vips_object_find_args(VipsObject *object, /** * vips_object_get_args: (skip) * @object: object whose args should be retrieved - * @names: (transfer none) (array length=n_args) (allow-none): output array of %GParamSpec names - * @flags: (transfer none) (array length=n_args) (allow-none): output array of #VipsArgumentFlags + * @names: (transfer none) (array length=n_args) (allow-none): output array of [class@GObject.ParamSpec] names + * @flags: (transfer none) (array length=n_args) (allow-none): output array of [flags@ArgumentFlags] * @n_args: (allow-none): length of output arrays * - * Get all %GParamSpec names and #VipsArgumentFlags for an object. + * Get all [class@GObject.ParamSpec] names and [flags@ArgumentFlags] for an object. * * This is handy for language bindings. From C, it's usually more convenient to - * use vips_argument_map(). + * use [func@Argument.map]. * * Returns: 0 on success, -1 on error */ @@ -2355,8 +2349,8 @@ vips_object_get_args(VipsObject *object, * @a: client data * @b: client data * - * g_object_new() the object, set any arguments with @set, call - * vips_object_build() and return the complete object. + * [ctor@GObject.Object.new] the object, set any arguments with @set, call + * [method@Object.build] and return the complete object. * * Returns: the new object */ @@ -2385,9 +2379,9 @@ vips_object_new(GType type, VipsObjectSetArguments set, void *a, void *b) /** * vips_object_set_valist: * @object: object to set arguments on - * @ap: %NULL-terminated list of argument/value pairs + * @ap: `NULL`-terminated list of argument/value pairs * - * See vips_object_set(). + * See [method@Object.set]. * * Returns: 0 on success, -1 on error */ @@ -2424,21 +2418,22 @@ vips_object_set_valist(VipsObject *object, va_list ap) /** * vips_object_set: * @object: object to set arguments on - * @...: %NULL-terminated list of argument/value pairs + * @...: `NULL`-terminated list of argument/value pairs * * Set a list of vips object arguments. For example: * - * |[ + * ```c * vips_object_set(operation, * "input", in, * "output", &out, * NULL); - * ]| + * ``` * * Input arguments are given in-line, output arguments are given as pointers * to where the output value should be written. * - * See also: vips_object_set_valist(), vips_object_set_from_string(). + * ::: seealso + * [method@Object.set_valist], [method@Object.set_from_string]. * * Returns: 0 on success, -1 on error */ @@ -2563,8 +2558,9 @@ vips_object_set_args(VipsObject *object, const char *p) * * You'd typically use this between creating the object and building it. * - * See also: vips_object_set(), vips_object_build(), - * vips_cache_operation_buildp(). + * ::: seealso + * [method@Object.set], [method@Object.build], + * [func@cache_operation_buildp]. * * Returns: 0 on success, -1 on error */ @@ -2679,8 +2675,8 @@ vips_object_to_string_optional(VipsObject *object, * @object: object to stringify * @buf: write string here * - * The inverse of vips_object_new_from_string(): turn @object into eg. - * "VipsInterpolateSnohalo1(blur=.333333)". + * The inverse of [ctor@Object.new_from_string]: turn @object into eg. + * `"VipsInterpolateSnohalo1(blur=.333333)"`. */ void vips_object_to_string(VipsObject *object, VipsBuf *buf) @@ -2726,10 +2722,10 @@ vips_object_map_sub(VipsObject *key, VipsObject *value, * @b: client data * * Call a function for all alive objects. - * Stop when @fn returns non-%NULL and return that value. + * Stop when @fn returns non-`NULL` and return that value. * - * Returns: %NULL if @fn returns %NULL for all arguments, otherwise the first - * non-%NULL value from @fn. + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. */ void * vips_object_map(VipsSListMap2Fn fn, void *a, void *b) @@ -2745,10 +2741,10 @@ vips_object_map(VipsSListMap2Fn fn, void *a, void *b) * only created when the first object is created. */ if (vips__object_all) { - g_mutex_lock(vips__object_all_lock); + g_mutex_lock(&vips__object_all_lock); g_hash_table_foreach(vips__object_all, (GHFunc) vips_object_map_sub, &args); - g_mutex_unlock(vips__object_all_lock); + g_mutex_unlock(&vips__object_all_lock); } return args.result; @@ -2761,11 +2757,11 @@ vips_object_map(VipsSListMap2Fn fn, void *a, void *b) * @a: client data * @b: client data * - * Map over a type's children. Stop when @fn returns non-%NULL + * Map over a type's children. Stop when @fn returns non-`NULL` * and return that value. * - * Returns: %NULL if @fn returns %NULL for all arguments, otherwise the first - * non-%NULL value from @fn. + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. */ void * vips_type_map(GType base, VipsTypeMap2Fn fn, void *a, void *b) @@ -2791,10 +2787,10 @@ vips_type_map(GType base, VipsTypeMap2Fn fn, void *a, void *b) * @a: client data * * Map over a type's children, direct and indirect. Stop when @fn returns - * non-%NULL and return that value. + * non-`NULL` and return that value. * - * Returns: %NULL if @fn returns %NULL for all arguments, otherwise the first - * non-%NULL value from @fn. + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. */ void * vips_type_map_all(GType base, VipsTypeMapFn fn, void *a) @@ -2816,10 +2812,10 @@ vips_type_map_all(GType base, VipsTypeMapFn fn, void *a) * * Loop over all the subclasses of @type. Non-abstract classes only. * Stop when @fn returns - * non-%NULL and return that value. + * non-`NULL` and return that value. * - * Returns: %NULL if @fn returns %NULL for all arguments, otherwise the first - * non-%NULL value from @fn. + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. */ void * vips_class_map_all(GType type, VipsClassMapFn fn, void *a) @@ -2881,7 +2877,8 @@ test_name(VipsObjectClass *class, const char *nickname) * Search below @basename, return the first class whose name or @nickname * matches. * - * See also: vips_type_find() + * ::: seealso + * [func@type_find] * * Returns: (transfer none): the found class. */ @@ -2940,8 +2937,7 @@ vips_class_build_hash_cb(void *dummy) { GType base; - vips__object_nickname_table = - g_hash_table_new(g_str_hash, g_str_equal); + vips__object_nickname_table = g_hash_table_new(g_str_hash, g_str_equal); base = g_type_from_name("VipsObject"); g_assert(base); @@ -2958,15 +2954,16 @@ vips_class_build_hash_cb(void *dummy) * @basename: name of base class * @nickname: search for a class with this nickname * - * Search below @basename, return the %GType of the class whose name or - * @nickname matches, or 0 for not found. - * If @basename is NULL, the whole of #VipsObject is searched. + * Search below @basename, return the [alias@GObject.Type] of the class + * whose name or @nickname matches, or 0 for not found. + * If @basename is NULL, the whole of [class@Object] is searched. * * This function uses a cache, so it should be quick. * - * See also: vips_class_find() + * ::: seealso + * [func@class_find] * - * Returns: the %GType of the class, or 0 if the class is not found. + * Returns: the [alias@GObject.Type] of the class, or 0 if the class is not found. */ GType vips_type_find(const char *basename, const char *nickname) @@ -2982,8 +2979,7 @@ vips_type_find(const char *basename, const char *nickname) VIPS_ONCE(&once, vips_class_build_hash_cb, NULL); hit = (NicknameGType *) - g_hash_table_lookup(vips__object_nickname_table, - (void *) nickname); + g_hash_table_lookup(vips__object_nickname_table, (void *) nickname); /* We must only search below basename ... check that the cache hit is * in the right part of the tree. @@ -3008,9 +3004,9 @@ vips_type_find(const char *basename, const char *nickname) /** * vips_nickname_find: - * @type: #GType to search for + * @type: [alias@GObject.Type] to search for * - * Return the VIPS nickname for a %GType. Handy for language bindings. + * Return the VIPS nickname for a [alias@GObject.Type]. Handy for language bindings. * * Returns: (transfer none): the class nickname. */ @@ -3029,7 +3025,7 @@ vips_nickname_find(GType type) return NULL; } -/* The vips_object_local() macro uses this as its callback. +/* The vips_object_local_array() macro uses this as its callback. */ void vips_object_local_cb(VipsObject *vobject, GObject *gobject) @@ -3068,7 +3064,7 @@ vips_object_local_array_cb(VipsObject *parent, VipsObjectLocal *local) * * Example: * - * |[ + * ```c * VipsObject **t; * * t = vips_object_local_array(parent, 5); @@ -3077,9 +3073,7 @@ vips_object_local_array_cb(VipsObject *parent, VipsObjectLocal *local) * vips_add(t[1], t[0], &t[2], NULL) || * vips_costra(t[2], out, NULL)) * return -1; - * ]| - * - * See also: vips_object_local(). + * ``` * * Returns: an array of NULL pointers of length @n */ @@ -3163,14 +3157,12 @@ vips__object_leak(void) /* Don't count static objects. */ if (vips__object_all && - g_hash_table_size(vips__object_all) > - vips_object_n_static()) { + g_hash_table_size(vips__object_all) > vips_object_n_static()) { fprintf(stderr, "%d objects alive:\n", g_hash_table_size(vips__object_all)); vips_object_map( - (VipsSListMap2Fn) vips_object_print_all_cb, - &n_leaks, NULL); + (VipsSListMap2Fn) vips_object_print_all_cb, &n_leaks, NULL); } return n_leaks; @@ -3234,7 +3226,8 @@ vips_object_unref_outputs_sub(VipsObject *object, * been made so far. This function can also be useful for callers when * they've finished processing outputs themselves. * - * See also: vips_cache_operation_build(). + * ::: seealso + * [func@cache_operation_build]. */ void vips_object_unref_outputs(VipsObject *object) @@ -3249,7 +3242,7 @@ vips_object_unref_outputs(VipsObject *object) * * Fetch the object description. Useful for language bindings. * - * @object.description is only available after _build(), which can be too + * [property@VipsObject:description] is only available after `_build()`, which can be too * late. This function fetches from the instance, if possible, but falls back * to the class description if we are too early. * diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index dc201c24f8..eb8be37a20 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -52,28 +52,23 @@ #include /** - * SECTION: operation - * @short_description: the VIPS operation base object class - * @stability: Stable - * @see_also: object - * @include: vips/vips.h + * VipsOperation: * - * The #VipsOperation class and associated types and macros. + * An abstract base class for all operations in libvips. * - * #VipsOperation is the base class for all operations in libvips. It builds - * on #VipsObject to provide the introspection and command-line interface to - * libvips. + * It builds on [class@VipsObject] to provide the introspection and + * command-line interface to libvips. * * It also maintains a cache of recent operations. See below. * - * vips_call(), vips_call_split() and vips_call_split_option_string() are used - * by vips to implement the C API. They can execute any #VipsOperation, + * [func@call], [func@call_split] and [func@call_split_option_string] are used + * by vips to implement the C API. They can execute any [class@Operation], * passing in a set of required and optional arguments. Normally you would not * use these functions directly: every operation has a tiny wrapper function * which provides type-safety for the required arguments. For example, - * vips_embed() is defined as: + * [method@Image.embed] is defined as: * - * |[ + * ```c * int * vips_embed(VipsImage *in, VipsImage **out, * int x, int y, int width, int height, ...) @@ -87,38 +82,38 @@ * * return result; * } - * ]| + * ``` * - * Use vips_call_argv() to run any vips operation from a command-line style - * argc/argv array. This is the thing used by the vips main program to - * implement the vips command-line interface. + * Use [func@call_argv] to run any libvips operation from a command-line style + * argc/argv array. This is the thing used by the `vips` main program to + * implement the command-line interface. * - * ## #VipsOperation and reference counting + * ## [class@Operation] and reference counting * - * After calling a #VipsOperation you are responsible for unreffing any output - * objects. For example, consider: + * After calling a [class@Operation] you are responsible for unreffing any + * output objects. For example, consider: * - * |[ + * ```c * VipsImage *im = ...; * VipsImage *t1; * * if (vips_invert(im, &t1, NULL)) - * error .. - * ]| + * error .. + * ``` * - * This will invert @im and return a new #VipsImage, @t1. As the caller - * of vips_invert(), you are responsible for @t1 and must unref it when you no - * longer need it. If vips_invert() fails, no @t1 is returned and you don't - * need to do anything. + * This will invert `im` and return a new [class@Image], `t1`. As the caller + * of [method@Image.invert], you are responsible for `t1` and must unref it + * when you no longer need it. If [method@Image.invert] fails, no `t1` is + * returned and you don't need to do anything. * - * If you don't need to use @im for another operation, - * you can unref @im immediately after the call. If @im is needed to calculate - * @t1, vips_invert() will add a ref to @im and automatically drop it when @t1 - * is unreffed. + * If you don't need to use `im` for another operation, you can unref `im` + * immediately after the call. If `im` is needed to calculate `t1`, + * [method@Image.invert] will add a ref to `im` and automatically drop it when + * `t1` is unreffed. * * Consider running two operations, one after the other. You could write: * - * |[ + * ```c * VipsImage *im = ...; * VipsImage *t1, *t2; * @@ -133,12 +128,12 @@ * return -1; * } * g_object_unref(t1); - * ]| + * ``` * * This is correct, but rather long-winded. libvips provides a handy thing to * make a vector of auto-freeing object references. You can write this as: * - * |[ + * ```c * VipsObject *parent = ...; * VipsImage *im = ...; * VipsImage *t = (VipsImage **) vips_object_local_array(parent, 2); @@ -146,23 +141,23 @@ * if (vips_invert(im, &t[0], NULL) || * vips_flip(t[0], &t[1], VIPS_DIRECTION_HORIZONTAL, NULL)) * return -1; - * ]| + * ``` * - * where @parent is some enclosing object which will be unreffed when this - * task is complete. vips_object_local_array() makes an array of #VipsObject - * (or #VipsImage, in this case) where when @parent is freed, all non-NULL - * #VipsObject in the array are also unreffed. + * where `parent` is some enclosing object which will be unreffed when this + * task is complete. [method@Object.local_array] makes an array of + * [class@Object] (or [class@Image], in this case) where when `parent` is + * freed, all non-`NULL` [class@Object] in the array are also unreffed. * - * ## The #VipsOperation cache + * ## The [class@Operation] cache * - * Because all #VipsObject are immutable, they can be cached. The cache is - * very simple to use: instead of calling vips_object_build(), call - * vips_cache_operation_build(). This function calculates a hash from the - * operations's input arguments and looks it up in table of all recent + * Because all [class@Object] are immutable, they can be cached. The cache is + * very simple to use: instead of calling [method@Object.build], call + * [func@cache_operation_build]. This function calculates a hash from the + * operations' input arguments and looks it up in table of all recent * operations. If there's a hit, the new operation is unreffed, the old * operation reffed, and the old operation returned in place of the new one. * - * The cache size is controlled with vips_cache_set_max() and friends. + * The cache size is controlled with [func@cache_set_max] and friends. */ /** @@ -177,9 +172,9 @@ * * Flags we associate with an operation. * - * @VIPS_OPERATION_SEQUENTIAL means that the operation works like vips_conv(): - * it can process images top-to-bottom with only small non-local - * references. + * [flags@Vips.OperationFlags.SEQUENTIAL] means that the operation works like + * [method@Image.conv]: it can process images top-to-bottom with only small + * non-local references. * * Every scan-line must be requested, you are not allowed to skip * ahead, but as a special case, the very first request can be for a region @@ -191,21 +186,21 @@ * not at the top of the image. In this case, the first part of the image will * be read and discarded * - * @VIPS_OPERATION_NOCACHE means that the operation must not be cached by + * [flags@Vips.OperationFlags.NOCACHE] means that the operation must not be cached by * vips. * - * @VIPS_OPERATION_DEPRECATED means this is an old operation kept in vips for + * [flags@Vips.OperationFlags.DEPRECATED] means this is an old operation kept in vips for * compatibility only and should be hidden from users. * - * @VIPS_OPERATION_UNTRUSTED means the operation depends on external libraries + * [flags@Vips.OperationFlags.UNTRUSTED] means the operation depends on external libraries * which have not been hardened against attack. It should probably not be used - * on untrusted input. Use vips_block_untrusted_set() to block all + * on untrusted input. Use [func@block_untrusted_set] to block all * untrusted operations. * - * @VIPS_OPERATION_BLOCKED means the operation is prevented from executing. Use - * vips_operation_block_set() to enable and disable groups of operations. + * [flags@Vips.OperationFlags.BLOCKED] means the operation is prevented from executing. Use + * [func@Operation.block_set] to enable and disable groups of operations. * - * @VIPS_OPERATION_REVALIDATE force the operation to run, updating the cache + * [flags@Vips.OperationFlags.REVALIDATE] force the operation to run, updating the cache * with the new value. This is used by eg. VipsForeignLoad to implement the * "revalidate" argument. */ @@ -727,11 +722,11 @@ vips_operation_invalidate(VipsOperation *operation) * vips_operation_new: (constructor) * @name: nickname of operation to create * - * Return a new #VipsOperation with the specified nickname. Useful for + * Return a new [class@Operation] with the specified nickname. Useful for * language bindings. * * You'll need to set any arguments and build the operation before you can use - * it. See vips_call() for a higher-level way to make new operations. + * it. See [func@call] for a higher-level way to make new operations. * * Returns: (transfer full): the new operation. */ @@ -940,8 +935,8 @@ vips_operation_get_valist_optional(VipsOperation *operation, va_list ap) /** * vips_call_required_optional: * @operation: the operation to execute - * @required: %va_list of required arguments - * @optional: NULL-terminated %va_list of name / value pairs + * @required: `va_list` of required arguments + * @optional: `NULL`-terminated `va_list` of name / value pairs * * This is the main entry point for the C and C++ varargs APIs. @operation * is executed, supplying @required and @optional arguments. @@ -1036,17 +1031,17 @@ vips_call_by_name(const char *operation_name, /** * vips_call: * @operation_name: name of operation to call - * @...: required args, then a %NULL-terminated list of argument/value pairs + * @...: required args, then a `NULL`-terminated list of argument/value pairs * - * vips_call() calls the named operation, passing in required arguments and + * [func@call] calls the named operation, passing in required arguments and * then setting any optional ones from the remainder of the arguments as a set * of name/value pairs. * - * For example, vips_embed() takes six required arguments, @in, @out, @x, @y, - * @width, @height, and has two optional arguments, @extend and @background. - * You can run it with vips_call() like this: + * For example, [method@Image.embed] takes six required arguments, @in, @out, + * @x, @y, @width, @height, and has two optional arguments, @extend and + * @background. You can run it with [func@call] like this: * - * |[ + * ```c * VipsImage *in = ... * VipsImage *out; * @@ -1054,12 +1049,13 @@ vips_call_by_name(const char *operation_name, * "extend", VIPS_EXTEND_COPY, * NULL)) * ... error - * ]| + * ``` * - * Normally of course you'd just use the vips_embed() wrapper function and get + * Normally of course you'd just use the [method@Image.embed] wrapper function and get * type-safety for the required arguments. * - * See also: vips_call_split(), vips_call_options(). + * ::: seealso + * [func@call_split], [func@call_options]. * * Returns: 0 on success, -1 on error */ @@ -1521,10 +1517,10 @@ vips_operation_block_set_operation(VipsOperationClass *class, gboolean *state) * * For example: * - * |[ + * ```c * vips_operation_block_set("VipsForeignLoad", TRUE); * vips_operation_block_set("VipsForeignLoadJpeg", FALSE); - * ]| + * ``` * * Will block all load operations, except JPEG. * @@ -1532,7 +1528,8 @@ vips_operation_block_set_operation(VipsOperationClass *class, gboolean *state) * * This call does nothing if the named operation is not found. * - * See also: vips_block_untrusted_set(). + * ::: seealso + * [func@block_untrusted_set]. */ void vips_operation_block_set(const char *name, gboolean state) diff --git a/libvips/iofuncs/rect.c b/libvips/iofuncs/rect.c index 460236db0e..09c1509dfb 100644 --- a/libvips/iofuncs/rect.c +++ b/libvips/iofuncs/rect.c @@ -44,16 +44,6 @@ #include -/** - * SECTION: rectangle - * @short_description: the VIPS rectangle class - * @stability: Stable - * @see_also: region - * @include: vips/vips.h - * - * The #VipsRect class and associated types and macros. - */ - /** * VipsRect: * @left: left edge of rectangle @@ -61,7 +51,7 @@ * @width: width of rectangle * @height: height of rectangle * - * A #VipsRect is a rectangular area of pixels. This is a struct for + * A [struct@Rect] is a rectangular area of pixels. This is a struct for * performing simple rectangle algebra. */ @@ -73,7 +63,7 @@ * * Does @r contain point (@x, @y)? * - * Returns: %TRUE if @r contains (@x, @y). + * Returns: `TRUE` if @r contains (@x, @y). */ gboolean vips_rect_includespoint(const VipsRect *r, int x, int y) @@ -90,7 +80,7 @@ vips_rect_includespoint(const VipsRect *r, int x, int y) * * Is @r empty? ie. zero width or height. * - * Returns: %TRUE if @r contains no pixels. + * Returns: `TRUE` if @r contains no pixels. */ gboolean vips_rect_isempty(const VipsRect *r) @@ -105,7 +95,7 @@ vips_rect_isempty(const VipsRect *r) * * Is @r2 a subset of @r1? * - * Returns: %TRUE if @r2 is a subset of @r1. + * Returns: `TRUE` if @r2 is a subset of @r1. */ gboolean vips_rect_includesrect(const VipsRect *r1, const VipsRect *r2) @@ -123,7 +113,7 @@ vips_rect_includesrect(const VipsRect *r1, const VipsRect *r2) * * Is @r1 equal to @r2? * - * Returns: %TRUE if @r1 is equal to @r2. + * Returns: `TRUE` if @r1 is equal to @r2. */ gboolean vips_rect_equalsrect(const VipsRect *r1, const VipsRect *r2) @@ -139,7 +129,7 @@ vips_rect_equalsrect(const VipsRect *r1, const VipsRect *r2) * * Do @r1 and @r2 have a non-empty intersection? * - * Returns: %TRUE if @r2 and @r1 overlap. + * Returns: `TRUE` if @r2 and @r1 overlap. */ gboolean vips_rect_overlapsrect(const VipsRect *r1, const VipsRect *r2) @@ -227,7 +217,7 @@ vips_rect_unionrect(const VipsRect *r1, const VipsRect *r2, VipsRect *out) * vips_rect_dup: (skip) * @r: rectangle to duplicate * - * Duplicate a rect to the heap. You need to free the result with g_free(). + * Duplicate a rect to the heap. You need to free the result with [func@GLib.free]. * * Returns: (transfer full): a pointer to copy of @r allocated on the heap. */ diff --git a/libvips/iofuncs/region.c b/libvips/iofuncs/region.c index a951e35388..55218eb299 100644 --- a/libvips/iofuncs/region.c +++ b/libvips/iofuncs/region.c @@ -102,90 +102,75 @@ #include #include -#include #include /** - * SECTION: region - * @short_description: small, rectangular parts of images - * @stability: Stable - * @see_also: image, - * generate - * @include: vips/vips.h + * VipsRegion: + * + * A [class@Region] represents a small, rectangular part of an image. * - * A #VipsRegion is a small part of an image. You use regions to - * read pixels out of images without having to have the whole image in memory - * at once. + * You use regions to read pixels out of images without having to have the + * whole image in memory at once. * * A region can be a memory buffer, part of a memory-mapped file, part of some * other image, or part of some other region. * * Regions must be created, used and freed all within the same thread, since - * they can reference private per-thread caches. VIPS sanity-checks region - * ownership in various places, so you are likely to see g_assert() errors if - * you don't follow this rule. + * they can reference private per-thread caches. libvips sanity-checks region + * ownership in various places, so you are likely to see [func@GLib.assert] + * errors if you don't follow this rule. * - * There - * is API to transfer ownership of regions between threads, but hopefully this - * is only needed within VIPS, so we don't expose it. Hopefully. - */ - -/** - * VipsRegion: - * @im: the #VipsImage that this region is defined on - * @valid: the #VipsRect of pixels that this region represents - * - * A small part of a #VipsImage. @valid holds the left/top/width/height of the - * area of pixels that are available from the region. - * - * See also: VIPS_REGION_ADDR(), vips_region_new(), vips_region_prepare(). + * There is API to transfer ownership of regions between threads, but + * (hopefully) this is only needed within libvips, so we don't expose it. */ /** * VIPS_REGION_LSKIP: - * @R: a #VipsRegion + * @R: a [class@Region] * * Returns: The number of bytes to add to move down a scanline. */ /** * VIPS_REGION_N_ELEMENTS: - * @R: a #VipsRegion + * @R: a [class@Region] * * Returns: The number of band elements across a region. */ /** * VIPS_REGION_SIZEOF_LINE: - * @R: a #VipsRegion + * @R: a [class@Region] * * Returns: The number of bytes across a region. */ /** * VIPS_REGION_ADDR: - * @R: a #VipsRegion + * @R: a [class@Region] * @X: x coordinate * @Y: y coordinate * * This macro returns a pointer to a pixel in a region. The (@X, @Y) - * coordinates need to be within the #VipsRect (@R->valid). + * coordinates need to be within the [struct@Rect] (@R->valid). * * If DEBUG is defined, you get a version that checks bounds for you. * - * See also: vips_region_prepare(). + * ::: seealso + * [method@Region.prepare]. * * Returns: The address of pixel (@X,@Y) in @R. */ /** * VIPS_REGION_ADDR_TOPLEFT: - * @R: a #VipsRegion + * @R: a [class@Region] * - * This macro returns a pointer to the top-left pixel in the #VipsRegion, that + * This macro returns a pointer to the top-left pixel in the [class@Region], that * is, the pixel at (@R->valid.left, @R->valid.top). * - * See also: vips_region_prepare(). + * ::: seealso + * [method@Region.prepare]. * * Returns: The address of the top-left pixel in the region. */ @@ -213,9 +198,9 @@ vips_region_finalize(GObject *gobject) #endif /*VIPS_DEBUG*/ #ifdef VIPS_DEBUG - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips__regions_all = g_slist_remove(vips__regions_all, gobject); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); #endif /*VIPS_DEBUG*/ G_OBJECT_CLASS(vips_region_parent_class)->finalize(gobject); @@ -231,14 +216,14 @@ vips__region_start(VipsRegion *region) if (!region->seq && image->start_fn) { VIPS_GATE_START("vips__region_start: wait"); - g_mutex_lock(image->sslock); + g_mutex_lock(&image->sslock); VIPS_GATE_STOP("vips__region_start: wait"); region->seq = image->start_fn(image, image->client1, image->client2); - g_mutex_unlock(image->sslock); + g_mutex_unlock(&image->sslock); if (!region->seq) { #ifdef DEBUG @@ -265,14 +250,14 @@ vips__region_stop(VipsRegion *region) VIPS_GATE_START("vips__region_stop: wait"); - g_mutex_lock(image->sslock); + g_mutex_lock(&image->sslock); VIPS_GATE_STOP("vips__region_stop: wait"); result = image->stop_fn(region->seq, image->client1, image->client2); - g_mutex_unlock(image->sslock); + g_mutex_unlock(&image->sslock); /* stop function can return an error, but we have nothing we * can really do with it, sadly. @@ -312,13 +297,13 @@ vips_region_dispose(GObject *gobject) */ VIPS_GATE_START("vips_region_dispose: wait"); - g_mutex_lock(image->sslock); + g_mutex_lock(&image->sslock); VIPS_GATE_STOP("vips_region_dispose: wait"); image->regions = g_slist_remove(image->regions, region); - g_mutex_unlock(image->sslock); + g_mutex_unlock(&image->sslock); region->im = NULL; @@ -382,7 +367,7 @@ vips__region_take_ownership(VipsRegion *region) */ VIPS_GATE_START("vips__region_take_ownership: wait"); - g_mutex_lock(region->im->sslock); + g_mutex_lock(®ion->im->sslock); VIPS_GATE_STOP("vips__region_take_ownership: wait"); @@ -400,7 +385,7 @@ vips__region_take_ownership(VipsRegion *region) region->thread = g_thread_self(); } - g_mutex_unlock(region->im->sslock); + g_mutex_unlock(®ion->im->sslock); } void @@ -422,7 +407,7 @@ vips__region_no_ownership(VipsRegion *region) { VIPS_GATE_START("vips__region_no_ownership: wait"); - g_mutex_lock(region->im->sslock); + g_mutex_lock(®ion->im->sslock); VIPS_GATE_STOP("vips__region_no_ownership: wait"); @@ -432,7 +417,7 @@ vips__region_no_ownership(VipsRegion *region) if (region->buffer) vips_buffer_undone(region->buffer); - g_mutex_unlock(region->im->sslock); + g_mutex_unlock(®ion->im->sslock); } static int @@ -452,13 +437,13 @@ vips_region_build(VipsObject *object) */ VIPS_GATE_START("vips_region_build: wait"); - g_mutex_lock(image->sslock); + g_mutex_lock(&image->sslock); VIPS_GATE_STOP("vips_region_build: wait"); image->regions = g_slist_prepend(image->regions, region); - g_mutex_unlock(image->sslock); + g_mutex_unlock(&image->sslock); return 0; } @@ -483,11 +468,11 @@ vips_region_init(VipsRegion *region) region->type = VIPS_REGION_NONE; #ifdef VIPS_DEBUG - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips__regions_all = g_slist_prepend(vips__regions_all, region); printf("vips_region_init: %d regions in vips\n", g_slist_length(vips__regions_all)); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); #endif /*VIPS_DEBUG*/ } @@ -495,10 +480,11 @@ vips_region_init(VipsRegion *region) * vips_region_new: (constructor) * @image: image to create this region on * - * Create a region. #VipsRegion s start out empty, you need to call - * vips_region_prepare() to fill them with pixels. + * Create a region. [class@Region] start out empty, you need to call + * [method@Region.prepare] to fill them with pixels. * - * See also: vips_region_prepare(). + * ::: seealso + * [method@Region.prepare]. */ VipsRegion * vips_region_new(VipsImage *image) @@ -533,7 +519,7 @@ vips_region_new(VipsImage *image) /** * vips_region_buffer: * @reg: region to operate upon - * @r: #VipsRect of pixels you need to be able to address + * @r: [struct@Rect] of pixels you need to be able to address * * The region is transformed so that at least @r pixels are available as a * memory buffer that can be written to. @@ -602,7 +588,7 @@ vips_region_buffer(VipsRegion *reg, const VipsRect *r) /** * vips_region_image: * @reg: region to operate upon - * @r: #VipsRect of pixels you need to be able to address + * @r: [struct@Rect] of pixels you need to be able to address * * The region is transformed so that at least @r pixels are available to be * read from the image. The image needs to be a memory buffer or represent a @@ -683,11 +669,11 @@ vips_region_image(VipsRegion *reg, const VipsRect *r) * vips_region_region: * @reg: region to operate upon * @dest: region to connect to - * @r: #VipsRect of pixels you need to be able to address + * @r: [struct@Rect] of pixels you need to be able to address * @x: position of @r in @dest * @y: position of @r in @dest * - * Make VIPS_REGION_ADDR() on @reg go to @dest instead. + * Make [func@REGION_ADDR] on @reg go to @dest instead. * * @r is the part of @reg which you want to be able to address (this * effectively becomes the valid field), (@x, @y) is the top LH corner of the @@ -798,11 +784,11 @@ vips_region_region(VipsRegion *reg, * * Do two regions point to the same piece of image? ie. * - * |[ + * ```c * VIPS_REGION_ADDR(reg1, x, y) == VIPS_REGION_ADDR(reg2, x, y) && * *VIPS_REGION_ADDR(reg1, x, y) == * *VIPS_REGION_ADDR(reg2, x, y) for all x, y, reg1, reg2. - * ]| + * ``` * * Returns: non-zero on equality. */ @@ -910,13 +896,14 @@ vips_region_fill(VipsRegion *reg, * @reg->valid. * * For int images, @value is - * passed to memset(), so it usually needs to be 0 or 255. For float images, + * passed to [`memset()`](man:memset(3)), so it usually needs to be 0 or 255. For float images, * value is cast to a float and copied in to each band element. * * @r is clipped against * @reg->valid. * - * See also: vips_region_black(). + * ::: seealso + * [method@Region.black]. */ void vips_region_paint(VipsRegion *reg, const VipsRect *r, int value) @@ -980,7 +967,8 @@ vips_region_paint(VipsRegion *reg, const VipsRect *r, int value) * @ink should be a byte array of the same size as an image pixel containing * the binary value to write into the pixels. * - * See also: vips_region_paint(). + * ::: seealso + * [method@Region.paint]. */ void vips_region_paint_pel(VipsRegion *reg, const VipsRect *r, const VipsPel *ink) @@ -1025,7 +1013,8 @@ vips_region_paint_pel(VipsRegion *reg, const VipsRect *r, const VipsPel *ink) * * Paints 0 into the valid part of @reg. * - * See also: vips_region_paint(). + * ::: seealso + * [method@Region.paint]. */ void vips_region_black(VipsRegion *reg) @@ -1037,7 +1026,7 @@ vips_region_black(VipsRegion *reg) * vips_region_copy: * @reg: source region * @dest: (inout): destination region - * @r: #VipsRect of pixels you need to copy + * @r: [struct@Rect] of pixels you need to copy * @x: position of @r in @dest * @y: position of @r in @dest * @@ -1045,7 +1034,8 @@ vips_region_black(VipsRegion *reg) * positioning the area of pixels at @x, @y. The two regions must have pixels * which are the same size. * - * See also: vips_region_paint(). + * ::: seealso + * [method@Region.paint]. */ void vips_region_copy(VipsRegion *reg, @@ -1547,16 +1537,18 @@ vips_region_shrink_alpha(VipsRegion *from, * vips_region_shrink_method: * @from: source region * @to: (inout): destination region - * @target: #VipsRect of pixels you need to copy + * @target: [struct@Rect] of pixels you need to copy * @method: method to use when generating target pixels * * Write the pixels @target in @to from the x2 larger area in @from. * Non-complex uncoded images and LABQ only. Images with alpha (see - * vips_image_hasalpha()) shrink with pixels scaled by alpha to avoid fringing. + * [method@Image.hasalpha]) shrink with pixels scaled by alpha to avoid + * fringing. * * @method selects the method used to do the 2x2 shrink. * - * See also: vips_region_copy(). + * ::: seealso + * [method@Region.copy]. */ int vips_region_shrink_method(VipsRegion *from, VipsRegion *to, @@ -1568,8 +1560,7 @@ vips_region_shrink_method(VipsRegion *from, VipsRegion *to, return -1; if (from->im->Coding == VIPS_CODING_NONE) { - if (vips_check_noncomplex("vips_region_shrink_method", - image)) + if (vips_check_noncomplex("vips_region_shrink_method", image)) return -1; if (vips_image_hasalpha(image)) @@ -1587,15 +1578,16 @@ vips_region_shrink_method(VipsRegion *from, VipsRegion *to, * vips_region_shrink: (skip) * @from: source region * @to: (inout): destination region - * @target: #VipsRect of pixels you need to copy + * @target: [struct@Rect] of pixels you need to copy * * Write the pixels @target in @to from the x2 larger area in @from. * Non-complex uncoded images and LABQ only. Images with alpha (see - * vips_image_hasalpha()) shrink with pixels scaled by alpha to avoid fringing. + * [method@Image.hasalpha]) shrink with pixels scaled by alpha to avoid fringing. * - * This is a compatibility stub that just calls vips_region_shrink_method(). + * This is a compatibility stub that just calls [method@Region.shrink_method]. * - * See also: vips_region_shrink_method(). + * ::: seealso + * [method@Region.shrink_method]. */ int vips_region_shrink(VipsRegion *from, VipsRegion *to, const VipsRect *target) @@ -1624,8 +1616,7 @@ vips_region_generate(VipsRegion *reg, void *a) if (im->generate_fn(reg, reg->seq, im->client1, im->client2, &stop)) return -1; if (stop) { - vips_error("vips_region_generate", - "%s", _("stop requested")); + vips_error("vips_region_generate", "%s", _("stop requested")); return -1; } @@ -1635,20 +1626,21 @@ vips_region_generate(VipsRegion *reg, void *a) /** * vips_region_prepare: * @reg: region to prepare - * @r: #VipsRect of pixels you need to be able to address + * @r: [struct@Rect] of pixels you need to be able to address * - * vips_region_prepare() fills @reg with pixels. After calling, - * you can address at least the area @r with VIPS_REGION_ADDR() and get + * [method@Region.prepare] fills @reg with pixels. After calling, + * you can address at least the area @r with [func@REGION_ADDR] and get * valid pixels. * - * vips_region_prepare() runs in-line, that is, computation is done by + * [method@Region.prepare] runs in-line, that is, computation is done by * the calling thread, no new threads are involved, and computation * blocks until the pixels are ready. * - * Use vips_sink_screen() to calculate an area of pixels in the + * Use [method@Image.sink_screen] to calculate an area of pixels in the * background. * - * See also: vips_sink_screen(), vips_region_prepare_to(). + * ::: seealso + * [method@Image.sink_screen], [method@Region.prepare_to]. * * Returns: 0 on success, or -1 on error. */ @@ -1731,8 +1723,7 @@ vips_region_prepare_to_generate(VipsRegion *reg, VipsPel *p; if (!im->generate_fn) { - vips_error("vips_region_prepare_to", - "%s", _("incomplete header")); + vips_error("vips_region_prepare_to", "%s", _("incomplete header")); return -1; } @@ -1762,22 +1753,23 @@ vips_region_prepare_to_generate(VipsRegion *reg, * vips_region_prepare_to: * @reg: region to prepare * @dest: region to write to - * @r: #VipsRect of pixels you need to be able to address + * @r: [struct@Rect] of pixels you need to be able to address * @x: position of @r in @dest * @y: position of @r in @dest * - * Like vips_region_prepare(): fill @reg with the pixels in area @r. + * Like [method@Region.prepare]: fill @reg with the pixels in area @r. * - * Unlike vips_region_prepare(), rather than writing the result to @reg, the + * Unlike [method@Region.prepare], rather than writing the result to @reg, the * pixels are written into @dest at offset @x, @y. * - * Also unlike vips_region_prepare(), @dest is not set up for writing for - * you with vips_region_buffer(). You can + * Also unlike [method@Region.prepare], @dest is not set up for writing for + * you with [method@Region.buffer]. You can * point @dest at anything, and pixels really will be written there. - * This makes vips_region_prepare_to() useful for making the ends of + * This makes [method@Region.prepare_to] useful for making the ends of * pipelines. * - * See also: vips_region_prepare(), vips_sink_disc(). + * ::: seealso + * [method@Region.prepare], [method@Image.sink_disc]. * * Returns: 0 on success, or -1 on error */ @@ -1826,8 +1818,7 @@ vips_region_prepare_to(VipsRegion *reg, /* Test that dest->valid is large enough. */ if (!vips_rect_includesrect(&dest->valid, &wanted)) { - vips_error("vips_region_prepare_to", - "%s", _("dest too small")); + vips_error("vips_region_prepare_to", "%s", _("dest too small")); return -1; } @@ -1884,8 +1875,7 @@ vips_region_prepare_to(VipsRegion *reg, * function, we are outputting. */ if (im->generate_fn) { - if (vips_region_prepare_to_generate(reg, - dest, &final, x, y)) + if (vips_region_prepare_to_generate(reg, dest, &final, x, y)) return -1; } else { @@ -1936,9 +1926,10 @@ vips_region_prepare_many(VipsRegion **reg, const VipsRect *r) * @height: area of pixels to fetch * * Generate an area of pixels and return a copy. The result must be freed - * with g_free(). The requested area must be completely inside the image. + * with [func@GLib.free]. The requested area must be completely inside the + * image. * - * This is equivalent to vips_region_prepare(), followed by a memcpy. It is + * This is equivalent to [method@Region.prepare], followed by a memcpy. It is * convenient for language bindings. * * Returns: A copy of the pixel data. @@ -2020,13 +2011,14 @@ vips_region_height(VipsRegion *region) * @reg: region to invalidate * * Mark a region as containing invalid pixels. Calling this function means - * that the next time vips_region_prepare() is called, the region will be + * that the next time [method@Region.prepare] is called, the region will be * recalculated. * - * This is faster than calling vips_image_invalidate_all(), but obviously only + * This is faster than calling [method@Image.invalidate_all], but obviously only * affects a single region. * - * See also: vips_image_invalidate_all(), vips_region_prepare(). + * ::: seealso + * [method@Image.invalidate_all], [method@Region.prepare]. */ void vips_region_invalidate(VipsRegion *reg) @@ -2055,13 +2047,13 @@ vips_region_dump_all(void) { size_t alive; - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); alive = 0; printf("%d regions in vips\n", g_slist_length(vips__regions_all)); vips_slist_map2(vips__regions_all, (VipsSListMap2Fn) vips_region_dump_all_cb, &alive, NULL); printf("%gMB alive\n", alive / (1024 * 1024.0)); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } #endif /*VIPS_DEBUG*/ @@ -2073,12 +2065,12 @@ vips__region_count_pixels(VipsRegion *region, const char *nickname) VipsImagePixels *pixels = g_object_get_qdata(G_OBJECT(image), vips__image_pixels_quark); - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); if (!pixels->tpels) pixels->tpels = VIPS_IMAGE_N_PELS(image); if (!pixels->nickname) pixels->nickname = nickname; pixels->npels += region->valid.width * region->valid.height; - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } #endif /*DEBUG_LEAK*/ diff --git a/libvips/iofuncs/reorder.c b/libvips/iofuncs/reorder.c index 003d0441eb..0e18863799 100644 --- a/libvips/iofuncs/reorder.c +++ b/libvips/iofuncs/reorder.c @@ -318,15 +318,16 @@ vips__reorder_set_input(VipsImage *image, VipsImage **in) * vips_reorder_prepare_many: (method) * @image: the image that's being written * @regions: (array): the set of regions to prepare - * @r: the #VipsRect to prepare on each region + * @r: the [struct@Rect] to prepare on each region * - * vips_reorder_prepare_many() runs vips_region_prepare() on each region in - * @regions, requesting the pixels in @r. + * [method@Image.reorder_prepare_many] runs [method@Region.prepare] on each + * region in @regions, requesting the pixels in @r. * * It tries to request the regions in the order which will cause least * recomputation. This can give a large speedup, in some cases. * - * See also: vips_region_prepare(), vips_reorder_margin_hint(). + * ::: seealso + * [method@Region.prepare], [method@Image.reorder_margin_hint]. * * Returns: 0 on success, or -1 on error. */ @@ -353,15 +354,16 @@ vips_reorder_prepare_many(VipsImage *image, VipsRegion **regions, VipsRect *r) * @image: the image to hint on * @margin: the size of the margin this operation has added * - * vips_reorder_margin_hint() sets a hint that @image contains a margin, that - * is, that each vips_region_prepare() on @image will request a slightly larger - * region from it's inputs. A good value for @margin is (width * height) for - * the window the operation uses. + * [method@Image.reorder_margin_hint] sets a hint that @image contains a + * margin, that is, that each [method@Region.prepare] on @image will request + * a slightly larger region from it's inputs. A good value for @margin is + * (width * height) for the window the operation uses. * - * This information is used by vips_image_prepare_many() to attempt to reorder - * computations to minimise recomputation. + * This information is used by [method@Image.reorder_prepare_many] to attempt to + * reorder computations to minimise recomputation. * - * See also: vips_image_prepare_many(). + * ::: seealso + * [method@Image.reorder_prepare_many]. */ void vips_reorder_margin_hint(VipsImage *image, int margin) diff --git a/libvips/iofuncs/sbuf.c b/libvips/iofuncs/sbuf.c index 7a7d92664e..bc9bedf29a 100644 --- a/libvips/iofuncs/sbuf.c +++ b/libvips/iofuncs/sbuf.c @@ -56,16 +56,11 @@ #include /** - * SECTION: sbuf - * @short_description: buffered read from a source - * @stability: Stable - * @see_also: foreign - * @include: vips/vips.h - * @title: VipsSbuf + * VipsSbuf: * - * #VipsSbuf wraps up a #VipsSource and provides a set of calls for - * text-oriented buffered reading. You can fetch lines of text, skip - * whitespace, and so on. + * A [class@Sbuf] provides a buffered reading interface for a [class@Source]. + * + * You can fetch lines of text, skip whitespace, and so on. * * It is useful for implementing things like CSV readers, for example. */ @@ -104,9 +99,9 @@ vips_sbuf_init(VipsSbuf *sbuf) * vips_sbuf_new_from_source: * @source: source to operate on * - * Create a VipsSbuf wrapping a source. + * Create a [class@Sbuf] wrapping a source. * - * Returns: a new #VipsSbuf + * Returns: a new [class@Sbuf] */ VipsSbuf * vips_sbuf_new_from_source(VipsSource *source) @@ -132,7 +127,7 @@ vips_sbuf_new_from_source(VipsSource *source) * @sbuf: source to operate on * * Discard the input buffer and reset the read point. You must call this - * before using read or seek on the underlying #VipsSource class. + * before using read or seek on the underlying [class@Source] class. */ void vips_sbuf_unbuffer(VipsSbuf *sbuf) @@ -180,7 +175,7 @@ vips_sbuf_refill(VipsSbuf *sbuf) * * Fetch the next character from the source. * - * If you can, use the macro VIPS_SBUF_GETC() instead for speed. + * If you can, use the macro [func@SBUF_GETC] instead for speed. * * Returns: the next char from @sbuf, -1 on read error or EOF. */ @@ -209,12 +204,12 @@ vips_sbuf_getc(VipsSbuf *sbuf) * vips_sbuf_ungetc: * @sbuf: source to operate on * - * The opposite of vips_sbuf_getc(): undo the previous getc. + * The opposite of [method@Sbuf.getc]: undo the previous getc. * * unget more than one character is undefined. Unget at the start of the file * does nothing. * - * If you can, use the macro VIPS_SBUF_UNGETC() instead for speed. + * If you can, use the macro [func@SBUF_UNGETC] instead for speed. */ void vips_sbuf_ungetc(VipsSbuf *sbuf) @@ -227,7 +222,7 @@ vips_sbuf_ungetc(VipsSbuf *sbuf) * VIPS_SBUF_UNGETC: * @sbuf: source to operate on * - * The opposite of vips_sbuf_getc(): undo the previous getc. + * The opposite of [method@Sbuf.getc]: undo the previous getc. * * unget more than one character is undefined. Unget at the start of the file * does nothing. @@ -295,7 +290,7 @@ vips_sbuf_require(VipsSbuf *sbuf, int require) * @require: need this many characters * * Make sure at least @require characters are available for - * VIPS_SBUF_PEEK() and VIPS_SBUF_FETCH(). + * [func@SBUF_PEEK] and [func@SBUF_FETCH]. * * Returns: 0 on success, -1 on read error or EOF. */ @@ -304,7 +299,7 @@ vips_sbuf_require(VipsSbuf *sbuf, int require) * VIPS_SBUF_PEEK: * @sbuf: source to operate on * - * After a successful VIPS_SBUF_REQUIRE(), you can index this to get + * After a successful [func@SBUF_REQUIRE], you can index this to get * require characters of input. * * Returns: a pointer to the next require characters of input. @@ -314,7 +309,7 @@ vips_sbuf_require(VipsSbuf *sbuf, int require) * VIPS_SBUF_FETCH: * @sbuf: source to operate on * - * After a successful VIPS_SBUF_REQUIRE(), you can use this require times + * After a successful [func@SBUF_REQUIRE], you can use this require times * to fetch characters of input. * * Returns: the next input character. @@ -332,7 +327,7 @@ vips_sbuf_require(VipsSbuf *sbuf, int require) * * If the line is longer than some arbitrary (but large) limit, it is * truncated. If you need to be able to read very long lines, use the - * slower vips_sbuf_get_line_copy(). + * slower [method@Sbuf.get_line_copy]. * * The return value is owned by @sbuf and must not be freed. It * is valid until the next get call to @sbuf. @@ -398,9 +393,9 @@ vips_sbuf_get_line(VipsSbuf *sbuf) * line character (or characters, for DOS files) are removed, and the string * is terminated with a null (`\0` character). * - * The return result must be freed with g_free(). + * The return result must be freed with [func@GLib.free]. * - * This is slower than vips_sbuf_get_line(), but can work with lines of + * This is slower than [method@Sbuf.get_line], but can work with lines of * any length. * * Returns: the next line of text, or NULL on EOF or read error. diff --git a/libvips/iofuncs/semaphore.c b/libvips/iofuncs/semaphore.c index cf7dcd6228..aaf5dbf613 100644 --- a/libvips/iofuncs/semaphore.c +++ b/libvips/iofuncs/semaphore.c @@ -48,11 +48,9 @@ #include #include -#include #include #include -#include #include void @@ -60,15 +58,17 @@ vips_semaphore_init(VipsSemaphore *s, int v, char *name) { s->v = v; s->name = name; - s->mutex = vips_g_mutex_new(); - s->cond = vips_g_cond_new(); + g_mutex_init(&s->mutex); + s->cond = g_new(GCond, 1); + g_cond_init(s->cond); } void vips_semaphore_destroy(VipsSemaphore *s) { - VIPS_FREEF(vips_g_mutex_free, s->mutex); - VIPS_FREEF(vips_g_cond_free, s->cond); + g_mutex_clear(&s->mutex); + g_cond_clear(s->cond); + g_free(s->cond); } /* Add n to the semaphore and signal any threads that are blocked waiting @@ -79,7 +79,7 @@ vips_semaphore_upn(VipsSemaphore *s, int n) { int value_after_op; - g_mutex_lock(s->mutex); + g_mutex_lock(&s->mutex); s->v += n; value_after_op = s->v; @@ -90,7 +90,7 @@ vips_semaphore_upn(VipsSemaphore *s, int n) g_cond_signal(s->cond); else g_cond_broadcast(s->cond); - g_mutex_unlock(s->mutex); + g_mutex_unlock(&s->mutex); #ifdef DEBUG_IO printf("vips_semaphore_upn(\"%s\",%d) = %d\n", @@ -120,15 +120,15 @@ vips__semaphore_downn_until(VipsSemaphore *s, int n, gint64 end_time) VIPS_GATE_START("vips__semaphore_downn_until: wait"); - g_mutex_lock(s->mutex); + g_mutex_lock(&s->mutex); while (s->v < n) { if (end_time == -1) - vips__worker_cond_wait(s->cond, s->mutex); - else if (!g_cond_wait_until(s->cond, s->mutex, end_time)) { + vips__worker_cond_wait(s->cond, &s->mutex); + else if (!g_cond_wait_until(s->cond, &s->mutex, end_time)) { /* timeout has passed. */ - g_mutex_unlock(s->mutex); + g_mutex_unlock(&s->mutex); VIPS_GATE_STOP("vips__semaphore_downn_until: wait"); return -1; @@ -138,7 +138,7 @@ vips__semaphore_downn_until(VipsSemaphore *s, int n, gint64 end_time) s->v -= n; value_after_op = s->v; - g_mutex_unlock(s->mutex); + g_mutex_unlock(&s->mutex); #ifdef DEBUG_IO printf("vips__semaphore_downn_until(\"%s\",%d): %d\n", diff --git a/libvips/iofuncs/sink.c b/libvips/iofuncs/sink.c index 5ae8ea1e92..8d94bdccc1 100644 --- a/libvips/iofuncs/sink.c +++ b/libvips/iofuncs/sink.c @@ -44,7 +44,6 @@ #include #include -#include #include #include @@ -238,7 +237,7 @@ sink_area_allocate_fn(VipsThreadState *state, void *a, gboolean *stop) /* Add the number of pixels we've just allocated to progress. */ - sink_base->processed += state->pos.width * state->pos.height; + sink_base->processed += (guint64) state->pos.width * state->pos.height; return 0; } @@ -447,9 +446,9 @@ vips_sink_base_progress(void *a) * @im: scan over this image * @tile_width: tile width * @tile_height: tile height - * @start_fn: start sequences with this function - * @generate_fn: generate pixels with this function - * @stop_fn: stop sequences with this function + * @start_fn: (scope async): start sequences with this function + * @generate_fn: (scope async): generate pixels with this function + * @stop_fn: (scope async): stop sequences with this function * @a: user data * @b: user data * @@ -461,7 +460,8 @@ vips_sink_base_progress(void *a) * image edges). This is handy for things like writing a tiled TIFF image, * where tiles have to be generated with a certain size. * - * See also: vips_sink(), vips_get_tile_size(). + * ::: seealso + * [method@Image.sink], [method@Image.get_tile_size]. * * Returns: 0 on success, or -1 on error. */ @@ -514,21 +514,22 @@ vips_sink_tile(VipsImage *im, /** * vips_sink: (method) * @im: scan over this image - * @start_fn: start sequences with this function - * @generate_fn: generate pixels with this function - * @stop_fn: stop sequences with this function + * @start_fn: (scope async): start sequences with this function + * @generate_fn: (scope async): generate pixels with this function + * @stop_fn: (scope async): stop sequences with this function * @a: user data * @b: user data * * Loops over an image. @generate_fn is called for every pixel in - * the image, with - * the @reg argument being a region of calculated pixels. vips_sink() is - * used to implement operations like vips_avg() which have no image output. + * the image, with the @reg argument being a region of calculated pixels. + * [method@Image.sink] is used to implement operations like + * [method@Image.avg] which have no image output. * * Each set of pixels is sized according to the requirements of the image * pipeline that generated @im. * - * See also: vips_image_generate(), vips_image_new(). + * ::: seealso + * [method@Image.generate], [ctor@Image.new]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/iofuncs/sink.h b/libvips/iofuncs/sink.h index be5835aa84..a21067f6e0 100644 --- a/libvips/iofuncs/sink.h +++ b/libvips/iofuncs/sink.h @@ -39,7 +39,6 @@ extern "C" { #endif /*__cplusplus*/ #include -#include /* Base for sink.c / sinkdisc.c / sinkmemory.c */ diff --git a/libvips/iofuncs/sinkdisc.c b/libvips/iofuncs/sinkdisc.c index 236c271ac3..83eb615dd7 100644 --- a/libvips/iofuncs/sinkdisc.c +++ b/libvips/iofuncs/sinkdisc.c @@ -59,8 +59,6 @@ #include #include -#include -#include #include #include "sink.h" @@ -98,6 +96,20 @@ typedef struct _Write { void *a; } Write; +static int +write_check_error(Write *write) +{ + if (write->buf->write_errno || + write->buf_back->write_errno) { + vips_error_system(write->buf->write_errno ? + write->buf->write_errno : write->buf_back->write_errno, + "wbuffer_write", "%s", _("write failed")); + return -1; + } + + return 0; +} + /* Our per-thread state ... we need to also track the buffer that pos is * supposed to write to. */ @@ -259,13 +271,8 @@ wbuffer_flush(Write *write) if (write->buf->area.top > 0) { vips_semaphore_down(&write->buf_back->done); - /* Previous write succeeded? - */ - if (write->buf_back->write_errno) { - vips_error_system(write->buf_back->write_errno, - "wbuffer_write", "%s", _("write failed")); + if (write_check_error(write)) return -1; - } } /* Set the background writer going for this buffer. @@ -410,7 +417,7 @@ wbuffer_allocate_fn(VipsThreadState *state, void *a, gboolean *stop) /* Add the number of pixels we've just allocated to progress. */ - sink_base->processed += state->pos.width * state->pos.height; + sink_base->processed += (guint64) state->pos.width * state->pos.height; return 0; } @@ -467,9 +474,9 @@ write_free(Write *write) * @a: client data * * The function should write the pixels in @area from @region. @a is the - * value passed into vips_sink_disc(). + * value passed into [method@Image.sink_disc]. * - * See also: vips_sink_disc(). + * See also: [method@Image.sink_disc]. * * Returns: 0 on success, -1 on error. */ @@ -477,10 +484,10 @@ write_free(Write *write) /** * vips_sink_disc: (method) * @im: image to process - * @write_fn: (scope call): called for every batch of pixels - * @a: (closure write_fn): client data + * @write_fn: (scope call) (closure a): called for every batch of pixels + * @a: client data * - * vips_sink_disc() loops over @im, top-to-bottom, generating it in sections. + * [method@Image.sink_disc] loops over @im, top-to-bottom, generating it in sections. * As each section is produced, @write_fn is called. * * @write_fn is always called single-threaded (though not always from the same @@ -488,10 +495,10 @@ write_free(Write *write) * sections in top-to-bottom order, and there are never any gaps. * * This operation is handy for making image sinks which output to things like - * disc files. Things like vips_jpegsave(), for example, use this to write + * disc files. Things like [method@Image.jpegsave], for example, use this to write * images to files in JPEG format. * - * See also: vips_concurrency_set(). + * See also: [func@concurrency_set]. * * Returns: 0 on success, -1 on error. */ @@ -533,6 +540,10 @@ vips_sink_disc(VipsImage *im, VipsRegionWrite write_fn, void *a) vips_image_posteval(im); + /* The final write might have failed, pick up any error code. + */ + result |= write_check_error(&write); + write_free(&write); vips_image_minimise_all(im); diff --git a/libvips/iofuncs/sinkmemory.c b/libvips/iofuncs/sinkmemory.c index 7808fc95f6..2abf833af7 100644 --- a/libvips/iofuncs/sinkmemory.c +++ b/libvips/iofuncs/sinkmemory.c @@ -51,8 +51,6 @@ #include #include -#include -#include #include #include "sink.h" @@ -244,7 +242,7 @@ sink_memory_area_allocate_fn(VipsThreadState *state, void *a, gboolean *stop) /* Add the number of pixels we've just allocated to progress. */ - sink_base->processed += state->pos.width * state->pos.height; + sink_base->processed += (guint64) state->pos.width * state->pos.height; return 0; } @@ -316,7 +314,9 @@ sink_memory_init(SinkMemory *memory, VipsImage *image) * Loops over @im, generating it to a memory buffer attached to @im. It is * used by vips to implement writing to a memory buffer. * - * See also: vips_sink(), vips_get_tile_size(), vips_image_new_memory(). + * ::: seealso + * [method@Image.sink], [method@Image.get_tile_size], + * [ctor@Image.new_memory]. * * Returns: 0 on success, or -1 on error. */ diff --git a/libvips/iofuncs/sinkscreen.c b/libvips/iofuncs/sinkscreen.c index d881640e72..5e9ade24bc 100644 --- a/libvips/iofuncs/sinkscreen.c +++ b/libvips/iofuncs/sinkscreen.c @@ -69,7 +69,6 @@ #endif /*HAVE_UNISTD_H*/ #include -#include #include #include @@ -111,7 +110,7 @@ typedef struct _Render { gatomicrefcount ref_count; #else int ref_count; - GMutex *ref_count_lock; + GMutex ref_count_lock; #endif /* Parameters. @@ -126,9 +125,17 @@ typedef struct _Render { VipsSinkNotify notify; /* Tell caller about paints here */ void *a; + /* This render has it's own threadpool and is not on the shared list. + * + * This private threadpool needs a semaphore to wait on for dirty tiles + * to arrive. + */ + gboolean private_threadpool; + VipsSemaphore dirty_sem; + /* Lock here before reading or modifying the tile structure. */ - GMutex *lock; + GMutex lock; /* Tile cache. */ @@ -179,7 +186,7 @@ static gboolean render_kill = FALSE; /* All the renders with dirty tiles, and a semaphore that the bg render thread * waits on. */ -static GMutex *render_dirty_lock = NULL; +static GMutex render_dirty_lock; static GSList *render_dirty_all = NULL; static VipsSemaphore n_render_dirty_sem; @@ -205,8 +212,7 @@ render_thread_state_init(RenderThreadState *state) static VipsThreadState * render_thread_state_new(VipsImage *im, void *a) { - return VIPS_THREAD_STATE(vips_object_new( - render_thread_state_get_type(), + return VIPS_THREAD_STATE(vips_object_new(render_thread_state_get_type(), vips_thread_state_set, im, a)); } @@ -232,7 +238,7 @@ render_free(Render *render) g_assert(render->ref_count == 0); #endif - g_mutex_lock(render_dirty_lock); + g_mutex_lock(&render_dirty_lock); if (g_slist_find(render_dirty_all, render)) { render_dirty_all = g_slist_remove(render_dirty_all, render); @@ -241,12 +247,15 @@ render_free(Render *render) * render_dirty_all is NULL. */ } - g_mutex_unlock(render_dirty_lock); + g_mutex_unlock(&render_dirty_lock); #if !GLIB_CHECK_VERSION(2, 58, 0) - vips_g_mutex_free(render->ref_count_lock); + g_mutex_clear(&render->ref_count_lock); #endif - vips_g_mutex_free(render->lock); + g_mutex_clear(&render->lock); + + if (render->private_threadpool) + vips_semaphore_destroy(&render->dirty_sem); vips_slist_map2(render->all, (VipsSListMap2Fn) tile_free, NULL, NULL); VIPS_FREEF(g_slist_free, render->all); @@ -274,10 +283,10 @@ render_ref(Render *render) g_assert(!g_atomic_ref_count_compare(&render->ref_count, 0)); g_atomic_ref_count_inc(&render->ref_count); #else - g_mutex_lock(render->ref_count_lock); + g_mutex_lock(&render->ref_count_lock); g_assert(render->ref_count != 0); render->ref_count += 1; - g_mutex_unlock(render->ref_count_lock); + g_mutex_unlock(&render->ref_count_lock); #endif return 0; @@ -292,11 +301,11 @@ render_unref(Render *render) g_assert(!g_atomic_ref_count_compare(&render->ref_count, 0)); kill = g_atomic_ref_count_dec(&render->ref_count); #else - g_mutex_lock(render->ref_count_lock); + g_mutex_lock(&render->ref_count_lock); g_assert(render->ref_count > 0); render->ref_count -= 1; kill = render->ref_count == 0; - g_mutex_unlock(render->ref_count_lock); + g_mutex_unlock(&render->ref_count_lock); #endif if (kill) @@ -341,8 +350,7 @@ render_tile_dirty_reuse(Render *render) g_assert(tile->dirty); tile->dirty = FALSE; - VIPS_DEBUG_MSG("render_tile_get_dirty_reuse: reusing dirty %p\n", - tile); + VIPS_DEBUG_MSG("render_tile_get_dirty_reuse: reusing dirty %p\n", tile); } return tile; @@ -387,9 +395,10 @@ render_allocate(VipsThreadState *state, void *a, gboolean *stop) { Render *render = (Render *) a; RenderThreadState *rstate = (RenderThreadState *) state; + Tile *tile; - g_mutex_lock(render->lock); + g_mutex_lock(&render->lock); if (render_reschedule || !(tile = render_tile_dirty_get(render))) { @@ -400,7 +409,7 @@ render_allocate(VipsThreadState *state, void *a, gboolean *stop) else rstate->tile = tile; - g_mutex_unlock(render->lock); + g_mutex_unlock(&render->lock); return 0; } @@ -419,8 +428,7 @@ render_work(VipsThreadState *state, void *a) if (vips_region_prepare_to(state->reg, tile->region, &tile->area, tile->area.left, tile->area.top)) { - VIPS_DEBUG_MSG_RED("render_work: " - "vips_region_prepare_to() failed: %s\n", + VIPS_DEBUG_MSG_RED("render_work: vips_region_prepare_to() failed: %s\n", vips_error_buffer()); return -1; } @@ -442,26 +450,21 @@ vips__render_shutdown(void) { /* We may come here without having inited. */ - if (render_dirty_lock) { - g_mutex_lock(render_dirty_lock); + if (render_thread) { + g_mutex_lock(&render_dirty_lock); - if (render_thread) { - GThread *thread; + GThread *thread; - thread = render_thread; - render_reschedule = TRUE; - render_kill = TRUE; + thread = render_thread; + render_reschedule = TRUE; + render_kill = TRUE; - g_mutex_unlock(render_dirty_lock); + g_mutex_unlock(&render_dirty_lock); - vips_semaphore_up(&n_render_dirty_sem); + vips_semaphore_up(&n_render_dirty_sem); - (void) g_thread_join(thread); - } - else - g_mutex_unlock(render_dirty_lock); + (void) g_thread_join(thread); - VIPS_FREEF(vips_g_mutex_free, render_dirty_lock); vips_semaphore_destroy(&n_render_dirty_sem); } } @@ -477,23 +480,28 @@ render_dirty_sort(Render *a, Render *b, void *user_data) static void render_dirty_put(Render *render) { - g_mutex_lock(render_dirty_lock); - - if (render->dirty) { - if (!g_slist_find(render_dirty_all, render)) { - render_dirty_all = g_slist_prepend(render_dirty_all, - render); - render_dirty_all = g_slist_sort(render_dirty_all, - (GCompareFunc) render_dirty_sort); - - /* Tell the bg render thread we have one more dirty - * render on there. - */ - vips_semaphore_up(&n_render_dirty_sem); + if (render->private_threadpool) + // set our private renderer going + vips_semaphore_up(&render->dirty_sem); + else { + // add to the worklist for thwe global renderer + g_mutex_lock(&render_dirty_lock); + + if (render->dirty) { + if (!g_slist_find(render_dirty_all, render)) { + render_dirty_all = g_slist_prepend(render_dirty_all, render); + render_dirty_all = g_slist_sort(render_dirty_all, + (GCompareFunc) render_dirty_sort); + + /* Tell the bg render thread we have one more dirty + * render on there. + */ + vips_semaphore_up(&n_render_dirty_sem); + } } - } - g_mutex_unlock(render_dirty_lock); + g_mutex_unlock(&render_dirty_lock); + } } static guint @@ -529,13 +537,21 @@ render_close_cb(VipsImage *image, Render *render) */ render->shutdown = TRUE; - render_unref(render); + if (render->private_threadpool) { + /* Nudge the bg thread (if any) for this pool. + */ + VIPS_DEBUG_MSG_GREEN("render_close_cb: nudge private worker\n"); + vips_semaphore_up(&render->dirty_sem); + } + else { + /* If this render is being worked on, we want to jog the bg thread, + * make it drop it's ref and think again. + */ + VIPS_DEBUG_MSG_GREEN("render_close_cb: reschedule\n"); + render_reschedule = TRUE; + } - /* If this render is being worked on, we want to jog the bg thread, - * make it drop it's ref and think again. - */ - VIPS_DEBUG_MSG_GREEN("render_close_cb: reschedule\n"); - render_reschedule = TRUE; + render_unref(render); } static Render * @@ -561,7 +577,7 @@ render_new(VipsImage *in, VipsImage *out, VipsImage *mask, g_atomic_ref_count_init(&render->ref_count); #else render->ref_count = 1; - render->ref_count_lock = vips_g_mutex_new(); + g_mutex_init(&render->ref_count_lock); #endif render->in = in; @@ -574,7 +590,12 @@ render_new(VipsImage *in, VipsImage *out, VipsImage *mask, render->notify = notify; render->a = a; - render->lock = vips_g_mutex_new(); + if (render->priority < 0) { + render->private_threadpool = TRUE; + vips_semaphore_init(&render->dirty_sem, 0, "dirty_sem"); + } + + g_mutex_init(&render->lock); render->all = NULL; render->ntiles = 0; @@ -588,12 +609,10 @@ render_new(VipsImage *in, VipsImage *out, VipsImage *mask, /* Both out and mask must close before we can free the render. */ - g_signal_connect(out, "close", - G_CALLBACK(render_close_cb), render); + g_signal_connect(out, "close", G_CALLBACK(render_close_cb), render); if (mask) { - g_signal_connect(mask, "close", - G_CALLBACK(render_close_cb), render); + g_signal_connect(mask, "close", G_CALLBACK(render_close_cb), render); render_ref(render); } @@ -737,13 +756,13 @@ tile_queue(Tile *tile, VipsRegion *reg) * This tile won't get pulled out from under us since it's not * marked as "painted", and it's not on the dirty list. */ - g_mutex_unlock(render->lock); + g_mutex_unlock(&render->lock); if (vips_region_prepare_to(reg, tile->region, &tile->area, tile->area.left, tile->area.top)) VIPS_DEBUG_MSG_RED("tile_queue: prepare failed\n"); - g_mutex_lock(render->lock); + g_mutex_lock(&render->lock); tile->painted = TRUE; } @@ -765,13 +784,10 @@ render_tile_get_painted(Render *render) Tile *tile; tile = NULL; - g_hash_table_foreach(render->tiles, - (GHFunc) tile_test_clean_ticks, &tile); + g_hash_table_foreach(render->tiles, (GHFunc) tile_test_clean_ticks, &tile); - if (tile) { - VIPS_DEBUG_MSG("render_tile_get_painted: reusing painted %p\n", - tile); - } + if (tile) + VIPS_DEBUG_MSG("render_tile_get_painted: reusing painted %p\n", tile); return tile; } @@ -850,8 +866,7 @@ tile_copy(Tile *tile, VipsRegion *to) tile, tile->area.left, tile->area.top); for (y = ovlap.top; y < VIPS_RECT_BOTTOM(&ovlap); y++) { - VipsPel *p = VIPS_REGION_ADDR(tile->region, - ovlap.left, y); + VipsPel *p = VIPS_REGION_ADDR(tile->region, ovlap.left, y); VipsPel *q = VIPS_REGION_ADDR(to, ovlap.left, y); memcpy(q, p, len); @@ -882,11 +897,10 @@ image_fill(VipsRegion *out, void *seq, void *a, void *b, gboolean *stop) int xs = (r->left / tile_width) * tile_width; int ys = (r->top / tile_height) * tile_height; - VIPS_DEBUG_MSG("image_fill: left = %d, top = %d, " - "width = %d, height = %d\n", + VIPS_DEBUG_MSG("image_fill: left = %d, top = %d, width = %d, height = %d\n", r->left, r->top, r->width, r->height); - g_mutex_lock(render->lock); + g_mutex_lock(&render->lock); /* @@ -912,7 +926,7 @@ image_fill(VipsRegion *out, void *seq, void *a, void *b, gboolean *stop) VIPS_DEBUG_MSG_RED("image_fill: argh!\n"); } - g_mutex_unlock(render->lock); + g_mutex_unlock(&render->lock); return 0; } @@ -934,11 +948,10 @@ mask_fill(VipsRegion *out, void *seq, void *a, void *b, gboolean *stop) int xs = (r->left / tile_width) * tile_width; int ys = (r->top / tile_height) * tile_height; - VIPS_DEBUG_MSG("mask_fill: left = %d, top = %d, " - "width = %d, height = %d\n", + VIPS_DEBUG_MSG("mask_fill: left = %d, top = %d, width = %d, height = %d\n", r->left, r->top, r->width, r->height); - g_mutex_lock(render->lock); + g_mutex_lock(&render->lock); for (y = ys; y < VIPS_RECT_BOTTOM(r); y += tile_height) for (x = xs; x < VIPS_RECT_RIGHT(r); x += tile_width) { @@ -963,7 +976,7 @@ mask_fill(VipsRegion *out, void *seq, void *a, void *b, gboolean *stop) vips_region_paint(out, &area, value); } - g_mutex_unlock(render->lock); + g_mutex_unlock(&render->lock); return 0; } @@ -979,7 +992,7 @@ render_dirty_get(void) */ vips_semaphore_down(&n_render_dirty_sem); - g_mutex_lock(render_dirty_lock); + g_mutex_lock(&render_dirty_lock); /* Just take the head of the jobs list ... we sort when we add. */ @@ -995,7 +1008,7 @@ render_dirty_get(void) render_dirty_all = g_slist_remove(render_dirty_all, render); } - g_mutex_unlock(render_dirty_lock); + g_mutex_unlock(&render_dirty_lock); return render; } @@ -1043,20 +1056,69 @@ render_thread_main(void *client) return NULL; } +static int +render_allocate_private(VipsThreadState *state, void *a, gboolean *stop) +{ + Render *render = (Render *) a; + RenderThreadState *rstate = (RenderThreadState *) state; + + /* Wait for a dirty tile to arrive on this render. + */ + vips_semaphore_down(&render->dirty_sem); + + /* The mask or image is closing, we must exit. + */ + if (render->shutdown) { + *stop = TRUE; + rstate->tile = NULL; + return 0; + } + + /* Get the dirty tile, if any. + */ + g_mutex_lock(&render->lock); + rstate->tile = render_tile_dirty_get(render); + VIPS_DEBUG_MSG_AMBER("render_allocate_private: allocated tile %p\n", + rstate->tile); + g_mutex_unlock(&render->lock); + + return 0; +} + +/* A worker for a private render. + */ +static void +render_work_private(void *data, void *null) +{ + VIPS_DEBUG_MSG_AMBER("render_work_private: start\n"); + + Render *render = (Render *) data; + + // this will quit on ->shutdown == TRUE + if (vips_threadpool_run(render->in, + render_thread_state_new, + render_allocate_private, + render_work, + NULL, + render)) + VIPS_DEBUG_MSG_RED("render_work_private: threadpool_run failed\n"); + + render_unref(render); + + VIPS_DEBUG_MSG_AMBER("render_work_private: stop\n"); +} + static void * vips__sink_screen_once(void *data) { g_assert(!render_thread); - g_assert(!render_dirty_lock); - render_dirty_lock = vips_g_mutex_new(); vips_semaphore_init(&n_render_dirty_sem, 0, "n_render_dirty"); /* Don't use vips_thread_execute(), since this thread will only be * ended by vips_shutdown, and that isn't always called. */ - render_thread = vips_g_thread_new("sink_screen", - render_thread_main, NULL); + render_thread = vips_g_thread_new("sink_screen", render_thread_main, NULL); return NULL; } @@ -1070,44 +1132,44 @@ vips__sink_screen_once(void *data) * @tile_height: tile height * @max_tiles: maximum tiles to cache * @priority: rendering priority - * @notify_fn: (scope call) (nullable): pixels are ready notification callback - * @a: (closure notify_fn) (nullable): client data for callback + * @notify_fn: (scope call) (closure a) (nullable): pixels are ready notification callback + * @a: (nullable): client data for callback + * + * This operation renders @in in the background, making pixels available + * on @out as they are calculated. The @notify_fn callback is run every + * time a new set of pixels are available. Calculated pixels are kept in + * a cache with tiles sized @tile_width by @tile_height pixels and with at + * most @max_tiles tiles. If @max_tiles is -1, the cache is of unlimited + * size (up to the maximum image * size). The @mask image is a one-band + * uchar image and has 255 for pixels which are currently in cache and 0 + * for uncalculated pixels. * - * This operation renders @in in the background, making pixels available on - * @out as they are calculated. The @notify_fn callback is run every time a new - * set of pixels are available. Calculated pixels are kept in a cache with - * tiles sized @tile_width by @tile_height pixels and with at most @max_tiles - * tiles. - * If @max_tiles is -1, the cache is of unlimited size (up to the maximum image - * size). - * The @mask image is a one-band uchar image and has 255 for pixels which are - * currently in cache and 0 for uncalculated pixels. + * Renders with a positive priority are assumed to be large, gh-priority, + * foreground images. Although there can be many of these, only one is ever + * active, to avoid overcommitting threads. * - * Only a single sink is calculated at any one time, though many may be - * alive. Use @priority to indicate which renders are more important: - * zero means normal - * priority, negative numbers are low priority, positive numbers high - * priority. + * Renders with a negative priority are assumed to be small, thumbnail images + * consisting of a single tile. Single tile images are effectively + * single-threaded, so all these renders are evaluated together. * - * Calls to vips_region_prepare() on @out return immediately and hold - * whatever is - * currently in cache for that #VipsRect (check @mask to see which parts of the - * #VipsRect are valid). Any pixels in the #VipsRect which are not in - * cache are added - * to a queue, and the @notify_fn callback will trigger when those pixels are - * ready. + * Calls to [method@Region.prepare] on @out return immediately and hold + * whatever is currently in cache for that [struct@Rect] (check @mask to see + * which parts of the [struct@Rect] are valid). Any pixels in the [struct@Rect] + * which are not in cache are added to a queue, and the @notify_fn + * callback will trigger when those pixels are ready. * * The @notify_fn callback is run from one of the background threads. In the - * callback - * you need to somehow send a message to the main thread that the pixels are - * ready. In a glib-based application, this is easily done with g_idle_add(). + * callback you need to somehow send a message to the main thread that the + * pixels are ready. In a glib-based application, this is easily done with + * [func@GLib.idle_add]. * - * If @notify_fn is %NULL then vips_sink_screen() runs synchronously. - * vips_region_prepare() on @out will always block until the pixels have been + * If @notify_fn is `NULL` then [method@Image.sink_screen] runs synchronously. + * [method@Region.prepare] on @out will always block until the pixels have been * calculated. * - * See also: vips_tilecache(), vips_region_prepare(), - * vips_sink_disc(), vips_sink(). + * ::: seealso + * [method@Image.tilecache], [method@Region.prepare], + * [method@Image.sink_disc], [method@Image.sink]. * * Returns: 0 on success, -1 on error. */ @@ -1131,13 +1193,11 @@ vips_sink_screen(VipsImage *in, VipsImage *out, VipsImage *mask, } if (vips_image_pio_input(in) || - vips_image_pipelinev(out, - VIPS_DEMAND_STYLE_SMALLTILE, in, NULL)) + vips_image_pipelinev(out, VIPS_DEMAND_STYLE_SMALLTILE, in, NULL)) return -1; if (mask) { - if (vips_image_pipelinev(mask, - VIPS_DEMAND_STYLE_SMALLTILE, in, NULL)) + if (vips_image_pipelinev(mask, VIPS_DEMAND_STYLE_SMALLTILE, in, NULL)) return -1; mask->Bands = 1; @@ -1152,12 +1212,16 @@ vips_sink_screen(VipsImage *in, VipsImage *out, VipsImage *mask, VIPS_DEBUG_MSG("vips_sink_screen: max = %d, %p\n", max_tiles, render); + if (render->private_threadpool) { + render_ref(render); + vips_thread_execute("private threadpool", render_work_private, render); + } + if (vips_image_generate(out, vips_start_one, image_fill, vips_stop_one, in, render)) return -1; if (mask && - vips_image_generate(mask, - NULL, mask_fill, NULL, render, NULL)) + vips_image_generate(mask, NULL, mask_fill, NULL, render, NULL)) return -1; return 0; @@ -1177,15 +1241,13 @@ vips__print_renders(void) } #endif /*VIPS_DEBUG_AMBER*/ - if (render_dirty_lock) { - g_mutex_lock(render_dirty_lock); + g_mutex_lock(&render_dirty_lock); - n_leaks += g_slist_length(render_dirty_all); - if (render_dirty_all) - printf("dirty renders\n"); + n_leaks += g_slist_length(render_dirty_all); + if (render_dirty_all) + printf("dirty renders\n"); - g_mutex_unlock(render_dirty_lock); - } + g_mutex_unlock(&render_dirty_lock); return n_leaks; } diff --git a/libvips/iofuncs/source.c b/libvips/iofuncs/source.c index d68fd225f7..eba0e4b59c 100644 --- a/libvips/iofuncs/source.c +++ b/libvips/iofuncs/source.c @@ -74,6 +74,46 @@ #include #include +/** + * VipsSource: + * + * A [class@Source] provides a unified interface for reading, seeking, and + * mapping data, regardless of the underlying source type. + * + * This source can originate from something like a socket, file or memory + * area. + * + * During the header phase, we save data from unseekable sources in a buffer + * so readers can rewind and read again. We don't buffer data during the + * decode stage. + */ + +/** + * VipsSourceCustom: + * + * Subclass of [class@Source] with action signals for handlers. + * + * This is supposed to be useful for language bindings. + */ + +/** + * VipsTarget: + * + * A [class@Target] provides a unified interface for writing data to various + * output destinations. + * + * This target could be a socket, file, memory area, or any other destination + * that accepts byte data. + */ + +/** + * VipsTargetCustom: + * + * Subclass of [class@Target] with action signals for handlers. + * + * This is supposed to be useful for language bindings. + */ + #define MODE_READ CLOEXEC(BINARYIZE(O_RDONLY)) /* -1 on a pipe isn't actually unbounded. Have a limit to prevent @@ -92,13 +132,14 @@ static gint64 vips__pipe_read_limit = 1024 * 1024 * 1024; * automatically read into memory to EOF before the loader starts. This can * produce high memory use if the descriptor represents a large object. * - * Use vips_pipe_read_limit_set() to limit the size of object that + * Use [func@pipe_read_limit_set] to limit the size of object that * will be read in this way. The default is 1GB. * * Set a value of -1 to mean no limit. * - * See also: `--vips-pipe-read-limit` and the environment variable - * `VIPS_PIPE_READ_LIMIT`. + * ::: seealso + * `--vips-pipe-read-limit` and the environment variable + * `VIPS_PIPE_READ_LIMIT`. */ void vips_pipe_read_limit_set(gint64 limit) @@ -336,7 +377,7 @@ vips_source_seek_real(VipsSource *source, gint64 offset, int whence) VIPS_DEBUG_MSG("vips_source_seek_real:\n"); /* Like _read_real(), we must not set a vips_error. We need to use the - * vips__seek() wrapper so we can seek long files on Windows. + * vips__seek wrapper so we can seek long files on Windows. */ if (connection->descriptor != -1) return vips__seek_no_error(connection->descriptor, offset, whence); @@ -383,7 +424,7 @@ vips_source_init(VipsSource *source) * @descriptor: read from this file descriptor * * Create an source attached to a file descriptor. @descriptor is - * closed with close() when source is finalized. + * closed with [`close()`](man:close(2)) when source is finalized. * * Returns: a new source. */ @@ -411,16 +452,16 @@ vips_source_new_from_descriptor(int descriptor) /** * vips_source_new_from_file: - * @descriptor: read from this filename + * @filename: read from this filename * - * Create an source attached to a file. + * Create a source attached to a file. * * If this descriptor does not support mmap and the source is * used with a loader that can only work from memory, then the data will be * automatically read into memory to EOF before the loader starts. This can * produce high memory use if the descriptor represents a large object. * - * Use vips_pipe_read_limit_set() to limit the size of object that + * Use [func@pipe_read_limit_set] to limit the size of object that * will be read in this way. The default is 1GB. * * Returns: a new source. @@ -582,7 +623,7 @@ vips_source_new_from_options(const char *options) * @source: source to operate on * * Minimise the source. As many resources as can be safely removed are - * removed. Use vips_source_unminimise() to restore the source if you wish to + * removed. Use [method@Source.unminimise] to restore the source if you wish to * use it again. * * Loaders should call this in response to the minimise signal on their output @@ -622,7 +663,8 @@ vips_source_minimise(VipsSource *source) * Restore the source after minimisation. This is called at the start * of every source method, so loaders should not usually need this. * - * See also: vips_source_minimise(). + * ::: seealso + * [method@Source.minimise]. * * Returns: 0 on success, or -1 on error. */ @@ -680,7 +722,8 @@ vips_source_unminimise(VipsSource *source) * * Loaders should call this at the end of header read. * - * See also: vips_source_unminimise(). + * ::: seealso + * [method@Source.unminimise]. * * Returns: 0 on success, -1 on error. */ @@ -737,7 +780,7 @@ vips_source_print(VipsSource *source) * Return the number of bytes actually read. If all bytes have been read from * the file, return 0. * - * Arguments exactly as read(2). + * Arguments exactly as [`read()`](man:read(2)). * * Returns: the number of bytes read, 0 on end of file, -1 on error. */ @@ -980,10 +1023,10 @@ vips_source_descriptor_to_memory(VipsSource *source) * @source: source to operate on * * Some sources can be efficiently mapped into memory. - * You can still use vips_source_map() if this function returns %FALSE, + * You can still use [method@Source.map] if this function returns `FALSE`, * but it will be slow. * - * Returns: %TRUE if the source can be efficiently mapped into memory. + * Returns: `TRUE` if the source can be efficiently mapped into memory. */ gboolean vips_source_is_mappable(VipsSource *source) @@ -1007,12 +1050,12 @@ vips_source_is_mappable(VipsSource *source) * * Test if this source is a simple file with support for seek. Named pipes, * for example, will fail this test. If TRUE, you can use - * vips_connection_filename() to find the filename. + * [method@Connection.filename] to find the filename. * * Use this to add basic source support for older loaders which can only work * on files. * - * Returns: %TRUE if the source is a simple file. + * Returns: `TRUE` if the source is a simple file. */ gboolean vips_source_is_file(VipsSource *source) @@ -1030,12 +1073,12 @@ vips_source_is_file(VipsSource *source) /** * vips_source_map: * @source: source to operate on - * @length_out: return the file length here, or NULL + * @length: return the file length here, or NULL * * Map the source entirely into memory and return a pointer to the - * start. If @length_out is non-NULL, the source size is written to it. + * start. If @length is non-NULL, the source size is written to it. * - * This operation can take a long time. Use vips_source_is_mappable() to + * This operation can take a long time. Use [method@Source.is_mappable] to * check if a source can be mapped efficiently. * * The pointer is valid for as long as @source is alive. @@ -1043,7 +1086,7 @@ vips_source_is_file(VipsSource *source) * Returns: a pointer to the start of the file contents, or NULL on error. */ const void * -vips_source_map(VipsSource *source, size_t *length_out) +vips_source_map(VipsSource *source, size_t *length) { VIPS_DEBUG_MSG("vips_source_map:\n"); @@ -1074,8 +1117,8 @@ vips_source_map(VipsSource *source, size_t *length_out) vips_source_pipe_read_to_position(source, -1)) return NULL; - if (length_out) - *length_out = source->length; + if (length) + *length = source->length; SANITY(source); @@ -1096,10 +1139,10 @@ vips_source_map_cb(void *a, VipsArea *area) * vips_source_map_blob: * @source: source to operate on * - * Just like vips_source_map(), but return a #VipsBlob containing the + * Just like [method@Source.map], but return a [struct@Blob] containing the * pointer. @source will stay alive as long as the result is alive. * - * Returns: a new #VipsBlob containing the data, or NULL on error. + * Returns: a new [struct@Blob] containing the data, or NULL on error. */ VipsBlob * vips_source_map_blob(VipsSource *source) @@ -1127,7 +1170,7 @@ vips_source_map_blob(VipsSource *source) * @whence: seek relative to this point * * Move the file read position. You can't call this after pixel decode starts. - * The arguments are exactly as lseek(2). + * The arguments are exactly as [`lseek()`](man:lseek(2)). * * Returns: the new file position, or -1 on error. */ diff --git a/libvips/iofuncs/sourcecustom.c b/libvips/iofuncs/sourcecustom.c index c90028f27e..9fe9c32e19 100644 --- a/libvips/iofuncs/sourcecustom.c +++ b/libvips/iofuncs/sourcecustom.c @@ -181,8 +181,8 @@ vips_source_custom_class_init(VipsSourceCustomClass *class) /** * VipsSourceCustom::read: * @source_custom: the source being operated on - * @buffer: %gpointer, buffer to fill - * @size: %gint64, size of buffer + * @buffer: `gpointer`, buffer to fill + * @size: `gint64`, size of buffer * * This signal is emitted to read bytes from the source into @buffer. * @@ -200,8 +200,8 @@ vips_source_custom_class_init(VipsSourceCustomClass *class) /** * VipsSourceCustom::seek: * @source_custom: the source being operated on - * @offset: %gint64, seek offset - * @whence: %gint, seek origin + * @offset: `gint64`, seek offset + * @whence: `gint`, seek origin * * This signal is emitted to seek the source. The handler should * change the source position appropriately. @@ -229,9 +229,9 @@ vips_source_custom_init(VipsSourceCustom *source_custom) /** * vips_source_custom_new: * - * Create a #VipsSourceCustom. Attach signals to implement read and seek. + * Create a [class@SourceCustom]. Attach signals to implement read and seek. * - * Returns: a new #VipsSourceCustom + * Returns: a new [class@SourceCustom] */ VipsSourceCustom * vips_source_custom_new(void) diff --git a/libvips/iofuncs/sourceginput.c b/libvips/iofuncs/sourceginput.c index 12cbe5beb8..ea5d55b7ef 100644 --- a/libvips/iofuncs/sourceginput.c +++ b/libvips/iofuncs/sourceginput.c @@ -240,9 +240,12 @@ vips_source_g_input_stream_init(VipsSourceGInputStream *source) * vips_source_g_input_stream_new: * @stream: read from this stream * - * Create a #VipsSourceGInputStream which wraps @stream. + * Create a [struct@SourceGInputStream] which wraps @stream. * - * Returns: the new source. + * ::: seealso + * [func@g_input_stream_new_from_source] + * + * Returns: (transfer full): the new source. */ VipsSourceGInputStream * vips_source_g_input_stream_new(GInputStream *stream) diff --git a/libvips/iofuncs/system.c b/libvips/iofuncs/system.c index 51dbc37737..8419ecd8ab 100644 --- a/libvips/iofuncs/system.c +++ b/libvips/iofuncs/system.c @@ -323,39 +323,38 @@ vips_system_init(VipsSystem *system) /** * vips_system: * @cmd_format: command to run - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * ::: tip "Optional arguments" + * * @in: array of input images + * * @out: output image + * * @in_format: write input files like this + * * @out_format: write output filename like this + * * @log: stdout of command is returned here * - * * @in: array of input images - * * @out: output image - * * @in_format: write input files like this - * * @out_format: write output filename like this - * * @log: stdout of command is returned here - * - * vips_system() runs a command, optionally passing a set of images in and + * [ctor@Image.system] runs a command, optionally passing a set of images in and * optionally getting an image back. The command's stdout is returned in @log. * * First, if @in is set, the array of images are written to files. See - * vips_image_new_temp_file() to see how temporary files are created. - * If @in_format is - * something like %s.png, the file will be written in PNG format. By - * default, @in_format is %s.tif. + * [ctor@Image.new_temp_file] to see how temporary files are created. + * If @in_format is something like `%s.png`, the file will be written in PNG + * format. By default, @in_format is `%s.tif`. * * If @out_format is set, an output filename is formed in the same way. Any - * trailing [options] are stripped from @out_format. + * trailing `[options]` are stripped from @out_format. * - * The command string to run is made by substituting the first set of %s + * The command string to run is made by substituting the first set of `%s` * in @cmd_format for the names of the input files, if @in is set, and then - * the next %s for the output filename, if @out_format is set. - * You can put a number between the % and the s to change the order + * the next `%s` for the output filename, if @out_format is set. + * You can put a number between the `%` and the `s` to change the order * in which the substitution occurs. * - * The command is executed with popen() and the output captured in @log. + * The command is executed with [`popen()`](man:popen(3)) and the output captured in @log. * * After the command finishes, if @out_format is set, the output image is - * opened and returned in @out. You can append [options] to @out_format to + * opened and returned in @out. You can append `[options]` to @out_format to * control how this open happens. + * * Closing @out image will automatically delete the output file. * * Finally the input images are deleted. @@ -363,7 +362,7 @@ vips_system_init(VipsSystem *system) * For example, this call will run the ImageMagick convert program on an * image, using JPEG files to pass images into and out of the convert command. * - * |[ + * ```c * VipsArrayImage *in; * VipsImage *out; * char *log; @@ -376,7 +375,7 @@ vips_system_init(VipsSystem *system) * "log", &log, * NULL)) * error ... - * ]| + * ``` * * Returns: 0 on success, -1 on failure. */ diff --git a/libvips/iofuncs/target.c b/libvips/iofuncs/target.c index df5a409512..dedebdac54 100644 --- a/libvips/iofuncs/target.c +++ b/libvips/iofuncs/target.c @@ -115,25 +115,10 @@ vips_target_build(VipsObject *object) return -1; } - if (connection->filename) { - const char *filename = connection->filename; + // for filename targets, don't create the file we write on _build() -- + // do it lazily on the first write - int fd; - - /* 0644 is rw user, r group and other. - */ - if ((fd = vips_tracked_open(filename, - MODE_READWRITE, 0644)) == -1) { - vips_error_system(errno, - vips_connection_nick(connection), - "%s", _("unable to open for write")); - return -1; - } - - connection->tracked_descriptor = fd; - connection->descriptor = fd; - } - else if (vips_object_argument_isset(object, "descriptor")) { + if (vips_object_argument_isset(object, "descriptor")) { connection->descriptor = dup(connection->descriptor); connection->close_descriptor = connection->descriptor; @@ -151,6 +136,36 @@ vips_target_build(VipsObject *object) return 0; } +/* If necessary, create the file we write to from the filename. We do this + * lazily on first write, since eg. dzsave might not actually write to this + * filename in some cases. + */ +static int +vips_target_create_file(VipsTarget *target) +{ + VipsConnection *connection = VIPS_CONNECTION(target); + + if (connection->filename && + connection->tracked_descriptor == -1) { + const char *filename = connection->filename; + + int fd; + + /* 0644 is rw user, r group and other. + */ + if ((fd = vips_tracked_open(filename, MODE_READWRITE, 0644)) == -1) { + vips_error_system(errno, vips_connection_nick(connection), + "%s", _("unable to open for write")); + return -1; + } + + connection->tracked_descriptor = fd; + connection->descriptor = fd; + } + + return 0; +} + static gint64 vips_target_write_real(VipsTarget *target, const void *data, size_t length) { @@ -169,8 +184,12 @@ vips_target_write_real(VipsTarget *target, const void *data, size_t length) target->position += length; result = length; } - else - result = write(connection->descriptor, data, length); + else { + if (vips_target_create_file(target)) + result = -1; + else + result = write(connection->descriptor, data, length); + } return result; } @@ -316,13 +335,14 @@ vips_target_init(VipsTarget *target) } /** - * vips_target_new_to_descriptor: + * vips_target_new_to_descriptor: (constructor) * @descriptor: write to this file descriptor * * Create a target attached to a file descriptor. * @descriptor is kept open until the target is finalized. * - * See also: vips_target_new_to_file(). + * ::: seealso + * [ctor@Target.new_to_file]. * * Returns: a new target. */ @@ -347,7 +367,7 @@ vips_target_new_to_descriptor(int descriptor) } /** - * vips_target_new_to_file: + * vips_target_new_to_file: (constructor) * @filename: write to this file * * Create a target attached to a file. @@ -375,14 +395,15 @@ vips_target_new_to_file(const char *filename) } /** - * vips_target_new_to_memory: + * vips_target_new_to_memory: (constructor) * * Create a target which will write to a memory area. Read from @blob to get * memory. * - * See also: vips_target_new_to_file(). + * ::: seealso + * [ctor@Target.new_to_file]. * - * Returns: a new #VipsConnection + * Returns: a new target. */ VipsTarget * vips_target_new_to_memory(void) @@ -404,13 +425,14 @@ vips_target_new_to_memory(void) } /** - * vips_target_new_temp: + * vips_target_new_temp: (constructor) * @based_on: base the temporary target on this target * * Create a temporary target -- either a temporary file on disc, or an area in * memory, depending on what sort of target @based_on is. * - * See also: vips_target_new_to_file(). + * ::: seealso + * [ctor@Target.new_to_file]. * * Returns: a new target. */ @@ -503,15 +525,15 @@ vips_target_flush(VipsTarget *target) /** * vips_target_write: * @target: target to operate on - * @buffer: bytes to write - * @length: length of @buffer in bytes + * @data: data to write + * @length: length of @data in bytes * - * Write @length bytes from @buffer to the output. + * Write @length bytes from @data to the output. * * Returns: 0 on success, -1 on error. */ int -vips_target_write(VipsTarget *target, const void *buffer, size_t length) +vips_target_write(VipsTarget *target, const void *data, size_t length) { VIPS_DEBUG_MSG("vips_target_write: %zd bytes\n", length); @@ -522,12 +544,12 @@ vips_target_write(VipsTarget *target, const void *buffer, size_t length) if (length > VIPS_TARGET_BUFFER_SIZE - target->write_point) { /* Still too large? Do an unbuffered write. */ - if (vips_target_write_unbuffered(target, buffer, length)) + if (vips_target_write_unbuffered(target, data, length)) return -1; } else { memcpy(target->output_buffer + target->write_point, - buffer, length); + data, length); target->write_point += length; } @@ -544,7 +566,7 @@ vips_target_write(VipsTarget *target, const void *buffer, size_t length) * Return the number of bytes actually read. If all bytes have been read from * the file, return 0. * - * Arguments exactly as read(2). + * Arguments exactly as [`read()`](man:read(2)). * * Reading from a target sounds weird, but libtiff needs this for * multi-page writes. This method will fail for targets like pipes. @@ -567,43 +589,41 @@ vips_target_read(VipsTarget *target, void *buffer, size_t length) /** * vips_target_seek: * @target: target to operate on - * @position: position to seek to + * @offset: offset to seek to * @whence: seek relative to beginning, offset, or end * - * Seek the target. This behaves exactly as lseek(2). + * Seek the target. This behaves exactly as [`lseek()`](man:lseek(2)). * * Seeking a target sounds weird, but libtiff needs this. This method will * fail for targets like pipes. * - * Returns: the new seek position, -1 on error. + * Returns: the new offset, -1 on error. */ gint64 -vips_target_seek(VipsTarget *target, gint64 position, int whence) +vips_target_seek(VipsTarget *target, gint64 offset, int whence) { VipsTargetClass *class = VIPS_TARGET_GET_CLASS(target); - gint64 new_position; + gint64 new_offset; - VIPS_DEBUG_MSG("vips_target_seek: pos = %" G_GINT64_FORMAT - ", whence = %d\n", - position, whence); + VIPS_DEBUG_MSG( + "vips_target_seek: offset = %" G_GINT64_FORMAT ", whence = %d\n", + offset, whence); if (vips_target_flush(target)) return -1; - new_position = class->seek(target, position, whence); + new_offset = class->seek(target, offset, whence); - VIPS_DEBUG_MSG("vips_target_seek: new_position = %" G_GINT64_FORMAT "\n", - new_position); + VIPS_DEBUG_MSG("vips_target_seek: new_offset = %" G_GINT64_FORMAT "\n", + new_offset); - return new_position; + return new_offset; } /** * vips_target_end: * @target: target to operate on - * @buffer: bytes to write - * @length: length of @buffer in bytes * * Call this at the end of write to make the target do any cleaning up. You * can call it many times. @@ -652,16 +672,16 @@ vips_target_end(VipsTarget *target) * @target: target to operate on * @length: return number of bytes of data * - * Memory targets only (see vips_target_new_to_memory()). Steal all data - * written to the target so far, and call vips_target_end(). + * Memory targets only (see [ctor@Target.new_to_memory]). Steal all data + * written to the target so far, and call [method@Target.end]. * - * You must free the returned pointer with g_free(). + * You must free the returned pointer with [func@GLib.free]. * - * The data is NOT automatically null-terminated. vips_target_putc() a '\0' - * before calling this to get a null-terminated string. + * The data is NOT automatically null-terminated. Use [method@Target.putc] with + * a '\0' before calling this to get a null-terminated string. * - * You can't call this after vips_target_end(), since that moves the data to a - * blob, and we can't steal from that in case the pointer has been be shared. + * You can't call this after [method@Target.end], since that moves the data to a + * blob, and we can't steal from that in case the pointer has been shared. * * You can't call this function more than once. * @@ -698,7 +718,7 @@ vips_target_steal(VipsTarget *target, size_t *length) * vips_target_steal_text: * @target: target to operate on * - * As vips_target_steal_text(), but return a null-terminated string. + * As [method@Target.steal], but return a null-terminated string. * * Returns: (transfer full): target contents as a null-terminated string. */ @@ -715,7 +735,7 @@ vips_target_steal_text(VipsTarget *target) * @target: target to operate on * @ch: character to write * - * Write a single character @ch to @target. See the macro VIPS_TARGET_PUTC() + * Write a single character @ch to @target. See the macro [func@TARGET_PUTC] * for a faster way to do this. * * Returns: 0 on success, -1 on error. @@ -753,7 +773,7 @@ vips_target_writes(VipsTarget *target, const char *str) /** * vips_target_writef: * @target: target to operate on - * @fmt: printf()-style format string + * @fmt: `printf()`-style format string * @...: arguments to format string * * Format the string and write to @target. diff --git a/libvips/iofuncs/targetcustom.c b/libvips/iofuncs/targetcustom.c index 84aaca2d94..832226d5a3 100644 --- a/libvips/iofuncs/targetcustom.c +++ b/libvips/iofuncs/targetcustom.c @@ -249,8 +249,8 @@ vips_target_custom_class_init(VipsTargetCustomClass *class) /** * VipsTargetCustom::write: * @target_custom: the target being operated on - * @data: %pointer, bytes to write - * @length: %gint64, number of bytes + * @data: `gpointer`, bytes to write + * @length: `gint64`, number of bytes * * This signal is emitted to write bytes to the target. * @@ -268,8 +268,8 @@ vips_target_custom_class_init(VipsTargetCustomClass *class) /** * VipsTargetCustom::read: * @target_custom: the target being operated on - * @buffer: %gpointer, buffer to fill - * @size: %gint64, size of buffer + * @buffer: `gpointer`, buffer to fill + * @size: `gint64`, size of buffer * * This signal is emitted to read bytes from the target into @buffer. * @@ -289,8 +289,8 @@ vips_target_custom_class_init(VipsTargetCustomClass *class) /** * VipsTargetCustom::seek: * @target_custom: the target being operated on - * @offset: %gint64, seek offset - * @whence: %gint, seek origin + * @offset: `gint64`, seek offset + * @whence: `gint`, seek origin * * This signal is emitted to seek the target. The handler should * change the target position appropriately. @@ -348,9 +348,9 @@ vips_target_custom_init(VipsTargetCustom *target_custom) /** * vips_target_custom_new: * - * Create a #VipsTargetCustom. Attach signals to implement write and finish. + * Create a [class@TargetCustom]. Attach signals to implement write and finish. * - * Returns: a new #VipsTargetCustom + * Returns: a new [class@TargetCustom] */ VipsTargetCustom * vips_target_custom_new(void) diff --git a/libvips/iofuncs/thread.c b/libvips/iofuncs/thread.c index 80a43f38de..06b55a97f4 100644 --- a/libvips/iofuncs/thread.c +++ b/libvips/iofuncs/thread.c @@ -50,7 +50,6 @@ #include #include -#include #include #ifdef G_OS_WIN32 @@ -87,45 +86,6 @@ vips_thread_isvips(void) return g_private_get(&is_vips_thread_key) != NULL; } -/* Glib 2.32 revised the thread API. We need some compat functions. - */ - -GMutex * -vips_g_mutex_new(void) -{ - GMutex *mutex; - - mutex = g_new(GMutex, 1); - g_mutex_init(mutex); - - return mutex; -} - -void -vips_g_mutex_free(GMutex *mutex) -{ - g_mutex_clear(mutex); - g_free(mutex); -} - -GCond * -vips_g_cond_new(void) -{ - GCond *cond; - - cond = g_new(GCond, 1); - g_cond_init(cond); - - return cond; -} - -void -vips_g_cond_free(GCond *cond) -{ - g_cond_clear(cond); - g_free(cond); -} - typedef struct { const char *domain; GThreadFunc func; @@ -154,6 +114,17 @@ vips_thread_run(gpointer data) return result; } +/** + * vips_g_thread_new: + * @domain: (nullable): an (optional) name for the new thread + * @func: (scope async) (closure data): a function to execute in the new thread + * @data: (nullable): an argument to supply to the new thread + * + * Wrapper for [ctor@GLib.Thread.try_new]. + * + * Returns: (transfer full): the new [struct@GLib.Thread], or `NULL` if an + * error occurred + */ GThread * vips_g_thread_new(const char *domain, GThreadFunc func, gpointer data) { @@ -198,7 +169,7 @@ vips__concurrency_get_default(void) nthr = vips__concurrency; else if ( ((str = g_getenv("VIPS_CONCURRENCY")) -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED || (str = g_getenv("IM_CONCURRENCY")) #endif ) && @@ -221,14 +192,15 @@ vips__concurrency_get_default(void) * vips_concurrency_set: * @concurrency: number of threads to run * - * Sets the number of worker threads that vips should use when running a - * #VipsThreadPool. + * Sets the number of worker threads that vips should use when running + * [func@threadpool_run]. * * The special value 0 means "default". In this case, the number of threads * is set by the environment variable VIPS_CONCURRENCY, or if that is not * set, the number of threads available on the host machine. * - * See also: vips_concurrency_get(). + * ::: seealso + * [func@concurrency_get]. */ void vips_concurrency_set(int concurrency) @@ -249,16 +221,16 @@ vips_concurrency_set(int concurrency) /** * vips_concurrency_get: * - * Returns the number of worker threads that vips should use when running a - * #VipsThreadPool. + * Returns the number of worker threads that vips should use when running + * [func@threadpool_run]. * * vips gets this values from these sources in turn: * - * If vips_concurrency_set() has been called, this value is used. The special + * If [func@concurrency_set] has been called, this value is used. The special * value 0 means "default". You can also use the command-line argument * "--vips-concurrency" to set this value. * - * If vips_concurrency_set() has not been called and no command-line argument + * If [func@concurrency_set] has not been called and no command-line argument * was used, vips uses the value of the environment variable VIPS_CONCURRENCY, * * If VIPS_CONCURRENCY has not been set, vips finds the number of hardware @@ -266,7 +238,8 @@ vips_concurrency_set(int concurrency) * * The final value is clipped to the range 1 - 1024. * - * See also: vips_concurrency_get(). + * ::: seealso + * [func@concurrency_get]. * * Returns: number of worker threads to use. */ @@ -284,7 +257,7 @@ vips_concurrency_get(void) * @n_lines: (out): return buffer height in scanlines * * Pick a tile size and a buffer height for this image and the current - * value of vips_concurrency_get(). The buffer height + * value of [func@concurrency_get]. The buffer height * will always be a multiple of tile_height. * * The buffer height is the height of each buffer we fill in sink disc. Since diff --git a/libvips/iofuncs/threadpool.c b/libvips/iofuncs/threadpool.c index 4706545d92..57c4d01801 100644 --- a/libvips/iofuncs/threadpool.c +++ b/libvips/iofuncs/threadpool.c @@ -71,7 +71,6 @@ #include #include -#include #include #ifdef G_OS_WIN32 @@ -79,17 +78,15 @@ #endif /*G_OS_WIN32*/ /** - * SECTION: threadpool - * @short_description: pools of worker threads - * @stability: Stable - * @see_also: generate - * @include: vips/vips.h - * @title: VipsThreadpool + * VipsThreadState: * - * vips_threadpool_run() loops a set of threads over an image. Threads take it - * in turns to allocate units of work (a unit might be a tile in an image), - * then run in parallel to process those units. An optional progress function - * can be used to give feedback. + * A [class@VipsThreadState] represents a per-thread state. + * + * [callback@ThreadpoolAllocateFn] functions can use these members to + * communicate with [callback@ThreadpoolWorkFn] functions. + * + * ::: seealso + * [func@threadpool_run]. */ /* Set to stall threads for debugging. @@ -139,9 +136,9 @@ vips__threadpool_shutdown(void) /** * vips_thread_execute: - * @name: a name for the thread - * @func: a function to execute in the libvips threadset - * @data: an argument to supply to @func + * @domain: a name for the thread (useful for debugging) + * @func: (scope async) (closure data): a function to execute in the libvips threadset + * @data: (nullable): an argument to supply to @func * * A newly created or reused thread will execute @func with the * argument @data. @@ -229,7 +226,6 @@ vips_thread_state_new(VipsImage *im, void *a) /* What we track for each thread in the pool. */ typedef struct _VipsWorker { - /*< private >*/ struct _VipsThreadpool *pool; /* Pool we are part of */ VipsThreadState *state; @@ -241,7 +237,6 @@ typedef struct _VipsWorker { /* What we track for a group of threads working together. */ typedef struct _VipsThreadpool { - /*< private >*/ VipsImage *im; /* Image we are calculating */ /* Start a thread, do a unit of work (runs in parallel) and allocate @@ -251,7 +246,7 @@ typedef struct _VipsThreadpool { VipsThreadStartFn start; VipsThreadpoolAllocateFn allocate; VipsThreadpoolWorkFn work; - GMutex *allocate_lock; + GMutex allocate_lock; void *a; /* User argument to start / allocate / etc. */ int max_workers; /* Max number of workers in pool */ @@ -270,6 +265,11 @@ typedef struct _VipsThreadpool { */ int n_waiting; // (atomic) + /* Increment this and the next worker will decrement and exit if needed + * (used to downsize the threadpool). + */ + int exit; // (atomic) + /* Set this to abort evaluation early with an error. */ gboolean error; @@ -277,11 +277,6 @@ typedef struct _VipsThreadpool { /* Ask threads to exit, either set by allocate, or on free. */ gboolean stop; - - /* Set this and the next worker to see it will clear the flag and exit - * (used to downsize the threadpool). - */ - gboolean exit; // (atomic) } VipsThreadpool; static int @@ -311,7 +306,7 @@ vips_worker_work_unit(VipsWorker *worker) VIPS_GATE_START("vips_worker_work_unit: wait"); - vips__worker_lock(pool->allocate_lock); + vips__worker_lock(&pool->allocate_lock); VIPS_GATE_STOP("vips_worker_work_unit: wait"); @@ -319,25 +314,31 @@ vips_worker_work_unit(VipsWorker *worker) */ if (pool->stop) { worker->stop = TRUE; - g_mutex_unlock(pool->allocate_lock); + g_mutex_unlock(&pool->allocate_lock); return; } /* Has a thread been asked to exit? Volunteer if yes. */ - if (g_atomic_int_compare_and_exchange(&pool->exit, TRUE, FALSE)) { + if (g_atomic_int_add(&pool->exit, -1) > 0) { /* A thread had been asked to exit, and we've grabbed the * flag. */ worker->stop = TRUE; - g_mutex_unlock(pool->allocate_lock); + g_mutex_unlock(&pool->allocate_lock); return; } + else { + /* No one had been asked to exit and we've mistakenly taken + * the exit count below zero. Put it back up again. + */ + g_atomic_int_inc(&pool->exit); + } if (vips_worker_allocate(worker)) { pool->error = TRUE; worker->stop = TRUE; - g_mutex_unlock(pool->allocate_lock); + g_mutex_unlock(&pool->allocate_lock); return; } @@ -345,11 +346,11 @@ vips_worker_work_unit(VipsWorker *worker) */ if (pool->stop) { worker->stop = TRUE; - g_mutex_unlock(pool->allocate_lock); + g_mutex_unlock(&pool->allocate_lock); return; } - g_mutex_unlock(pool->allocate_lock); + g_mutex_unlock(&pool->allocate_lock); if (worker->state->stall && vips__stall) { @@ -401,11 +402,11 @@ vips_thread_main_loop(void *a, void *b) /* unreffing the worker state will trigger stop in the threadstate, so * we need to single-thread. */ - g_mutex_lock(pool->allocate_lock); + g_mutex_lock(&pool->allocate_lock); VIPS_FREEF(g_object_unref, worker->state); - g_mutex_unlock(pool->allocate_lock); + g_mutex_unlock(&pool->allocate_lock); VIPS_FREE(worker); g_private_set(&worker_key, NULL); @@ -485,7 +486,7 @@ vips_threadpool_free(VipsThreadpool *pool) vips_threadpool_wait(pool); - VIPS_FREEF(vips_g_mutex_free, pool->allocate_lock); + g_mutex_clear(&pool->allocate_lock); vips_semaphore_destroy(&pool->n_workers); vips_semaphore_destroy(&pool->tick); VIPS_FREE(pool); @@ -507,13 +508,13 @@ vips_threadpool_new(VipsImage *im) pool->im = im; pool->allocate = NULL; pool->work = NULL; - pool->allocate_lock = vips_g_mutex_new(); + g_mutex_init(&pool->allocate_lock); pool->max_workers = vips_concurrency_get(); vips_semaphore_init(&pool->n_workers, 0, "n_workers"); vips_semaphore_init(&pool->tick, 0, "tick"); pool->error = FALSE; pool->stop = FALSE; - pool->exit = FALSE; + pool->exit = 0; /* If this is a tiny image, we won't need all max_workers threads. * Guess how @@ -545,35 +546,33 @@ vips_threadpool_new(VipsImage *im) * * This function is called once by each worker just before the first time work * is allocated to it to build the per-thread state. Per-thread state is used - * by #VipsThreadpoolAllocate and #VipsThreadpoolWork to communicate. + * by [callback@ThreadpoolAllocateFn] and [callback@ThreadpoolWorkFn] to + * communicate. * - * #VipsThreadState is a subclass of #VipsObject. Start functions are called - * from allocate, that is, they are single-threaded. + * [class@ThreadState] is a subclass of [class@Object]. Start functions are + * called from allocate, that is, they are single-threaded. * - * See also: vips_threadpool_run(). + * ::: seealso + * [func@threadpool_run]. * - * Returns: a new #VipsThreadState object, or NULL on error + * Returns: a new [class@ThreadState] object, or NULL on error */ /** * VipsThreadpoolAllocateFn: * @state: per-thread state * @a: client data - * @b: client data - * @c: client data * @stop: set this to signal end of computation * * This function is called to allocate a new work unit for the thread. It is * always single-threaded, so it can modify per-pool state (such as a * counter). * - * @a, @b, @c are the values supplied to the call to - * vips_threadpool_run(). - * - * It should set @stop to %TRUE to indicate that no work could be allocated + * It should set @stop to `TRUE` to indicate that no work could be allocated * because the job is done. * - * See also: vips_threadpool_run(). + * ::: seealso + * [func@threadpool_run]. * * Returns: 0 on success, or -1 on error */ @@ -582,17 +581,13 @@ vips_threadpool_new(VipsImage *im) * VipsThreadpoolWorkFn: * @state: per-thread state * @a: client data - * @b: client data - * @c: client data * * This function is called to process a work unit. Many copies of this can run * at once, so it should not write to the per-pool state. It can write to * per-thread state. * - * @a, @b, @c are the values supplied to the call to - * vips_threadpool_run(). - * - * See also: vips_threadpool_run(). + * ::: seealso + * [func@threadpool_run]. * * Returns: 0 on success, or -1 on error */ @@ -600,13 +595,12 @@ vips_threadpool_new(VipsImage *im) /** * VipsThreadpoolProgressFn: * @a: client data - * @b: client data - * @c: client data * * This function is called by the main thread once for every work unit * processed. It can be used to give the user progress feedback. * - * See also: vips_threadpool_run(). + * ::: seealso + * [func@threadpool_run]. * * Returns: 0 on success, or -1 on error */ @@ -614,10 +608,10 @@ vips_threadpool_new(VipsImage *im) /** * vips_threadpool_run: * @im: image to loop over - * @start: allocate per-thread state - * @allocate: allocate a work unit - * @work: process a work unit - * @progress: give progress feedback about a work unit, or %NULL + * @start: (scope async): allocate per-thread state + * @allocate: (scope async): allocate a work unit + * @work: (scope async): process a work unit + * @progress: (scope async): give progress feedback about a work unit, or `NULL` * @a: client data * * This function runs a set of threads over an image. Each thread first calls @@ -625,17 +619,18 @@ vips_threadpool_new(VipsImage *im) * @allocate to set up a new work unit (perhaps the next tile in an image, for * example), then @work to process that work unit. After each unit is * processed, @progress is called, so that the operation can give - * progress feedback. @progress may be %NULL. + * progress feedback. @progress may be `NULL`. * * The object returned by @start must be an instance of a subclass of - * #VipsThreadState. Use this to communicate between @allocate and @work. + * [class@ThreadState]. Use this to communicate between @allocate and @work. * * @allocate and @start are always single-threaded (so they can write to the * per-pool state), whereas @work can be executed concurrently. @progress is * always called by - * the main thread (ie. the thread which called vips_threadpool_run()). + * the main thread (ie. the thread which called [func@threadpool_run]). * - * See also: vips_concurrency_set(). + * ::: seealso + * [func@concurrency_set]. * * Returns: 0 on success, or -1 on error. */ @@ -696,7 +691,7 @@ vips_threadpool_run(VipsImage *im, if (n_waiting > 3 && n_working > 1) { VIPS_DEBUG_MSG("shrinking thread pool\n"); - g_atomic_int_set(&pool->exit, TRUE); + g_atomic_int_inc(&pool->exit); n_working -= 1; } else if (n_waiting < 2 && diff --git a/libvips/iofuncs/threadset.c b/libvips/iofuncs/threadset.c index 10b48a332b..40b9409a23 100644 --- a/libvips/iofuncs/threadset.c +++ b/libvips/iofuncs/threadset.c @@ -49,7 +49,6 @@ #include #include -#include #include typedef struct _VipsThreadExec { @@ -75,6 +74,10 @@ struct _VipsThreadset { */ VipsSemaphore idle; + /* The number of threads that haven't reached their entry point. + */ + int queue_guard; + /* The current number of (idle-)threads, the highwater mark, * and the max we allow before blocking thread creation. */ @@ -138,6 +141,8 @@ vips_threadset_work(void *pointer) g_async_queue_lock(set->queue); + set->queue_guard--; + for (;;) { /* Pop a task from the queue. If the number of threads is limited, * this will block until a task becomes available. Otherwise, it @@ -239,6 +244,7 @@ vips_threadset_add_thread(VipsThreadset *set) g_thread_unref(thread); set->n_threads++; + set->queue_guard++; set->n_threads_highwater = VIPS_MAX(set->n_threads_highwater, set->n_threads); } @@ -247,16 +253,16 @@ vips_threadset_add_thread(VipsThreadset *set) } /** - * vips_threadset_new: + * vips_threadset_new: (free-func vips_threadset_free) (skip) * @max_threads: maximum number of system threads * * Create a new threadset. * * If @max_threads is 0, new threads will be created when necessary by - * vips_threadset_run(), with no limit on the number of threads. + * [func@threadset_run], with no limit on the number of threads. * * If @max_threads is > 0, then that many threads will be created by - * vips_threadset_new() during startup and vips_threadset_run() will + * [ctor@Threadset.new] during startup and [func@threadset_run] will * not spawn any additional threads. * * Returns: the new threadset. @@ -286,14 +292,15 @@ vips_threadset_new(int max_threads) * vips_threadset_run: * @set: the threadset to run the task in * @domain: the name of the task (useful for debugging) - * @func: the task to execute - * @data: the task's data + * @func: (scope async) (closure data): the task to execute + * @data: (nullable): the task's data * * Execute a task in a thread. If there are no idle threads and the maximum * thread limit specified by @max_threads has not been reached, a new thread * will be spawned. * - * See also: vips_threadset_new(). + * ::: seealso + * [ctor@Threadset.new]. * * Returns: 0 on success, or -1 on error. */ @@ -305,9 +312,11 @@ vips_threadset_run(VipsThreadset *set, g_async_queue_lock(set->queue); - /* Create a new thread if there are no waiting threads in the queue. + /* Create or reuse an idle thread if there are at least as many tasks + * in the queue as waiting threads. The guard comparison prevents + * oversubscription by threads that haven't started yet. */ - if (g_async_queue_length_unlocked(set->queue) >= 0) + if (g_async_queue_length_unlocked(set->queue) >= set->queue_guard) if (!vips_threadset_add_thread(set)) { g_async_queue_unlock(set->queue); diff --git a/libvips/iofuncs/type.c b/libvips/iofuncs/type.c index d6797ae661..1fcb6971eb 100644 --- a/libvips/iofuncs/type.c +++ b/libvips/iofuncs/type.c @@ -57,25 +57,6 @@ #include #include -/** - * SECTION: basic - * @short_description: a few typedefs used everywhere - * @stability: Stable - * @include: vips/vips.h - * - * A few simple typedefs used by VIPS. - */ - -/** - * SECTION: type - * @short_description: basic types - * @stability: Stable - * @see_also: header - * @include: vips/vips.h - * - * A selection of %GType definitions used by VIPS. - */ - /* A very simple boxed type for testing. Just an int. * * You can manipulate this thing from Python (for example) with: @@ -93,7 +74,7 @@ * vips_thing_new: * @i: * - * Returns: (transfer full): a new #VipsThing. + * Returns: (transfer full): a new [struct@Thing]. */ VipsThing * vips_thing_new(int i) @@ -137,7 +118,7 @@ static GSList *vips_area_all = NULL; VipsArea * vips_area_copy(VipsArea *area) { - g_mutex_lock(area->lock); + g_mutex_lock(&area->lock); g_assert(area->count > 0); @@ -147,7 +128,7 @@ vips_area_copy(VipsArea *area) printf("vips_area_copy: %p count = %d\n", area, area->count); #endif /*DEBUG*/ - g_mutex_unlock(area->lock); + g_mutex_unlock(&area->lock); return area; } @@ -175,7 +156,7 @@ vips_area_free(VipsArea *area) void vips_area_unref(VipsArea *area) { - g_mutex_lock(area->lock); + g_mutex_lock(&area->lock); g_assert(area->count > 0); @@ -186,35 +167,35 @@ vips_area_unref(VipsArea *area) #endif /*DEBUG*/ if (vips__leak) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); g_assert(g_slist_find(vips_area_all, area)); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } if (area->count == 0) { vips_area_free(area); - g_mutex_unlock(area->lock); - - VIPS_FREEF(vips_g_mutex_free, area->lock); + g_mutex_unlock(&area->lock); - g_free(area); + g_mutex_clear(&area->lock); if (vips__leak) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips_area_all = g_slist_remove(vips_area_all, area); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } + g_free(area); + #ifdef DEBUG - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); printf("vips_area_unref: free .. total = %d\n", g_slist_length(vips_area_all)); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); #endif /*DEBUG*/ } else - g_mutex_unlock(area->lock); + g_mutex_unlock(&area->lock); } /* autoptr needs typed versions of functions for free. @@ -237,17 +218,19 @@ VipsArrayImage_unref(VipsArrayImage *array) * @data: (transfer full): data will be freed with this function * * A VipsArea wraps a chunk of memory. It adds reference counting and a free - * function. It also keeps a count and a %GType, so the area can be an array. + * function. It also keeps a count and a [alias@GObject.Type], so the area can + * be an array. * * This type is used for things like passing an array of double or an array of - * #VipsObject pointers to operations, and for reference-counted immutable + * [class@Object] pointers to operations, and for reference-counted immutable * strings. * - * Initial count == 1, so _unref() after attaching somewhere. + * Initial count == 1, so [method@Area.unref] after attaching somewhere. * - * See also: vips_area_unref(). + * ::: seealso + * [method@Area.unref]. * - * Returns: (transfer full): the new #VipsArea. + * Returns: (transfer full): the new [struct@Area]. */ VipsArea * vips_area_new(VipsCallbackFn free_fn, void *data) @@ -256,7 +239,7 @@ vips_area_new(VipsCallbackFn free_fn, void *data) area = g_new(VipsArea, 1); area->count = 1; - area->lock = vips_g_mutex_new(); + g_mutex_init(&area->lock); area->length = 0; area->data = data; area->free_fn = free_fn; @@ -264,17 +247,17 @@ vips_area_new(VipsCallbackFn free_fn, void *data) area->sizeof_type = 0; if (vips__leak) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); vips_area_all = g_slist_prepend(vips_area_all, area); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } #ifdef DEBUG - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); printf("vips_area_new: %p count = %d (%d in total)\n", area, area->count, g_slist_length(vips_area_all)); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); #endif /*DEBUG*/ return area; @@ -307,16 +290,17 @@ vips__type_leak(void) /** * vips_area_new_array: - * @type: %GType of elements to store - * @sizeof_type: sizeof() an element in the array + * @type: [alias@GObject.Type] of elements to store + * @sizeof_type: `sizeof()` an element in the array * @n: number of elements in the array * - * An area which holds an array of elements of some %GType. To set values for - * the elements, get the pointer and write. + * An area which holds an array of elements of some [alias@GObject.Type]. + * To set values for the elements, get the pointer and write. * - * See also: vips_area_unref(). + * ::: seealso + * [method@Area.unref]. * - * Returns: (transfer full): the new #VipsArea. + * Returns: (transfer full): the new [struct@Area]. */ VipsArea * vips_area_new_array(GType type, size_t sizeof_type, int n) @@ -352,15 +336,16 @@ vips_area_free_array_object(GObject **array, VipsArea *area) * vips_area_new_array_object: (constructor) * @n: number of elements in the array * - * An area which holds an array of %GObject s. See vips_area_new_array(). When - * the area is freed, each %GObject will be unreffed. + * An area which holds an array of [class@GObject.Object] s. See [ctor@Area.new_array]. When + * the area is freed, each [class@GObject.Object] will be unreffed. * * Add an extra NULL element at the end, handy for eg. - * vips_image_pipeline_array() etc. + * [func@Image.pipeline_array] etc. * - * See also: vips_area_unref(). + * ::: seealso + * [method@Area.unref]. * - * Returns: (transfer full): the new #VipsArea. + * Returns: (transfer full): the new [struct@Area]. */ VipsArea * vips_area_new_array_object(int n) @@ -381,15 +366,15 @@ vips_area_new_array_object(int n) /** * vips_area_get_data: - * @area: #VipsArea to fetch from + * @area: [struct@Area] to fetch from * @length: (out) (optional): optionally return length in bytes here * @n: (out) (optional): optionally return number of elements here * @type: (out) (optional): optionally return element type here - * @sizeof_type: (out) (optional): optionally return sizeof() element type here + * @sizeof_type: (out) (optional): optionally return `sizeof()` element type here * * Return the data pointer plus optionally the length in bytes of an area, - * the number of elements, the %GType of each element and the sizeof() each - * element. + * the number of elements, the [alias@GObject.Type] of each element and the + * `sizeof()` each element. * * Returns: (transfer none): The pointer held by @area. */ @@ -568,9 +553,11 @@ transform_save_string_ref_string(const GValue *src_value, GValue *dest_value) * * Strings must be valid utf-8; use blob for binary data. * - * See also: vips_area_unref(). + * ::: seealso + * [method@Area.unref]. * - * Returns: (transfer full) (nullable): the new #VipsRefString, or NULL on error. + * Returns: (transfer full) (nullable): the new [struct@RefString], or NULL on + * error. */ VipsRefString * vips_ref_string_new(const char *str) @@ -590,13 +577,14 @@ vips_ref_string_new(const char *str) /** * vips_ref_string_get: - * @refstr: the #VipsRefString to fetch from + * @refstr: the [struct@RefString] to fetch from * @length: (out) (optional): return length here, optionally * * Get a pointer to the private string inside a refstr. Handy for language * bindings. * - * See also: vips_value_get_ref_string(). + * ::: seealso + * [func@value_get_ref_string]. * * Returns: (transfer none): The C string held by @refstr. */ @@ -637,16 +625,17 @@ G_DEFINE_BOXED_TYPE_WITH_CODE(VipsRefString, vips_ref_string, * @data: (array length=length) (element-type guint8) (transfer full): data to store * @length: number of bytes in @data * - * Like vips_area_new(), but track a length as well. The returned #VipsBlob - * takes ownership of @data and will free it with @free_fn. Pass %NULL for + * Like [ctor@Area.new], but track a length as well. The returned [struct@Blob] + * takes ownership of @data and will free it with @free_fn. Pass `NULL` for * @free_fn to not transfer ownership. * * An area of mem with a free func and a length (some sort of binary object, * like an ICC profile). * - * See also: vips_area_unref(). + * ::: seealso + * [method@Area.unref]. * - * Returns: (transfer full): the new #VipsBlob. + * Returns: (transfer full): the new [struct@Blob]. */ VipsBlob * vips_blob_new(VipsCallbackFn free_fn, const void *data, size_t length) @@ -664,12 +653,13 @@ vips_blob_new(VipsCallbackFn free_fn, const void *data, size_t length) * @data: (array length=length) (element-type guint8) (transfer none): data to store * @length: number of bytes in @data * - * Like vips_blob_new(), but take a copy of the data. Useful for bindings + * Like [ctor@Blob.new], but take a copy of the data. Useful for bindings * which struggle with callbacks. * - * See also: vips_blob_new(). + * ::: seealso + * [ctor@Blob.new]. * - * Returns: (transfer full): the new #VipsBlob. + * Returns: (transfer full): the new [struct@Blob]. */ VipsBlob * vips_blob_copy(const void *data, size_t length) @@ -687,12 +677,13 @@ vips_blob_copy(const void *data, size_t length) /** * vips_blob_get: - * @blob: #VipsBlob to fetch from + * @blob: [struct@Blob] to fetch from * @length: return number of bytes of data * - * Get the data from a #VipsBlob. + * Get the data from a [struct@Blob]. * - * See also: vips_blob_new(). + * ::: seealso + * [ctor@Blob.new]. * * Returns: (array length=length) (element-type guint8) (transfer none): the * data @@ -706,7 +697,7 @@ vips_blob_get(VipsBlob *blob, size_t *length) /** * vips_blob_set: - * @blob: #VipsBlob to set + * @blob: [struct@Blob] to set * @free_fn: (scope async) (allow-none): @data will be freed with this function * @data: (array length=length) (element-type guint8) (transfer full): data to store * @length: number of bytes in @data @@ -716,7 +707,8 @@ vips_blob_get(VipsBlob *blob, size_t *length) * It's sometimes useful to be able to create blobs as empty and then fill * them later. * - * See also: vips_blob_new(). + * ::: seealso + * [ctor@Blob.new]. */ void vips_blob_set(VipsBlob *blob, @@ -724,7 +716,7 @@ vips_blob_set(VipsBlob *blob, { VipsArea *area = VIPS_AREA(blob); - g_mutex_lock(area->lock); + g_mutex_lock(&area->lock); vips_area_free(area); @@ -732,7 +724,7 @@ vips_blob_set(VipsBlob *blob, area->length = length; area->data = (void *) data; - g_mutex_unlock(area->lock); + g_mutex_unlock(&area->lock); } /* Transform a blob to a G_TYPE_STRING. @@ -813,11 +805,12 @@ G_DEFINE_BOXED_TYPE_WITH_CODE(VipsBlob, vips_blob, * @n: number of ints * * Allocate a new array of ints and copy @array into it. Free with - * vips_area_unref(). + * [method@Area.unref]. * - * See also: #VipsArea. + * ::: seealso + * [struct@Area]. * - * Returns: (transfer full): A new #VipsArrayInt. + * Returns: (transfer full): A new [struct@ArrayInt]. */ VipsArrayInt * vips_array_int_new(const int *array, int n) @@ -838,11 +831,12 @@ vips_array_int_new(const int *array, int n) * @...: list of int arguments * * Allocate a new array of @n ints and copy @... into it. Free with - * vips_area_unref(). + * [method@Area.unref]. * - * See also: vips_array_int_new() + * ::: seealso + * [ctor@ArrayInt.new] * - * Returns: (transfer full): A new #VipsArrayInt. + * Returns: (transfer full): A new [struct@ArrayInt]. */ VipsArrayInt * vips_array_int_newv(int n, ...) @@ -865,10 +859,10 @@ vips_array_int_newv(int n, ...) /** * vips_array_int_get: - * @array: the #VipsArrayInt to fetch from + * @array: the [struct@ArrayInt] to fetch from * @n: length of array * - * Fetch an int array from a #VipsArrayInt. Useful for language bindings. + * Fetch an int array from a [struct@ArrayInt]. Useful for language bindings. * * Returns: (array length=n) (transfer none): array of int */ @@ -1058,11 +1052,12 @@ G_DEFINE_BOXED_TYPE_WITH_CODE(VipsArrayInt, vips_array_int, * @n: number of doubles * * Allocate a new array of doubles and copy @array into it. Free with - * vips_area_unref(). + * [method@Area.unref]. * - * See also: #VipsArea. + * ::: seealso + * [struct@Area]. * - * Returns: (transfer full): A new #VipsArrayDouble. + * Returns: (transfer full): A new [struct@ArrayDouble]. */ VipsArrayDouble * vips_array_double_new(const double *array, int n) @@ -1083,11 +1078,12 @@ vips_array_double_new(const double *array, int n) * @...: list of double arguments * * Allocate a new array of @n doubles and copy @... into it. Free with - * vips_area_unref(). + * [method@Area.unref]. * - * See also: vips_array_double_new() + * ::: seealso + * [ctor@ArrayDouble.new] * - * Returns: (transfer full): A new #VipsArrayDouble. + * Returns: (transfer full): A new [struct@ArrayDouble]. */ VipsArrayDouble * vips_array_double_newv(int n, ...) @@ -1110,10 +1106,10 @@ vips_array_double_newv(int n, ...) /** * vips_array_double_get: - * @array: the #VipsArrayDouble to fetch from + * @array: the [struct@ArrayDouble] to fetch from * @n: length of array * - * Fetch a double array from a #VipsArrayDouble. Useful for language bindings. + * Fetch a double array from a [struct@ArrayDouble]. Useful for language bindings. * * Returns: (array length=n) (transfer none): array of double */ @@ -1268,22 +1264,23 @@ G_DEFINE_BOXED_TYPE_WITH_CODE(VipsArrayDouble, vips_array_double, /** * vips_array_image_new: (constructor) - * @array: (array length=n): array of #VipsImage + * @array: (array length=n): array of [class@Image] * @n: number of images * * Allocate a new array of images and copy @array into it. Free with - * vips_area_unref(). + * [method@Area.unref]. * * The images will all be reffed by this function. They * will be automatically unreffed for you by - * vips_area_unref(). + * [method@Area.unref]. * * Add an extra NULL element at the end, handy for eg. - * vips_image_pipeline_array() etc. + * [func@Image.pipeline_array] etc. * - * See also: #VipsArea. + * ::: seealso + * [struct@Area]. * - * Returns: (transfer full): A new #VipsArrayImage. + * Returns: (transfer full): A new [struct@ArrayImage]. */ VipsArrayImage * vips_array_image_new(VipsImage **array, int n) @@ -1307,21 +1304,22 @@ vips_array_image_new(VipsImage **array, int n) /** * vips_array_image_newv: (constructor) * @n: number of images - * @...: list of #VipsImage arguments + * @...: list of [class@Image] arguments * - * Allocate a new array of @n #VipsImage and copy @... into it. Free with - * vips_area_unref(). + * Allocate a new array of @n [class@Image] and copy @... into it. Free with + * [method@Area.unref]. * * The images will all be reffed by this function. They * will be automatically unreffed for you by - * vips_area_unref(). + * [method@Area.unref]. * * Add an extra NULL element at the end, handy for eg. - * vips_image_pipeline_array() etc. + * [func@Image.pipeline_array] etc. * - * See also: vips_array_image_new() + * ::: seealso + * [ctor@ArrayImage.new] * - * Returns: (transfer full): A new #VipsArrayImage. + * Returns: (transfer full): A new [struct@ArrayImage]. */ VipsArrayImage * vips_array_image_newv(int n, ...) @@ -1395,12 +1393,13 @@ vips_array_image_new_from_string(const char *string, VipsAccess access) * vips_array_image_empty: (constructor) * * Make an empty image array. - * Handy with vips_array_image_add() for bindings + * Handy with [method@ArrayImage.append] for bindings * which can't handle object array arguments. * - * See also: vips_array_image_add(). + * ::: seealso + * [method@ArrayImage.append]. * - * Returns: (transfer full): A new #VipsArrayImage. + * Returns: (transfer full): A new [struct@ArrayImage]. */ VipsArrayImage * vips_array_image_empty(void) @@ -1413,14 +1412,15 @@ vips_array_image_empty(void) * @array: (transfer none): append to this * @image: add this * - * Make a new #VipsArrayImage, one larger than @array, with @image appended + * Make a new [struct@ArrayImage], one larger than @array, with @image appended * to the end. - * Handy with vips_array_image_empty() for bindings + * Handy with [ctor@ArrayImage.empty] for bindings * which can't handle object array arguments. * - * See also: vips_array_image_empty(). + * ::: seealso + * [ctor@ArrayImage.empty]. * - * Returns: (transfer full): A new #VipsArrayImage. + * Returns: (transfer full): A new [struct@ArrayImage]. */ VipsArrayImage * vips_array_image_append(VipsArrayImage *array, VipsImage *image) @@ -1450,12 +1450,12 @@ vips_array_image_append(VipsArrayImage *array, VipsImage *image) /** * vips_array_image_get: - * @array: the #VipsArrayImage to fetch from + * @array: the [struct@ArrayImage] to fetch from * @n: length of array * - * Fetch an image array from a #VipsArrayImage. Useful for language bindings. + * Fetch an image array from a [struct@ArrayImage]. Useful for language bindings. * - * Returns: (array length=n) (transfer none): array of #VipsImage + * Returns: (array length=n) (transfer none): array of [class@Image] */ VipsImage ** vips_array_image_get(VipsArrayImage *array, int *n) @@ -1578,8 +1578,8 @@ vips_value_set_save_string(GValue *value, const char *str) /** * vips_value_set_save_stringf: * @value: (out): GValue to set - * @fmt: printf()-style format string - * @...: arguments to printf()-formatted @fmt + * @fmt: `printf()`-style format string + * @...: arguments to `printf()`-formatted @fmt * * Generates a string and copies it into @value. */ @@ -1600,10 +1600,10 @@ vips_value_set_save_stringf(GValue *value, const char *fmt, ...) /** * vips_value_get_ref_string: - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @length: (out) (optional): return length here, optionally * - * Get the C string held internally by the %GValue. + * Get the C string held internally by the [struct@GObject.Value]. * * Returns: (transfer none): The C string held by @value. */ @@ -1615,14 +1615,14 @@ vips_value_get_ref_string(const GValue *value, size_t *length) /** * vips_value_set_ref_string: - * @value: (out): %GValue to set + * @value: (out): [struct@GObject.Value] to set * @str: C string to copy into the GValue * * Copies the C string @str into @value. * * vips_ref_string are immutable C strings that are copied between images by * copying reference-counted pointers, making them much more efficient than - * regular %GValue strings. + * regular [struct@GObject.Value] strings. * * @str should be a valid utf-8 string. */ @@ -1654,7 +1654,8 @@ vips_value_set_ref_string(GValue *value, const char *str) * are saved to VIPS files for you coded as base64 inside the XML. They are * copied by copying reference-counted pointers. * - * See also: vips_value_get_blob() + * ::: seealso + * [func@value_get_blob] */ void vips_value_set_blob(GValue *value, @@ -1676,13 +1677,14 @@ vips_value_set_blob(GValue *value, * memory * @length: length of memory area * - * Just like vips_value_set_blob(), but when + * Just like [func@value_set_blob], but when * @value is freed, @data will be - * freed with g_free(). + * freed with [func@GLib.free]. * * This can be easier to call for language bindings. * - * See also: vips_value_set_blob() + * ::: seealso + * [func@value_set_blob] */ void vips_value_set_blob_free(GValue *value, void *data, size_t length) @@ -1707,7 +1709,8 @@ vips_value_set_blob_free(GValue *value, void *data, size_t length) * are saved to VIPS files for you coded as base64 inside the XML. They are * copied by copying reference-counted pointers. * - * See also: vips_value_set_blob() + * ::: seealso + * [func@value_set_blob] * * Returns: (transfer none) (array length=length) (element-type guint8): The pointer held * by @value. @@ -1720,7 +1723,7 @@ vips_value_get_blob(const GValue *value, size_t *length) /** * vips_value_set_array: - * @value: (out): %GValue to set + * @value: (out): [struct@GObject.Value] to set * @n: number of elements * @type: the type of each element * @sizeof_type: the sizeof each element @@ -1742,7 +1745,7 @@ vips_value_set_array(GValue *value, int n, GType type, size_t sizeof_type) /** * vips_value_get_array: - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @n: (out) (optional): return the number of elements here, optionally * @type: (out) (optional): return the type of each element here, optionally * @sizeof_type: (out) (optional): return the sizeof each element here, optionally @@ -1751,7 +1754,8 @@ vips_value_set_array(GValue *value, int n, GType type, size_t sizeof_type) * Optionally return the other properties of the array in @n, @type, * @sizeof_type. * - * See also: vips_value_set_array(). + * ::: seealso + * [func@value_set_array]. * * Returns: (transfer none): The array address. */ @@ -1779,13 +1783,14 @@ vips_value_get_array(const GValue *value, /** * vips_value_get_array_int: - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @n: (out) (optional): return the number of elements here, optionally * * Return the start of the array of ints held by @value. * optionally return the number of elements in @n. * - * See also: vips_array_int_new(). + * ::: seealso + * [ctor@ArrayInt.new]. * * Returns: (transfer none) (array length=n): The array address. */ @@ -1797,13 +1802,14 @@ vips_value_get_array_int(const GValue *value, int *n) /** * vips_value_set_array_int: - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @array: (array length=n) (allow-none): array of ints * @n: the number of elements * * Set @value to hold a copy of @array. Pass in the array length in @n. * - * See also: vips_array_int_get(). + * ::: seealso + * [method@ArrayInt.get]. */ void vips_value_set_array_int(GValue *value, const int *array, int n) @@ -1820,13 +1826,14 @@ vips_value_set_array_int(GValue *value, const int *array, int n) /** * vips_value_get_array_double: - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @n: (out) (optional): return the number of elements here, optionally * * Return the start of the array of doubles held by @value. * optionally return the number of elements in @n. * - * See also: vips_array_double_new(). + * ::: seealso + * [ctor@ArrayDouble.new]. * * Returns: (transfer none) (array length=n): The array address. */ @@ -1838,13 +1845,14 @@ vips_value_get_array_double(const GValue *value, int *n) /** * vips_value_set_array_double: - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @array: (array length=n) (allow-none): array of doubles * @n: the number of elements * * Set @value to hold a copy of @array. Pass in the array length in @n. * - * See also: vips_array_double_get(). + * ::: seealso + * [method@ArrayDouble.get]. */ void vips_value_set_array_double(GValue *value, const double *array, int n) @@ -1861,13 +1869,14 @@ vips_value_set_array_double(GValue *value, const double *array, int n) /** * vips_value_get_array_image: - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @n: (out) (optional): return the number of elements here, optionally * * Return the start of the array of images held by @value. * optionally return the number of elements in @n. * - * See also: vips_value_set_array_image(). + * ::: seealso + * [func@value_set_array_image]. * * Returns: (transfer none) (array length=n): The array address. */ @@ -1879,12 +1888,13 @@ vips_value_get_array_image(const GValue *value, int *n) /** * vips_value_set_array_image: - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @n: the number of elements * * Set @value to hold an array of images. Pass in the array length in @n. * - * See also: vips_array_image_get(). + * ::: seealso + * [method@ArrayImage.get]. */ void vips_value_set_array_image(GValue *value, int n) @@ -1899,13 +1909,14 @@ vips_value_set_array_image(GValue *value, int n) /** * vips_value_get_array_object: (skip) - * @value: %GValue to get from + * @value: [struct@GObject.Value] to get from * @n: (out) (optional): return the number of elements here, optionally * - * Return the start of the array of %GObject held by @value. + * Return the start of the array of [class@GObject.Object] held by @value. * Optionally return the number of elements in @n. * - * See also: vips_area_new_array_object(). + * ::: seealso + * [ctor@Area.new_array_object]. * * Returns: (transfer none) (array length=n): The array address. */ @@ -1917,12 +1928,13 @@ vips_value_get_array_object(const GValue *value, int *n) /** * vips_value_set_array_object: - * @value: (out): %GValue to set + * @value: (out): [struct@GObject.Value] to set * @n: the number of elements * - * Set @value to hold an array of %GObject. Pass in the array length in @n. + * Set @value to hold an array of [class@GObject.Object]. Pass in the array length in @n. * - * See also: vips_value_get_array_object(). + * ::: seealso + * [func@value_get_array_object]. */ void vips_value_set_array_object(GValue *value, int n) diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index acf78ade81..345e74ec65 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -68,7 +68,14 @@ #define MODE_READ CLOEXEC(BINARYIZE(O_RDONLY)) -/* Test two lists for eqality. +/** + * vips_slist_equal: + * @l1: (element-type guint8): a [struct@GLib.SList] + * @l2: (element-type guint8): another [struct@GLib.SList] + * + * Test two lists for equality. + * + * Returns: `TRUE` if @l1 is equal to @l2. `FALSE` otherwise. */ gboolean vips_slist_equal(GSList *l1, GSList *l2) @@ -87,7 +94,17 @@ vips_slist_equal(GSList *l1, GSList *l2) return TRUE; } -/* Map over an slist. _copy() the list in case the callback changes it. +/** + * vips_slist_map2: + * @list: (element-type guint8): a [struct@GLib.SList] + * @fn: (scope call): function to apply to each list element + * @a: user data + * @b: user data + * + * Map over a slist. _copy() the list in case the callback changes it. + * + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. */ void * vips_slist_map2(GSList *list, VipsSListMap2Fn fn, void *a, void *b) @@ -105,7 +122,17 @@ vips_slist_map2(GSList *list, VipsSListMap2Fn fn, void *a, void *b) return result; } -/* Map backwards. We _reverse() rather than recurse and unwind to save stack. +/** + * vips_slist_map2_rev: + * @list: (element-type guint8): a [struct@GLib.SList] + * @fn: (scope call): function to apply to each list element + * @a: user data + * @b: user data + * + * Map backwards. We _reverse() rather than recurse and unwind to save stack. + * + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. */ void * vips_slist_map2_rev(GSList *list, VipsSListMap2Fn fn, void *a, void *b) @@ -124,6 +151,20 @@ vips_slist_map2_rev(GSList *list, VipsSListMap2Fn fn, void *a, void *b) return result; } +/** + * vips_slist_map4: + * @list: (element-type guint8): a [struct@GLib.SList] + * @fn: (scope call): function to apply to each list element + * @a: user data + * @b: user data + * @c: user data + * @d: user data + * + * Map over a slist. _copy() the list in case the callback changes it. + * + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. + */ void * vips_slist_map4(GSList *list, VipsSListMap4Fn fn, void *a, void *b, void *c, void *d) @@ -142,6 +183,19 @@ vips_slist_map4(GSList *list, return result; } +/** + * vips_slist_fold2: + * @list: (element-type guint8): a [struct@GLib.SList] + * @start: initial value for the accumulator + * @fn: (scope call): function to apply to each list element + * @a: user data + * @b: user data + * + * Fold over a slist, applying @fn to each element. + * + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. + */ void * vips_slist_fold2(GSList *list, void *start, VipsSListFold2Fn fn, void *a, void *b) @@ -159,7 +213,17 @@ vips_slist_fold2(GSList *list, void *start, return c; } -/* Remove all occurrences of an item from a list. +/** + * vips_slist_filter: + * @list: (element-type guint8): a [struct@GLib.SList] + * @fn: (scope call): function to call for each element. + * @a: user data + * @b: user data + * + * Remove all occurrences of an item from a list. + * Returns the new head of the list. + * + * Returns: (element-type guint8) (transfer full): new head of @list */ GSList * vips_slist_filter(GSList *list, VipsSListMap2Fn fn, void *a, void *b) @@ -198,7 +262,11 @@ vips_slist_free_all_cb(void *thing, void *dummy) g_free(thing); } -/* Free a g_slist of things which need g_free()ing. +/** + * vips_slist_free_all: + * @list: (element-type guint8): a [struct@GLib.SList] + * + * Free a [struct@GLib.SList] of things which need [func@GLib.free]ing. */ void vips_slist_free_all(GSList *list) @@ -229,7 +297,17 @@ vips_hash_table_predicate(const char *key, void *value, Pair *pair) return (pair->result = pair->fn(value, pair->a, pair->b)) != NULL; } -/* Like slist map, but for a hash table. +/** + * vips_hash_table_map: + * @hash: a [struct@GLib.HashTable] + * @fn: (scope call): function to apply to each hash value + * @a: user data + * @b: user data + * + * Like slist map, but for a hash table. + * + * Returns: `NULL` if @fn returns `NULL` for all arguments, otherwise the first + * non-`NULL` value from @fn. */ void * vips_hash_table_map(GHashTable *hash, VipsSListMap2Fn fn, void *a, void *b) @@ -850,7 +928,11 @@ vips__gvalue_ref_string_new(const char *text) return value; } -/* Free a GSList of GValue. +/** + * vips__gslist_gvalue_free: + * @list: (element-type GValue): a [struct@GLib.SList] of GValue + * + * Free a GSList of GValue. */ void vips__gslist_gvalue_free(GSList *list) @@ -859,7 +941,13 @@ vips__gslist_gvalue_free(GSList *list) g_slist_free(list); } -/* Copy a GSList of GValue. +/** + * vips__gslist_gvalue_copy: + * @list: (element-type GValue): a [struct@GLib.SList] of GValue + * + * Copy a GSList of GValue. + * + * Returns: (element-type GValue) (transfer full): a copy of @list */ GSList * vips__gslist_gvalue_copy(const GSList *list) @@ -878,9 +966,15 @@ vips__gslist_gvalue_copy(const GSList *list) return copy; } -/* Merge two GSList of GValue ... append to a all elements in b which are not - * in a. Return the new value of a. Works for any vips refcounted type - * (string, blob, etc.). +/** + * vips__gslist_gvalue_merge: + * @a: (element-type GValue): a [struct@GLib.SList] of GValue + * @b: (element-type GValue): a [struct@GLib.SList] of GValue + * + * Merge two GSList of GValue ... append to a all elements in b which are not + * in a. Works for any vips refcounted type (string, blob, etc.). + * + * Returns: (element-type GValue) (transfer full): the new value of @a */ GSList * vips__gslist_gvalue_merge(GSList *a, const GSList *b) @@ -919,8 +1013,16 @@ vips__gslist_gvalue_merge(GSList *a, const GSList *b) return a; } -/* Make a char * from GSList of GValue. Each GValue should be a ref_string. - * free the result. Empty list -> "", not NULL. Join strings with '\n'. +/** + * vips__gslist_gvalue_get: + * @list: (element-type GValue): a [struct@GLib.SList] of GValue + * + * Make a char * from GSList of GValue. Each GValue should be a ref_string. + * + * If @list is empty, the return value will be `NULL`. + * + * Returns: (transfer full) (nullable): a newly-allocated string containing + * all of the list elements joined together, with '\n' between them. */ char * vips__gslist_gvalue_get(const GSList *list) @@ -1610,6 +1712,7 @@ vips__parse_size(const char *size_string) */ unit = g_strdup(size_string); + size = 0; n = sscanf(size_string, "%" G_GUINT64_FORMAT " %s", &size, unit); if (n > 1) for (int j = 0; j < VIPS_NUMBER(units); j++) diff --git a/libvips/iofuncs/vector.cpp b/libvips/iofuncs/vector.cpp index 2c1802ce52..a98d72174e 100644 --- a/libvips/iofuncs/vector.cpp +++ b/libvips/iofuncs/vector.cpp @@ -87,7 +87,7 @@ vips__vector_init(void) /* Look for the deprecated IM_NOVECTOR environment variable as well. */ if (g_getenv("VIPS_NOVECTOR") -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED || g_getenv("IM_NOVECTOR") #endif ) @@ -133,7 +133,7 @@ vips_vector_get_builtin_targets(void) * vips_vector_get_supported_targets: * * Gets a bitfield of enabled targets that are supported on this CPU. The - * targets returned may change after calling vips_vector_disable_targets(). + * targets returned may change after calling [func@vector_disable_targets]. * * Returns: a bitfield of supported CPU targets. */ diff --git a/libvips/iofuncs/vips.c b/libvips/iofuncs/vips.c index cd44d7d1c5..078e669e4a 100644 --- a/libvips/iofuncs/vips.c +++ b/libvips/iofuncs/vips.c @@ -103,20 +103,6 @@ #include #include -/** - * SECTION: vips - * @short_description: startup, shutdown, version - * @stability: Stable - * @see_also: VipsOperation - * @include: vips/vips.h - * - * Start VIPS up, shut VIPS down, get version information, relocation. - * - * VIPS is a relocatable package, meaning you can move the directory tree you - * compiled it to at runtime and it will still be able to find all data files. - * This is required for OS X and Windows, but slightly unusual in the Unix - * world. See vips_init() and vips_guess_prefix(). - */ /* Open mode for image write. * @@ -386,7 +372,7 @@ vips__read_header_bytes(VipsImage *im, unsigned char *from) * pixel interpretation, don't clip them. */ - /* Coding values imply Bands and BandFmt settings --- make sure they + /* Coding values imply Bands and BandFmt settings -- make sure they * are sane. */ switch (im->Coding) { diff --git a/libvips/iofuncs/window.c b/libvips/iofuncs/window.c index 43b35fab7d..216b83547d 100644 --- a/libvips/iofuncs/window.c +++ b/libvips/iofuncs/window.c @@ -56,7 +56,6 @@ #include #include -#include #ifdef G_OS_WIN32 #include @@ -93,10 +92,10 @@ vips_window_unmap(VipsWindow *window) return -1; #ifdef DEBUG_TOTAL - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); total_mmap_usage -= window->length; g_assert(total_mmap_usage >= 0); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); #endif /*DEBUG_TOTAL*/ window->data = NULL; @@ -139,7 +138,7 @@ vips_window_unref(VipsWindow *window) { VipsImage *im = window->im; - g_mutex_lock(im->sslock); + g_mutex_lock(&im->sslock); #ifdef DEBUG printf("vips_window_unref: window top = %d, height = %d, count = %d\n", @@ -152,12 +151,12 @@ vips_window_unref(VipsWindow *window) if (window->ref_count == 0) { if (vips_window_free(window)) { - g_mutex_unlock(im->sslock); + g_mutex_unlock(&im->sslock); return -1; } } - g_mutex_unlock(im->sslock); + g_mutex_unlock(&im->sslock); return 0; } @@ -166,7 +165,7 @@ vips_window_unref(VipsWindow *window) static void trace_mmap_usage(void) { - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); { static int last_total = 0; int total = total_mmap_usage / (1024 * 1024); @@ -179,7 +178,7 @@ trace_mmap_usage(void) last_total = total; } } - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); } #endif /*DEBUG_TOTAL*/ @@ -252,11 +251,11 @@ vips_window_set(VipsWindow *window, int top, int height) vips__read_test &= window->data[0]; #ifdef DEBUG_TOTAL - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); total_mmap_usage += window->length; if (total_mmap_usage > max_mmap_usage) max_mmap_usage = total_mmap_usage; - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); trace_mmap_usage(); #endif /*DEBUG_TOTAL*/ @@ -353,20 +352,20 @@ vips_window_take(VipsWindow *window, VipsImage *im, int top, int height) window->top + window->height >= top + height) return window; - g_mutex_lock(im->sslock); + g_mutex_lock(&im->sslock); /* We have a window and we are the only ref to it ... scroll. */ if (window && window->ref_count == 1) { if (vips_window_set(window, top, height)) { - g_mutex_unlock(im->sslock); + g_mutex_unlock(&im->sslock); vips_window_unref(window); return NULL; } - g_mutex_unlock(im->sslock); + g_mutex_unlock(&im->sslock); return window; } @@ -380,7 +379,7 @@ vips_window_take(VipsWindow *window, VipsImage *im, int top, int height) /* Is there an existing window we can reuse? */ if ((window = vips_window_find(im, top, height))) { - g_mutex_unlock(im->sslock); + g_mutex_unlock(&im->sslock); return window; } @@ -396,11 +395,11 @@ vips_window_take(VipsWindow *window, VipsImage *im, int top, int height) height = VIPS_CLIP(0, height, im->Ysize - top); if (!(window = vips_window_new(im, top, height))) { - g_mutex_unlock(im->sslock); + g_mutex_unlock(&im->sslock); return NULL; } - g_mutex_unlock(im->sslock); + g_mutex_unlock(&im->sslock); return window; } diff --git a/libvips/meson.build b/libvips/meson.build index f89a93f252..ff55c98781 100644 --- a/libvips/meson.build +++ b/libvips/meson.build @@ -45,13 +45,14 @@ if enable_introspection vips_gir = gnome.generate_gir( libvips_lib, namespace: 'Vips', - nsversion: '8.0', + nsversion: '@0@.0'.format(version_major), identifier_prefix: 'Vips', symbol_prefix: 'vips', + export_packages: 'vips', header: 'vips/vips.h', sources: libvips_sources, dependencies: libvips_deps, - includes: 'GObject-2.0', + includes: ['GObject-2.0', 'Gio-2.0'], install: true ) diff --git a/libvips/morphology/countlines.c b/libvips/morphology/countlines.c index 265fc8d4ad..916d4fc9cb 100644 --- a/libvips/morphology/countlines.c +++ b/libvips/morphology/countlines.c @@ -160,7 +160,7 @@ vips_countlines_init(VipsCountlines *countlines) * @in: input image * @nolines: (out): output average number of lines * @direction: count lines horizontally or vertically - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Function which calculates the number of transitions * between black and white for the horizontal or the vertical @@ -169,7 +169,8 @@ vips_countlines_init(VipsCountlines *countlines) * Xsize or Ysize and returns the mean of the result * Input should be one band, 8-bit. * - * See also: vips_morph(), vips_conv(). + * ::: seealso + * [method@Image.morph], [method@Image.conv]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/morphology/labelregions.c b/libvips/morphology/labelregions.c index a30f50d574..bd7ac22045 100644 --- a/libvips/morphology/labelregions.c +++ b/libvips/morphology/labelregions.c @@ -143,11 +143,9 @@ vips_labelregions_init(VipsLabelregions *labelregions) * vips_labelregions: (method) * @in: image to test * @mask: write labelled regions here - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @segments: return number of regions found here + * Label regions of equal pixels in an image. * * Repeatedly scans @in for regions of 4-connected pixels * with the same pixel value. Every time a region is discovered, those @@ -155,16 +153,20 @@ vips_labelregions_init(VipsLabelregions *labelregions) * have been labelled, the operation returns, setting @segments to the number * of discrete regions which were detected. * - * @mask is always a 1-band #VIPS_FORMAT_INT image of the same dimensions as - * @in. + * @mask is always a 1-band [enum@Vips.BandFormat.INT] image of the same + * dimensions as @in. * * This operation is useful for, for example, blob counting. You can use the * morphological operators to detect and isolate a series of objects, then use - * vips_labelregions() to number them all. + * [method@Image.labelregions] to number them all. + * + * Use [method@Image.hist_find_indexed] to (for example) find blob coordinates. * - * Use vips_hist_find_indexed() to (for example) find blob coordinates. + * ::: tip "Optional arguments" + * * @segments: `gint`, return number of regions found here * - * See also: vips_hist_find_indexed(). + * ::: seealso + * [method@Image.hist_find_indexed]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/morphology/morph.c b/libvips/morphology/morph.c index c7637177cd..5cdb83c417 100644 --- a/libvips/morphology/morph.c +++ b/libvips/morphology/morph.c @@ -94,6 +94,7 @@ typedef struct { int r; /* Set previous result in this var */ int d1; /* The destination var */ + int n_const; int n_scanline; /* The associated line corresponding to the scanline. @@ -113,7 +114,8 @@ typedef struct { * * More like hit-miss, really. * - * See also: vips_morph(). + * ::: seealso + * [method@Image.morph]. */ typedef struct { @@ -149,10 +151,9 @@ typedef struct { VipsMorph *morph; VipsRegion *ir; /* Input region */ - int *soff; /* Offsets we check for set */ - int ss; /* ... and number we check for set */ - guint8 *coff; /* Offsets we check for clear */ - int cs; /* ... and number we check for clear */ + int *off; /* Offsets for each non-128 matrix element */ + int nn128; /* Number of non-128 mask elements */ + guint8 *coeff; /* Array of non-128 mask coefficients */ int last_bpl; /* Avoid recalcing offsets, if we can */ @@ -212,10 +213,9 @@ vips_morph_start(VipsImage *out, void *a, void *b) */ seq->morph = morph; seq->ir = NULL; - seq->soff = NULL; - seq->ss = 0; - seq->coff = NULL; - seq->cs = 0; + seq->off = NULL; + seq->nn128 = 0; + seq->coeff = NULL; seq->last_bpl = -1; #ifdef HAVE_ORC seq->t1 = NULL; @@ -224,11 +224,11 @@ vips_morph_start(VipsImage *out, void *a, void *b) seq->ir = vips_region_new(in); - seq->soff = VIPS_ARRAY(out, morph->n_point, int); - seq->coff = VIPS_ARRAY(out, morph->n_point, guint8); + seq->off = VIPS_ARRAY(out, morph->n_point, int); + seq->coeff = VIPS_ARRAY(out, morph->n_point, guint8); - if (!seq->soff || - !seq->coff) { + if (!seq->off || + !seq->coeff) { vips_morph_stop(seq, in, morph); return NULL; } @@ -263,13 +263,8 @@ vips_dilate_vector_gen(VipsRegion *out_region, VipsImage *M = morph->M; VipsRegion *ir = seq->ir; - /* Offsets for each non-128 matrix element. - */ - int *soff = seq->soff; - - /* Array of non-128 mask coefficients. - */ - guint8 *coff = seq->coff; + int *off = seq->off; + guint8 *coeff = seq->coeff; VipsRect *r = &out_region->valid; int sz = VIPS_REGION_N_ELEMENTS(out_region); @@ -298,9 +293,7 @@ vips_dilate_vector_gen(VipsRegion *out_region, if (seq->last_bpl != VIPS_REGION_LSKIP(ir)) { seq->last_bpl = VIPS_REGION_LSKIP(ir); - /* Number of non-128 mask elements. - */ - seq->ss = 0; + seq->nn128 = 0; for (t = morph->coeff, y = 0; y < M->Ysize; y++) for (x = 0; x < M->Xsize; x++, t++) { /* Exclude don't-care elements. @@ -308,19 +301,18 @@ vips_dilate_vector_gen(VipsRegion *out_region, if (*t == 128) continue; - soff[seq->ss] = - VIPS_REGION_ADDR(ir, - x + r->left, y + r->top) - + off[seq->nn128] = + VIPS_REGION_ADDR(ir, x + r->left, y + r->top) - VIPS_REGION_ADDR(ir, r->left, r->top); - coff[seq->ss] = *t; - seq->ss++; + coeff[seq->nn128] = *t; + seq->nn128++; } } VIPS_GATE_START("vips_dilate_vector_gen: work"); vips_dilate_uchar_hwy(out_region, ir, r, - sz, seq->ss, soff, coff); + sz, seq->nn128, off, coeff); VIPS_GATE_STOP("vips_dilate_vector_gen: work"); @@ -338,13 +330,8 @@ vips_erode_vector_gen(VipsRegion *out_region, VipsImage *M = morph->M; VipsRegion *ir = seq->ir; - /* Offsets for each non-128 matrix element. - */ - int *soff = seq->soff; - - /* Array of non-128 mask coefficients. - */ - guint8 *coff = seq->coff; + int *off = seq->off; + guint8 *coeff = seq->coeff; VipsRect *r = &out_region->valid; int sz = VIPS_REGION_N_ELEMENTS(out_region); @@ -373,9 +360,7 @@ vips_erode_vector_gen(VipsRegion *out_region, if (seq->last_bpl != VIPS_REGION_LSKIP(ir)) { seq->last_bpl = VIPS_REGION_LSKIP(ir); - /* Number of non-128 mask elements. - */ - seq->ss = 0; + seq->nn128 = 0; for (t = morph->coeff, y = 0; y < M->Ysize; y++) for (x = 0; x < M->Xsize; x++, t++) { /* Exclude don't-care elements. @@ -383,19 +368,18 @@ vips_erode_vector_gen(VipsRegion *out_region, if (*t == 128) continue; - soff[seq->ss] = - VIPS_REGION_ADDR(ir, - x + r->left, y + r->top) - + off[seq->nn128] = + VIPS_REGION_ADDR(ir, x + r->left, y + r->top) - VIPS_REGION_ADDR(ir, r->left, r->top); - coff[seq->ss] = *t; - seq->ss++; + coeff[seq->nn128] = *t; + seq->nn128++; } } VIPS_GATE_START("vips_erode_vector_gen: work"); vips_erode_uchar_hwy(out_region, ir, r, - sz, seq->ss, soff, coff); + sz, seq->nn128, off, coeff); VIPS_GATE_STOP("vips_erode_vector_gen: work"); @@ -444,6 +428,7 @@ vips_morph_compile_section(VipsMorph *morph, Pass *pass, gboolean first_pass) CONST("zero", 0, 1); CONST("one", 255, 1); + pass->n_const += 2; /* Init the sum. If this is the first pass, it's a constant. If this * is a later pass, we have to init the sum from the result @@ -483,8 +468,10 @@ vips_morph_compile_section(VipsMorph *morph, Pass *pass, gboolean first_pass) */ if (x > 0) { g_snprintf(offset, 256, "c%db", x); - if (orc_program_find_var_by_name(p, offset) == -1) + if (orc_program_find_var_by_name(p, offset) == -1) { CONST(offset, morphology->in->Bands * x, 1); + pass->n_const++; + } ASM3("loadoffb", "value", source, offset); } else @@ -511,6 +498,12 @@ vips_morph_compile_section(VipsMorph *morph, Pass *pass, gboolean first_pass) ASM3("andb", "sum", "sum", "value"); } + /* orc allows up to 8 constants, so break early once we + * approach this limit. + */ + if (pass->n_const >= 7 /*ORC_MAX_CONST_VARS - 1*/) + break; + /* You can have 8 sources, and pass->r counts as one of them, * so +1 there. */ @@ -524,9 +517,9 @@ vips_morph_compile_section(VipsMorph *morph, Pass *pass, gboolean first_pass) /* Some orcs seem to be unstable with many compilers active at once. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); result = orc_program_compile(p); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) return -1; @@ -571,6 +564,7 @@ vips_morph_compile(VipsMorph *morph) pass->first = i; pass->last = i; pass->r = -1; + pass->n_const = 0; pass->n_scanline = 0; if (vips_morph_compile_section(morph, pass, morph->n_pass == 1)) @@ -667,8 +661,8 @@ vips_dilate_gen(VipsRegion *out_region, VipsImage *M = morph->M; VipsRegion *ir = seq->ir; - int *soff = seq->soff; - guint8 *coff = seq->coff; + int *off = seq->off; + guint8 *coeff = seq->coeff; VipsRect *r = &out_region->valid; int le = r->left; @@ -701,37 +695,24 @@ vips_dilate_gen(VipsRegion *out_region, if (seq->last_bpl != VIPS_REGION_LSKIP(ir)) { seq->last_bpl = VIPS_REGION_LSKIP(ir); - seq->ss = 0; - seq->cs = 0; + seq->nn128 = 0; for (t = morph->coeff, y = 0; y < M->Ysize; y++) - for (x = 0; x < M->Xsize; x++, t++) - switch (*t) { - case 255: - soff[seq->ss++] = - VIPS_REGION_ADDR(ir, - x + le, y + to) - - VIPS_REGION_ADDR(ir, le, to); - break; - - case 128: - break; - - case 0: - coff[seq->cs++] = - VIPS_REGION_ADDR(ir, - x + le, y + to) - - VIPS_REGION_ADDR(ir, le, to); - break; - - default: - g_assert_not_reached(); - } + for (x = 0; x < M->Xsize; x++, t++) { + /* Exclude don't-care elements. + */ + if (*t == 128) + continue; + + off[seq->nn128] = + VIPS_REGION_ADDR(ir, x + le, y + to) - + VIPS_REGION_ADDR(ir, le, to); + coeff[seq->nn128] = *t; + seq->nn128++; + } } VIPS_GATE_START("vips_dilate_gen: work"); - /* Dilate! - */ for (y = to; y < bo; y++) { VipsPel *p = VIPS_REGION_ADDR(ir, le, y); VipsPel *q = VIPS_REGION_ADDR(out_region, le, y); @@ -739,28 +720,11 @@ vips_dilate_gen(VipsRegion *out_region, /* Loop along line. */ for (x = 0; x < sz; x++, q++, p++) { - /* Search for a hit on the set list. + /* Dilate! */ result = 0; - for (i = 0; i < seq->ss; i++) - if (p[soff[i]]) { - /* Found a match! - */ - result = 255; - break; - } - - /* No set pixels ... search for a hit in the clear - * pixels. - */ - if (!result) - for (i = 0; i < seq->cs; i++) - if (!p[coff[i]]) { - /* Found a match! - */ - result = 255; - break; - } + for (i = 0; i < seq->nn128; i++) + result |= !coeff[i] ? ~p[off[i]] : p[off[i]]; *q = result; } @@ -784,8 +748,8 @@ vips_erode_gen(VipsRegion *out_region, VipsImage *M = morph->M; VipsRegion *ir = seq->ir; - int *soff = seq->soff; - guint8 *coff = seq->coff; + int *off = seq->off; + guint8 *coeff = seq->coeff; VipsRect *r = &out_region->valid; int le = r->left; @@ -818,37 +782,24 @@ vips_erode_gen(VipsRegion *out_region, if (seq->last_bpl != VIPS_REGION_LSKIP(ir)) { seq->last_bpl = VIPS_REGION_LSKIP(ir); - seq->ss = 0; - seq->cs = 0; + seq->nn128 = 0; for (t = morph->coeff, y = 0; y < M->Ysize; y++) - for (x = 0; x < M->Xsize; x++, t++) - switch (*t) { - case 255: - soff[seq->ss++] = - VIPS_REGION_ADDR(ir, - x + le, y + to) - - VIPS_REGION_ADDR(ir, le, to); - break; - - case 128: - break; - - case 0: - coff[seq->cs++] = - VIPS_REGION_ADDR(ir, - x + le, y + to) - - VIPS_REGION_ADDR(ir, le, to); - break; - - default: - g_assert_not_reached(); - } + for (x = 0; x < M->Xsize; x++, t++) { + /* Exclude don't-care elements. + */ + if (*t == 128) + continue; + + off[seq->nn128] = + VIPS_REGION_ADDR(ir, x + le, y + to) - + VIPS_REGION_ADDR(ir, le, to); + coeff[seq->nn128] = *t; + seq->nn128++; + } } VIPS_GATE_START("vips_erode_gen: work"); - /* Erode! - */ for (y = to; y < bo; y++) { VipsPel *p = VIPS_REGION_ADDR(ir, le, y); VipsPel *q = VIPS_REGION_ADDR(out_region, le, y); @@ -856,25 +807,11 @@ vips_erode_gen(VipsRegion *out_region, /* Loop along line. */ for (x = 0; x < sz; x++, q++, p++) { - /* Check all set pixels are set. + /* Erode! */ result = 255; - for (i = 0; i < seq->ss; i++) - if (!p[soff[i]]) { - /* Found a mismatch! - */ - result = 0; - break; - } - - /* Check all clear pixels are clear. - */ - if (result) - for (i = 0; i < seq->cs; i++) - if (p[coff[i]]) { - result = 0; - break; - } + for (i = 0; i < seq->nn128; i++) + result &= !coeff[i] ? ~p[off[i]] : p[off[i]]; *q = result; } @@ -950,7 +887,7 @@ vips_morph_build(VipsObject *object) coeff[i]); return -1; } - morph->coeff[i] = coeff[i]; + morph->coeff[i] = (guint8) coeff[i]; } /* Try to make a vector path. @@ -984,7 +921,7 @@ vips_morph_build(VipsObject *object) VIPS_DEMAND_STYLE_SMALLTILE, in, NULL)) return -1; - /* Prepare output. Consider a 7x7 mask and a 7x7 image --- the output + /* Prepare output. Consider a 7x7 mask and a 7x7 image -- the output * would be 1x1. */ morph->out->Xsize -= M->Xsize - 1; @@ -1053,7 +990,7 @@ vips_morph_init(VipsMorph *morph) * @out: (out): output image * @mask: morphology with this mask * @morph: operation to perform - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * Performs a morphological operation on @in using @mask as a * structuring element. @@ -1071,21 +1008,21 @@ vips_morph_init(VipsMorph *morph) * based on the book "Fundamentals of Digital Image Processing" by A. Jain, * pp 384-388, Prentice-Hall, 1989. * - * For #VIPS_OPERATION_MORPHOLOGY_ERODE, + * For [enum@Vips.OperationMorphology.ERODE], * the whole mask must match for the output pixel to be * set, that is, the result is the logical AND of the selected input pixels. * - * For #VIPS_OPERATION_MORPHOLOGY_DILATE, + * For [enum@Vips.OperationMorphology.DILATE], * the output pixel is set if any part of the mask * matches, that is, the result is the logical OR of the selected input pixels. * - * See the boolean operations vips_andimage(), vips_orimage() and - * vips_eorimage() + * See the boolean operations [method@Image.andimage], [method@Image.orimage] + * and [method@Image.eorimage] * for analogues of the usual set difference and set union operations. * * Operations are performed using the processor's vector unit, * if possible. Disable this with `--vips-novector` or `VIPS_NOVECTOR` or - * vips_vector_set_enabled() + * [func@vector_set_enabled]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/morphology/morph_hwy.cpp b/libvips/morphology/morph_hwy.cpp index 1acdf2cb19..e8c64c8704 100644 --- a/libvips/morphology/morph_hwy.cpp +++ b/libvips/morphology/morph_hwy.cpp @@ -89,7 +89,7 @@ vips_dilate_uchar_hwy(VipsRegion *out_region, VipsRegion *ir, VipsRect *r, */ auto pix = LoadU(du8, p + offsets[i]); - pix = IfThenElse(Ne(mmk, one), Xor(pix, one), pix); + pix = IfThenElse(Ne(mmk, one), AndNot(pix, one), pix); sum = Or(sum, pix); } @@ -109,7 +109,7 @@ vips_dilate_uchar_hwy(VipsRegion *out_region, VipsRegion *ir, VipsRect *r, auto pix = LoadU(du8, p + offsets[i]); if (!coeff[i]) - pix = Xor(pix, one); + pix = AndNot(pix, one); sum = Or(sum, pix); } @@ -146,9 +146,8 @@ vips_erode_uchar_hwy(VipsRegion *out_region, VipsRegion *ir, VipsRect *r, */ auto pix = LoadU(du8, p + offsets[i]); - sum = IfThenElse(Ne(mmk, one), - AndNot(pix, one), - And(sum, pix)); + pix = IfThenElse(Ne(mmk, one), AndNot(pix, one), pix); + sum = And(sum, pix); } StoreU(sum, du8, q + x); @@ -166,7 +165,9 @@ vips_erode_uchar_hwy(VipsRegion *out_region, VipsRegion *ir, VipsRect *r, */ auto pix = LoadU(du8, p + offsets[i]); - sum = !coeff[i] ? AndNot(pix, one) : And(sum, pix); + if (!coeff[i]) + pix = AndNot(pix, one); + sum = And(sum, pix); } q[x] = GetLane(sum); diff --git a/libvips/morphology/morphology.c b/libvips/morphology/morphology.c index bb655fa6f0..7704cd5e18 100644 --- a/libvips/morphology/morphology.c +++ b/libvips/morphology/morphology.c @@ -49,56 +49,6 @@ #include "pmorphology.h" -/** - * SECTION: morphology - * @short_description: morphological operators, rank filters and related image - * analysis - * @see_also: arithmetic - * @stability: Stable - * @include: vips/vips.h - * - * The morphological functions search images - * for particular patterns of pixels, specified with the mask argument, - * either adding or removing pixels when they find a match. They are useful - * for cleaning up images --- for example, you might threshold an image, and - * then use one of the morphological functions to remove all single isolated - * pixels from the result. - * - * If you combine the morphological operators with the mask rotators - * (vips_rot45(), for example) and apply them repeatedly, you - * can achieve very complicated effects: you can thin, prune, fill, open edges, - * close gaps, and many others. For example, see `Fundamentals of Digital - * Image Processing' by A. Jain, pp 384-388, Prentice-Hall, 1989 for more - * ideas. - * - * Beware that VIPS reverses the usual image processing convention, by - * assuming white objects (non-zero pixels) on a black background (zero - * pixels). - * - * The mask you give to the morphological functions should contain only the - * values 0 (for background), 128 (for don't care) and 255 (for object). The - * mask must have odd length sides --- the origin of the mask is taken to be - * the centre value. For example, the mask: - * - * VipsImage *mask = vips_image_new_matrixv(3, 3, - * 128.0, 255.0, 128.0, - * 255.0, 255.0, 255.0, - * 128.0, 255.0, 128.0); - * - * applied to an image with vips_morph() #VIPS_OPERATION_MORPHOLOGY_DILATE will - * do a 4-connected dilation. - * - * Dilate sets pixels in the output if any part of the mask matches, whereas - * erode sets pixels only if all of the mask matches. - * - * See vips_andimage(), vips_orimage() and vips_eorimage() - * for analogues of the usual set difference and set union operations. - * - * Use vips_image_new_matrixv() to create a mask in source, vips_matrixload() - * to load a mask from a simple text file, and vips_mask_ideal() and friends to - * create square, circular and ring masks of specific sizes. - */ - G_DEFINE_ABSTRACT_TYPE(VipsMorphology, vips_morphology, VIPS_TYPE_OPERATION); diff --git a/libvips/morphology/nearest.c b/libvips/morphology/nearest.c index 7ba764a165..f1a6aa225c 100644 --- a/libvips/morphology/nearest.c +++ b/libvips/morphology/nearest.c @@ -85,12 +85,6 @@ vips_fill_nearest_finalize(GObject *gobject) { VipsFillNearest *nearest = (VipsFillNearest *) gobject; -#ifdef DEBUG - printf("vips_fill_nearest_finalize: "); - vips_object_print_name(VIPS_OBJECT(gobject)); - printf("\n"); -#endif /*DEBUG*/ - VIPS_FREEF(g_array_unref, nearest->seeds); G_OBJECT_CLASS(vips_fill_nearest_parent_class)->finalize(gobject); @@ -122,7 +116,7 @@ vips_fill_nearest_pixel(Circle *circle, int x, int y, int octant) p = (float *) VIPS_IMAGE_ADDR(circle->nearest->distance, x, y); dx = x - circle->seed->x; dy = y - circle->seed->y; - radius = sqrt(dx * dx + dy * dy); + radius = sqrtf(dx * dx + dy * dy); if (p[0] == 0 || p[0] > radius) { @@ -244,8 +238,7 @@ vips_fill_nearest_build(VipsObject *object) if (i != ps) { Seed *seed; - g_array_set_size(nearest->seeds, - nearest->seeds->len + 1); + g_array_set_size(nearest->seeds, nearest->seeds->len + 1); seed = &g_array_index(nearest->seeds, Seed, nearest->seeds->len - 1); seed->x = x; @@ -261,9 +254,9 @@ vips_fill_nearest_build(VipsObject *object) /* Create the output and distance images in memory. */ g_object_set(object, "distance", vips_image_new_memory(), NULL); - if (vips_black(&t[1], nearest->width, nearest->height, NULL) || - vips_cast(t[1], &t[2], VIPS_FORMAT_FLOAT, NULL) || - vips_image_write(t[2], nearest->distance)) + if (vips_black(&t[0], nearest->width, nearest->height, NULL) || + vips_cast(t[0], &t[1], VIPS_FORMAT_FLOAT, NULL) || + vips_image_write(t[1], nearest->distance)) return -1; g_object_set(object, "out", vips_image_new_memory(), NULL); @@ -334,11 +327,7 @@ vips_fill_nearest_init(VipsFillNearest *nearest) * vips_fill_nearest: (method) * @in: image to test * @out: image with zero pixels filled with the nearest non-zero pixel - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @distance: output image of distance to nearest non-zero pixel + * @...: `NULL`-terminated list of optional named arguments * * Fill outwards from every non-zero pixel in @in, setting pixels in @distance * and @value. @@ -350,7 +339,12 @@ vips_fill_nearest_init(VipsFillNearest *nearest) * @distance is a one-band float image. @value has the same number of bands and * format as @in. * - * See also: vips_hist_find_indexed(). + * ::: tip "Optional arguments" + * * @distance: [class@Image], output image of distance to nearest + * non-zero pixel + * + * ::: seealso + * [method@Image.hist_find_indexed]. * * Returns: 0 on success, -1 on error. */ diff --git a/libvips/morphology/rank.c b/libvips/morphology/rank.c index 2151084f75..430b21580f 100644 --- a/libvips/morphology/rank.c +++ b/libvips/morphology/rank.c @@ -223,7 +223,7 @@ vips_rank_generate_uchar(VipsRegion *out_region, } q[b] = i; - /* Adapt histogram --- remove the pels from + /* Adapt histogram -- remove the pels from * the left hand column, add in pels for a * new right-hand column. */ @@ -603,9 +603,9 @@ vips_rank_init(VipsRank *rank) * @width: width of region * @height: height of region * @index: select pixel - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * vips_rank() does rank filtering on an image. A window of size @width by + * [method@Image.rank] does rank filtering on an image. A window of size @width by * @height is passed over the image. At each position, the pixels inside the * window are sorted into ascending order and the pixel at position @index is * output. @index numbers from 0. @@ -617,12 +617,15 @@ vips_rank_init(VipsRank *rank) * * For a median filter with mask size m (3 for 3x3, 5 for 5x5, etc.) use * - * vips_rank(in, out, m, m, m * m / 2); + * ```c + * vips_rank(in, out, m, m, m * m / 2); + * ``` * * The special cases n == 0 and n == m * m - 1 are useful dilate and * expand operators. * - * See also: vips_conv(), vips_median(), vips_spcor(). + * ::: seealso + * [method@Image.conv], [method@Image.median], [method@Image.spcor]. * * Returns: 0 on success, -1 on error */ @@ -645,13 +648,16 @@ vips_rank(VipsImage *in, VipsImage **out, * @in: input image * @out: (out): output image * @size: size of region - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * A convenience function equivalent to: * - * vips_rank(in, out, size, size, (size * size) / 2); + * ```c + * vips_rank(in, out, size, size, (size * size) / 2); + * ``` * - * See also: vips_rank(). + * ::: seealso + * [method@Image.rank]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/mosaicing/chkpair.c b/libvips/mosaicing/chkpair.c index d1e9284b2f..75e7b74d9c 100644 --- a/libvips/mosaicing/chkpair.c +++ b/libvips/mosaicing/chkpair.c @@ -81,11 +81,12 @@ * returned, together with the correlation at that point. * * Only the first band of each image is correlated. @ref and @sec may be - * very large --- the function extracts and generates just the - * parts needed. Correlation is done with vips_spcor(); the position of - * the maximum is found with vips_max(). + * very large -- the function extracts and generates just the + * parts needed. Correlation is done with [method@Image.spcor]; the position + * of the maximum is found with [method@Image.max]. * - * See also: vips_match(), vips__lrmosaic(). + * ::: seealso + * [method@Image.match], [method@Image.mosaic]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/mosaicing/global_balance.c b/libvips/mosaicing/global_balance.c index b7f39d5253..1ba48ff9f6 100644 --- a/libvips/mosaicing/global_balance.c +++ b/libvips/mosaicing/global_balance.c @@ -1103,7 +1103,7 @@ find_image_stats(VipsImage *mem, #ifdef DEBUG if (count == 0) - g_warning("global_balance %s", _("empty overlap!")); + g_warning("global_balance empty overlap"); #endif /*DEBUG*/ return t[4]; @@ -1495,18 +1495,12 @@ vips__build_mosaic(SymbolTable *st, VipsImage *out, transform_fn tfn, void *a) static int vips__matrixtranspose(VipsImage *in, VipsImage **out) { - int yc, xc; - - /* Allocate output matrix. - */ if (!(*out = vips_image_new_matrix(in->Ysize, in->Xsize))) return -1; - /* Transpose. - */ - for (yc = 0; yc < (*out)->Ysize; ++yc) - for (xc = 0; xc < (*out)->Xsize; ++xc) - *VIPS_MATRIX(*out, xc, yc) = *VIPS_MATRIX(in, yc, xc); + for (int y = 0; y < (*out)->Ysize; y++) + for (int x = 0; x < (*out)->Xsize; x++) + *VIPS_MATRIX(*out, x, y) = *VIPS_MATRIX(in, y, x); return 0; } @@ -1614,7 +1608,7 @@ find_factors(SymbolTable *st, double gamma) #ifdef DEBUG /* Diagnostics! */ - printf("debugging output for vips_global_balance():\n"); + printf("debugging output for vips_globalbalance():\n"); for (i = 0; i < st->nim; i++) printf("balance factor %d = %g\n", i, st->fac[i]); total = 0.0; @@ -1767,7 +1761,7 @@ analyse_mosaic(SymbolTable *st, VipsImage *in) return 0; } -/* Scale im by fac --- if it's uchar/ushort, use a lut. If we can use a lut, +/* Scale im by fac -- if it's uchar/ushort, use a lut. If we can use a lut, * transform in linear space. If we can't, don't bother for efficiency. */ static VipsImage * @@ -1957,14 +1951,9 @@ vips_globalbalance_init(VipsGlobalbalance *globalbalance) * vips_globalbalance: (method) * @in: mosaic to rebuild * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @gamma: gamma of source images - * * @int_output: %TRUE for integer image output - * - * vips_globalbalance() can be used to remove contrast differences in + * [method@Image.globalbalance] can be used to remove contrast differences in * an assembled mosaic. * * It reads the History field attached to @in and builds a list of the source @@ -1979,16 +1968,21 @@ vips_globalbalance_init(VipsGlobalbalance *globalbalance) * 1.0 will stop this. * * Each of the source images is transformed with the appropriate correction - * factor, then the mosaic is reassembled. @out is #VIPS_FORMAT_FLOAT, but - * if @int_output is set, the output image is the same format as the input - * images. + * factor, then the mosaic is reassembled. @out is + * [enum@Vips.BandFormat.FLOAT], but if @int_output is set, the output image + * is the same format as the input images. * * There are some conditions that must be met before this operation can work: * the source images must all be present under the filenames recorded in the * history on @in, and the mosaic must have been built using only operations in * this package. * - * See also: vips_remosaic(). + * ::: tip "Optional arguments" + * * @gamma: `gdouble`, gamma of source images + * * @int_output: `gboolean`, `TRUE` for integer image output + * + * ::: seealso + * [method@Image.mosaic]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/mosaicing/im_avgdxdy.c b/libvips/mosaicing/im_avgdxdy.c index 015e1ffd68..e0214c9e4f 100644 --- a/libvips/mosaicing/im_avgdxdy.c +++ b/libvips/mosaicing/im_avgdxdy.c @@ -75,8 +75,8 @@ vips__avgdxdy(TiePoints *points, int *dx, int *dy) sumdy += points->y_secondary[i] - points->y_reference[i]; } - *dx = VIPS_RINT((double) sumdx / (double) points->nopoints); - *dy = VIPS_RINT((double) sumdy / (double) points->nopoints); + *dx = rint((double) sumdx / (double) points->nopoints); + *dy = rint((double) sumdy / (double) points->nopoints); return 0; } diff --git a/libvips/mosaicing/lrmerge.c b/libvips/mosaicing/lrmerge.c index 27d9e8f625..eb1b9d9d52 100644 --- a/libvips/mosaicing/lrmerge.c +++ b/libvips/mosaicing/lrmerge.c @@ -130,7 +130,6 @@ */ #include -#include #include #include @@ -332,7 +331,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) * threads. In fact it's harmless if we do get two writers, but we may * avoid duplicating work. */ - g_mutex_lock(ovlap->fl_lock); + g_mutex_lock(&ovlap->fl_lock); /* Do we already have first/last for this area? Bail out if we do. */ @@ -349,7 +348,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) if (!missing) { /* No work to do! */ - g_mutex_unlock(ovlap->fl_lock); + g_mutex_unlock(&ovlap->fl_lock); return 0; } @@ -383,7 +382,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) */ if (vips_region_prepare(rir, &rr) || vips_region_prepare(sir, &sr)) { - g_mutex_unlock(ovlap->fl_lock); + g_mutex_unlock(&ovlap->fl_lock); return -1; } @@ -404,7 +403,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) sr.left, ys, sr.width) || find_last(rir, last, rr.left, yr, rr.width)) { - g_mutex_unlock(ovlap->fl_lock); + g_mutex_unlock(&ovlap->fl_lock); return -1; } @@ -425,7 +424,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) } } - g_mutex_unlock(ovlap->fl_lock); + g_mutex_unlock(&ovlap->fl_lock); return 0; } @@ -737,9 +736,9 @@ lr_blend_labpack(VipsRegion *out_region, MergeInfo *inf, Overlapping *ovlap, } static void -lock_free(VipsImage *image, GMutex *lock) +ovlap_free(VipsImage *image, Overlapping *ovlap) { - VIPS_FREEF(vips_g_mutex_free, lock); + g_mutex_clear(&ovlap->fl_lock); } /* Build basic per-call state and do some geometry calculations. Shared with @@ -853,10 +852,10 @@ vips__build_mergestate(const char *domain, for (x = 0; x < ovlap->flsize; x++) ovlap->first[x] = -1; - ovlap->fl_lock = vips_g_mutex_new(); + g_mutex_init(&ovlap->fl_lock); g_signal_connect(out, "close", - G_CALLBACK(lock_free), ovlap->fl_lock); + G_CALLBACK(ovlap_free), ovlap); return ovlap; } diff --git a/libvips/mosaicing/match.c b/libvips/mosaicing/match.c index e8e2c94daf..166bbb5da4 100644 --- a/libvips/mosaicing/match.c +++ b/libvips/mosaicing/match.c @@ -122,7 +122,7 @@ vips_match_build(VipsObject *object) return -1; if (!match->interpolate) - match->interpolate = vips_interpolate_new("bilinear"); + match->interpolate = vips_interpolate_new("bilinear"); // FIXME: Invalidates operation cache if (match->search) { int xs, ys; @@ -133,8 +133,8 @@ vips_match_build(VipsObject *object) match->hwindow, match->harea, &cor, &xs, &ys)) return -1; - match->xs1 = xs; - match->ys1 = ys; + match->xs1 = xs; // FIXME: Invalidates operation cache + match->ys1 = ys; // FIXME: Invalidates operation cache if (vips__correl(match->ref, match->sec, match->xr2, match->yr2, match->xs2, match->ys2, @@ -142,8 +142,8 @@ vips_match_build(VipsObject *object) &cor, &xs, &ys)) return -1; - match->xs2 = xs; - match->ys2 = ys; + match->xs2 = xs; // FIXME: Invalidates operation cache + match->ys2 = ys; // FIXME: Invalidates operation cache } /* Solve to get scale + rot + disp to obtain match. @@ -271,14 +271,14 @@ vips_match_class_init(VipsMatchClass *class) _("Half window size"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsMatch, hwindow), - 0, 1000000000, 1); + 0, 1000000000, 5); VIPS_ARG_INT(class, "harea", 14, _("harea"), _("Half area size"), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET(VipsMatch, harea), - 0, 1000000000, 1); + 0, 1000000000, 15); VIPS_ARG_BOOL(class, "search", 15, _("Search"), @@ -303,7 +303,7 @@ vips_match_init(VipsMatch *match) } /** - * vips_match: + * vips_match: (method) * @ref: reference image * @sec: secondary image * @out: (out): output image @@ -315,23 +315,22 @@ vips_match_init(VipsMatch *match) * @yr2: second reference tie-point * @xs2: second secondary tie-point * @ys2: second secondary tie-point - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @search: search to improve tie-points - * * @hwindow: half window size - * * @harea: half search size - * * @interpolate: interpolate pixels with this + * @...: `NULL`-terminated list of optional named arguments * * Scale, rotate and translate @sec so that the tie-points line up. * - * If @search is %TRUE, before performing the transformation, the tie-points + * If @search is `TRUE`, before performing the transformation, the tie-points * are improved by searching an area of @sec of size @harea for a * match of size @hwindow to @ref. * * This function will only work well for small rotates and scales. * + * ::: tip "Optional arguments" + * * @search: `gboolean`, search to improve tie-points + * * @hwindow: `gint`, half window size + * * @harea: `gint`, half search size + * * @interpolate: [class@Interpolate], interpolate pixels with this + * * Returns: 0 on success, -1 on error */ int diff --git a/libvips/mosaicing/matrixinvert.c b/libvips/mosaicing/matrixinvert.c index 22bbb1cc4a..7de4dd2e11 100644 --- a/libvips/mosaicing/matrixinvert.c +++ b/libvips/mosaicing/matrixinvert.c @@ -91,18 +91,18 @@ vips_matrixinvert_dispose(GObject *gobject) * lu_decomp: * @mat: matrix to decompose * - * This function takes any square NxN #VipsImage. - * It returns a #VipsImage which is (N+1)xN. + * This function takes any square NxN [class@Image]. + * It returns a [class@Image] which is (N+1)xN. * * It calculates the PLU decomposition, storing the upper and diagonal parts * of U, together with the lower parts of L, as an NxN matrix in the first * N rows of the new matrix. The diagonal parts of L are all set to unity * and are not stored. * - * The final row of the new #VipsImage has only integer entries, which + * The final row of the new [class@Image] has only integer entries, which * represent the row-wise permutations made by the permutation matrix P. * - * The scale and offset members of the input #VipsImage are ignored. + * The scale and offset members of the input [class@Image] are ignored. * * See: * @@ -129,7 +129,7 @@ lu_decomp(VipsImage *mat) /* copy all coefficients and then perform decomposition in-place */ memcpy(VIPS_MATRIX(lu, 0, 0), VIPS_MATRIX(mat, 0, 0), - mat->Xsize * mat->Xsize * sizeof(double)); + (size_t) mat->Xsize * mat->Xsize * sizeof(double)); for (i = 0; i < mat->Xsize; ++i) { row_scale[i] = 0.0; @@ -220,7 +220,7 @@ lu_decomp(VipsImage *mat) * @vec: name for output matrix * * Solve the system of linear equations Ax=b, where matrix A has already - * been decomposed into LU form in VipsImage *lu. Input vector b is in + * been decomposed into LU form in @lu. Input vector b is in * vec and is overwritten with vector x. * * See: @@ -228,7 +228,8 @@ lu_decomp(VipsImage *mat) * PRESS, W. et al, 1992. Numerical Recipes in C; The Art of Scientific * Computing, 2nd ed. Cambridge: Cambridge University Press, pp. 43-50. * - * See also: vips__matrixtranspose(), vips__matrixmultiply(). + * ::: seealso + * [method@Image.matrixmultiply]. * * Returns: 0 on success, -1 on error */ @@ -436,7 +437,7 @@ vips_matrixinvert_class_init(VipsMatrixinvertClass *class) gobject_class->get_property = vips_object_get_property; vobject_class->nickname = "matrixinvert"; - vobject_class->description = _("invert an matrix"); + vobject_class->description = _("invert a matrix"); vobject_class->build = vips_matrixinvert_build; VIPS_ARG_IMAGE(class, "in", 0, @@ -461,12 +462,13 @@ vips_matrixinvert_init(VipsMatrixinvert *matrix) * vips_matrixinvert: (method) * @m: matrix to invert * @out: (out): output matrix - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * * This operation calculates the inverse of the matrix represented in @m. * The scale and offset members of the input matrix are ignored. * - * See also: vips_matrixload(). + * ::: seealso + * [ctor@Image.matrixload], [method@Image.matrixmultiply]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/mosaicing/matrixmultiply.c b/libvips/mosaicing/matrixmultiply.c new file mode 100644 index 0000000000..13b2ed1bd4 --- /dev/null +++ b/libvips/mosaicing/matrixmultiply.c @@ -0,0 +1,197 @@ +/* Multiply two matrices. + * + * Copyright: 1990, K. Martinez and J. Cupitt + * + * 23/10/10 + * - gtk-doc + * 31/1/25 + * - wrapped as a class + */ + +/* + + 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 + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include + +#include + +/* Our state. + */ +typedef struct _VipsMatrixmultiply { + VipsOperation parent_instance; + + VipsImage *left; + VipsImage *right; + VipsImage *out; + + VipsImage *mat1; + VipsImage *mat2; + +} VipsMatrixmultiply; + +typedef VipsOperationClass VipsMatrixmultiplyClass; + +G_DEFINE_TYPE(VipsMatrixmultiply, vips_matrixmultiply, VIPS_TYPE_OPERATION); + +static void +vips_matrixmultiply_dispose(GObject *gobject) +{ + VipsMatrixmultiply *matrix = (VipsMatrixmultiply *) gobject; + + VIPS_UNREF(matrix->mat1); + VIPS_UNREF(matrix->mat2); + + G_OBJECT_CLASS(vips_matrixmultiply_parent_class)->dispose(gobject); +} + +static int +vips_matrixmultiply_build(VipsObject *object) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object); + VipsMatrixmultiply *matrix = (VipsMatrixmultiply *) object; + + if (VIPS_OBJECT_CLASS(vips_matrixmultiply_parent_class)->build(object)) + return -1; + + if (vips_check_matrix(class->nickname, matrix->left, &matrix->mat1) || + vips_check_matrix(class->nickname, matrix->right, &matrix->mat2)) + return -1; + + if (matrix->mat1->Xsize != matrix->mat2->Ysize) { + vips_error(class->nickname, "%s", _("bad sizes")); + return -1; + } + + g_object_set(matrix, + "out", vips_image_new_matrix(matrix->mat2->Xsize, matrix->mat1->Ysize), + NULL); + + /* Multiply. + */ + double *out; + double *s1; + + s1 = VIPS_MATRIX(matrix->mat1, 0, 0); + out = VIPS_MATRIX(matrix->out, 0, 0); + for (int yc = 0; yc < matrix->mat1->Ysize; yc++) { + double *s2 = VIPS_MATRIX(matrix->mat2, 0, 0); + + for (int col = 0; col < matrix->mat2->Xsize; col++) { + /* Get ready to sweep a row. + */ + double *a = s1; + double *b = s2; + + double sum; + + sum = 0.0; + for (int xc = 0; xc < matrix->mat1->Xsize; xc++) { + sum += *a++ * *b; + b += matrix->mat2->Xsize; + } + + *out++ = sum; + s2 += 1; + } + + s1 += matrix->mat1->Xsize; + } + + return 0; +} + +static void +vips_matrixmultiply_class_init(VipsMatrixmultiplyClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(class); + + gobject_class->dispose = vips_matrixmultiply_dispose; + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "matrixmultiply"; + vobject_class->description = _("multiply two matrices"); + vobject_class->build = vips_matrixmultiply_build; + + VIPS_ARG_IMAGE(class, "left", 1, + _("Left"), + _("First matrix to multiply"), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET(VipsMatrixmultiply, left)); + + VIPS_ARG_IMAGE(class, "right", 2, + _("Right"), + _("Second matrix to multiply"), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET(VipsMatrixmultiply, right)); + + VIPS_ARG_IMAGE(class, "out", 3, + _("Output"), + _("Output matrix"), + VIPS_ARGUMENT_REQUIRED_OUTPUT, + G_STRUCT_OFFSET(VipsMatrixmultiply, out)); +} + +static void +vips_matrixmultiply_init(VipsMatrixmultiply *matrix) +{ +} + +/** + * vips_matrixmultiply: (method) + * @left: input matrix + * @right: input matrix + * @out: (out): output matrix + * @...: `NULL`-terminated list of optional named arguments + * + * Multiplies two matrix images. + * + * The scale and offset members of @left and @right are ignored. + * + * ::: seealso + * [method@Image.matrixinvert]. + * + * Returns: 0 on success, -1 on error + */ +int +vips_matrixmultiply(VipsImage *left, VipsImage *right, VipsImage **out, ...) +{ + va_list ap; + int result; + + va_start(ap, out); + result = vips_call_split("matrixmultiply", ap, left, right, out); + va_end(ap); + + return result; +} diff --git a/libvips/mosaicing/merge.c b/libvips/mosaicing/merge.c index e6d151cd46..29fa0579ed 100644 --- a/libvips/mosaicing/merge.c +++ b/libvips/mosaicing/merge.c @@ -172,18 +172,14 @@ vips_merge_init(VipsMerge *merge) } /** - * vips_merge: + * vips_merge: (method) * @ref: reference image * @sec: secondary image * @out: (out): output image * @direction: horizontal or vertical merge * @dx: displacement of ref from sec * @dy: displacement of ref from sec - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @mblend: %gint, maximum blend size + * @...: `NULL`-terminated list of optional named arguments * * This operation joins two images left-right (with @ref on the left) or * up-down (with @ref above) with a smooth seam. @@ -195,7 +191,7 @@ vips_merge_init(VipsMerge *merge) * * The two input images are cast up to the smallest common type (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). * * @dx and @dy give the displacement of @sec relative to @ref, in other words, * the vector to get from the origin of @sec to the origin of @ref, in other @@ -209,7 +205,11 @@ vips_merge_init(VipsMerge *merge) * is, zero pixels in the overlap area do not contribute to the merge. * This makes it possible to join non-rectangular images. * - * See also: vips_mosaic(), vips_insert(). + * ::: tip "Optional arguments" + * * @mblend: `gint`, maximum blend size + * + * ::: seealso + * [method@Image.mosaic], [method@Image.insert]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/mosaicing/meson.build b/libvips/mosaicing/meson.build index 224866465a..b82bb49e32 100644 --- a/libvips/mosaicing/meson.build +++ b/libvips/mosaicing/meson.build @@ -6,6 +6,7 @@ mosaicing_sources = files( 'mosaic1.c', 'chkpair.c', 'matrixinvert.c', + 'matrixmultiply.c', 'global_balance.c', 'lrmerge.c', 'tbmerge.c', diff --git a/libvips/mosaicing/mosaic.c b/libvips/mosaicing/mosaic.c index 6101046f85..d4e4947ad1 100644 --- a/libvips/mosaicing/mosaic.c +++ b/libvips/mosaicing/mosaic.c @@ -309,7 +309,7 @@ vips_mosaic_init(VipsMosaic *mosaic) } /** - * vips_mosaic: + * vips_mosaic: (method) * @ref: reference image * @sec: secondary image * @out: (out): output image @@ -318,20 +318,7 @@ vips_mosaic_init(VipsMosaic *mosaic) * @yref: position in reference image * @xsec: position in secondary image * @ysec: position in secondary image - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @bandno: %gint, band to search for features - * * @hwindow: %gint, half window size - * * @harea: %gint, half search size - * * @mblend: %gint, maximum blend size - * * @dx0: %gint, output, detected displacement - * * @dy0: %gint, output, detected displacement - * * @scale1: %gdouble, output, detected first order scale - * * @angle1: %gdouble, output, detected first order rotation - * * @dx1: %gdouble, output, detected first order displacement - * * @dy1: %gdouble, output, detected first order displacement + * @...: `NULL`-terminated list of optional named arguments * * This operation joins two images left-right (with @ref on the left) or * top-bottom (with @ref above) given an approximate overlap. @@ -346,13 +333,26 @@ vips_mosaic_init(VipsMosaic *mosaic) * fit are discarded, and the model refitted until either too few points * remain or the model reaches good agreement. * - * The detected displacement is used with vips_merge() to join the two images - * together. + * The detected displacement is used with [method@Image.merge] to join the + * two images together. * * You can read out the detected transform with @dx0, @dy0, @scale1, @angle1, * @dx1, @dy1. * - * See also: vips_merge(), vips_insert(). + * ::: tip "Optional arguments" + * * @bandno: `gint`, band to search for features + * * @hwindow: `gint`, half window size + * * @harea: `gint`, half search size + * * @mblend: `gint`, maximum blend size + * * @dx0: `gint`, output, detected displacement + * * @dy0: `gint`, output, detected displacement + * * @scale1: `gdouble`, output, detected first order scale + * * @angle1: `gdouble`, output, detected first order rotation + * * @dx1: `gdouble`, output, detected first order displacement + * * @dy1: `gdouble`, output, detected first order displacement + * + * ::: seealso + * [method@Image.merge], [method@Image.insert]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/mosaicing/mosaic1.c b/libvips/mosaicing/mosaic1.c index efe6fb8b7c..d83d5be9c7 100644 --- a/libvips/mosaicing/mosaic1.c +++ b/libvips/mosaicing/mosaic1.c @@ -454,7 +454,7 @@ vips_mosaic1_build(VipsObject *object) return -1; if (!mosaic1->interpolate) - mosaic1->interpolate = vips_interpolate_new("bilinear"); + mosaic1->interpolate = vips_interpolate_new("bilinear"); // FIXME: Invalidates operation cache jfn = mosaic1->direction == VIPS_DIRECTION_HORIZONTAL ? vips__lrmerge1 @@ -626,7 +626,7 @@ vips_mosaic1_init(VipsMosaic1 *mosaic1) } /** - * vips_mosaic1: + * vips_mosaic1: (method) * @ref: reference image * @sec: secondary image * @out: output image @@ -639,22 +639,14 @@ vips_mosaic1_init(VipsMosaic1 *mosaic1) * @yr2: second reference tie-point * @xs2: second secondary tie-point * @ys2: second secondary tie-point - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @search: search to improve tie-points - * * @hwindow: half window size - * * @harea: half search size - * * @interpolate: interpolate pixels with this - * * @mblend: maximum blend size + * @...: `NULL`-terminated list of optional named arguments * * This operation joins two images top-bottom (with @sec on the right) * or left-right (with @sec at the bottom) * given an approximate pair of tie-points. @sec is scaled and rotated as * necessary before the join. * - * If @search is %TRUE, before performing the transformation, the tie-points + * If @search is `TRUE`, before performing the transformation, the tie-points * are improved by searching an area of @sec of size @harea for a * object of size @hwindow in @ref. * @@ -673,9 +665,17 @@ vips_mosaic1_init(VipsMosaic1 *mosaic1) * * The two input images are cast up to the smallest common type (see table * Smallest common format in - * arithmetic). + * [arithmetic](libvips-arithmetic.html)). + * + * ::: tip "Optional arguments" + * * @search: `gboolean`, search to improve tie-points + * * @hwindow: `gint`, half window size + * * @harea: `gint`, half search size + * * @interpolate: [class@Interpolate], interpolate pixels with this + * * @mblend: `gint`, maximum blend size * - * See also: vips_merge(), vips_insert(), vips_globalbalance(). + * ::: seealso + * [method@Image.merge], [method@Image.insert], [method@Image.globalbalance]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/mosaicing/mosaicing.c b/libvips/mosaicing/mosaicing.c index cc738b4208..f9cc8e682a 100644 --- a/libvips/mosaicing/mosaicing.c +++ b/libvips/mosaicing/mosaicing.c @@ -45,46 +45,6 @@ #include #include -/** - * SECTION: mosaicing - * @short_description: build image mosaics - * @stability: Stable - * @include: vips/vips.h - * - * These functions are useful for joining many small images together to make - * one large image. They can cope with unstable contrast and arbitrary sub-image - * layout, but will not do any geometric correction. Geometric errors should - * be removed before using these functions. - * - * The mosaicing functions can be grouped into layers: - * - * The lowest level operation is vips_merge() which - * joins two images together - * left-right or up-down with a smooth seam. - * - * Next, vips_mosaic() uses - * search functions plus the two low-level merge operations to join two images - * given just an approximate overlap as a start point. - * - * vips_mosaic1() is a first-order - * analogue of the basic mosaic functions: it takes two approximate - * tie-points and uses - * them to rotate and scale the right-hand or bottom image before starting to - * join. - * - * Finally, vips_globalbalance() can be used to remove contrast differences in - * a mosaic - * which has been assembled with these functions. It takes the mosaic apart, - * measures image contrast differences along the seams, finds a set of - * correction factors which will minimise these differences, and reassembles - * the mosaic. - * vips_remosaic() uses the - * same - * techniques, but will reassemble the image from a different set of source - * images. - * - */ - /* Called from iofuncs to init all operations in this dir. Use a plugin system * instead? */ @@ -97,11 +57,15 @@ vips_mosaicing_operation_init(void) extern GType vips_match_get_type(void); extern GType vips_globalbalance_get_type(void); extern GType vips_matrixinvert_get_type(void); + extern GType vips_matrixmultiply_get_type(void); + extern GType vips_remosaic_get_type(void); vips_merge_get_type(); vips_mosaic_get_type(); vips_mosaic1_get_type(); vips_matrixinvert_get_type(); + vips_matrixmultiply_get_type(); vips_match_get_type(); vips_globalbalance_get_type(); + vips_remosaic_get_type(); } diff --git a/libvips/mosaicing/pmosaicing.h b/libvips/mosaicing/pmosaicing.h index 5f6a7ce521..5e4c1f0e3f 100644 --- a/libvips/mosaicing/pmosaicing.h +++ b/libvips/mosaicing/pmosaicing.h @@ -82,7 +82,7 @@ typedef struct _Overlapping { /* Overlap start/end cache */ - GMutex *fl_lock; /* Need to lock on build */ + GMutex fl_lock; /* Need to lock on build */ int *first, *last; /* Blend function. diff --git a/libvips/mosaicing/remosaic.c b/libvips/mosaicing/remosaic.c index 7e141bc8d5..d6410ed885 100644 --- a/libvips/mosaicing/remosaic.c +++ b/libvips/mosaicing/remosaic.c @@ -198,20 +198,21 @@ vips_remosaic_init(VipsRemosaic *remosaic) * @out: (out): output image * @old_str: gamma of source images * @new_str: gamma of source images - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * vips_remosaic() works rather as vips_globalbalance(). It takes apart the - * mosaiced image @in and rebuilds it, substituting images. + * [method@Image.remosaic] works rather as [method@Image.globalbalance]. It + * takes apart the mosaiced image @in and rebuilds it, substituting images. * - * Unlike vips_globalbalance(), images are substituted based on their file‐ - * names. The rightmost occurrence of the string @old_str is swapped + * Unlike [method@Image.globalbalance], images are substituted based on their + * filenames. The rightmost occurrence of the string @old_str is swapped * for @new_str, that file is opened, and that image substituted for * the old image. * * It's convenient for multispectral images. You can mosaic one band, then * use that mosaic as a template for mosaicing the others automatically. * - * See also: vips_globalbalance(). + * ::: seealso + * [method@Image.globalbalance]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/mosaicing/tbmerge.c b/libvips/mosaicing/tbmerge.c index a827c18ad0..9477392cc2 100644 --- a/libvips/mosaicing/tbmerge.c +++ b/libvips/mosaicing/tbmerge.c @@ -112,7 +112,6 @@ #include #include -#include #include #include @@ -283,7 +282,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) * threads. In fact it's harmless if we do get two writers, but we may * avoid duplicating work. */ - g_mutex_lock(ovlap->fl_lock); + g_mutex_lock(&ovlap->fl_lock); /* Do we already have first/last for this area? Bail out if we do. */ @@ -300,7 +299,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) if (!missing) { /* No work to do! */ - g_mutex_unlock(ovlap->fl_lock); + g_mutex_unlock(&ovlap->fl_lock); return 0; } @@ -327,7 +326,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) */ if (vips_region_prepare(rir, &rr) || vips_region_prepare(sir, &sr)) { - g_mutex_unlock(ovlap->fl_lock); + g_mutex_unlock(&ovlap->fl_lock); return -1; } @@ -347,7 +346,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) x + sr.left, sr.top, sr.height) || find_bot(rir, last, x + rr.left, rr.top, rr.height)) { - g_mutex_unlock(ovlap->fl_lock); + g_mutex_unlock(&ovlap->fl_lock); return -1; } @@ -368,7 +367,7 @@ make_firstlast(MergeInfo *inf, Overlapping *ovlap, VipsRect *oreg) } } - g_mutex_unlock(ovlap->fl_lock); + g_mutex_unlock(&ovlap->fl_lock); return 0; } diff --git a/libvips/resample/affine.c b/libvips/resample/affine.c index 74881ddabe..5c79e3ae6f 100644 --- a/libvips/resample/affine.c +++ b/libvips/resample/affine.c @@ -156,6 +156,10 @@ typedef struct _VipsAffine { VipsTransformation trn; + /* Interpolate parameter, prepared and ready for use. + */ + VipsInterpolate *affine_interpolate; + /* How to generate extra edge pixels. */ VipsExtend extend; @@ -178,6 +182,16 @@ typedef VipsResampleClass VipsAffineClass; G_DEFINE_TYPE(VipsAffine, vips_affine, VIPS_TYPE_RESAMPLE); +static void +vips_affine_dispose(GObject *gobject) +{ + VipsAffine *affine = (VipsAffine *) gobject; + + VIPS_UNREF(affine->affine_interpolate); + + G_OBJECT_CLASS(vips_affine_parent_class)->dispose(gobject); +} + /* We have five (!!) coordinate systems. Working forward through them, these * are: * @@ -216,12 +230,11 @@ vips_affine_gen(VipsRegion *out_region, VipsRegion *ir = (VipsRegion *) seq; const VipsAffine *affine = (VipsAffine *) b; const VipsImage *in = (VipsImage *) a; - const int window_size = - vips_interpolate_get_window_size(affine->interpolate); - const int window_offset = - vips_interpolate_get_window_offset(affine->interpolate); - const VipsInterpolateMethod interpolate = - vips_interpolate_get_method(affine->interpolate); + VipsInterpolate *interpolate = affine->affine_interpolate; + const int window_size = vips_interpolate_get_window_size(interpolate); + const int window_offset = vips_interpolate_get_window_offset(interpolate); + const VipsInterpolateMethod interpolate_method = + vips_interpolate_get_method(interpolate); /* Area we generate in the output image. */ @@ -353,8 +366,8 @@ vips_affine_gen(VipsRegion *out_region, for (x = le; x < ri; x++) { int fx, fy; - fx = VIPS_FLOOR(ix); - fy = VIPS_FLOOR(iy); + fx = floor(ix); + fy = floor(iy); /* Clip against iarea. */ @@ -374,7 +387,7 @@ vips_affine_gen(VipsRegion *out_region, (int) iy - window_offset + window_size - 1)); - interpolate(affine->interpolate, q, ir, ix, iy); + interpolate_method(interpolate, q, ir, ix, iy); } else { /* Out of range: paint the background. @@ -420,27 +433,28 @@ vips_affine_build(VipsObject *object) if (vips_check_coding_known(class->nickname, resample->in)) return -1; - if (vips_check_vector_length(class->nickname, - affine->matrix->n, 4)) + if (vips_check_vector_length(class->nickname, affine->matrix->n, 4)) return -1; if (vips_object_argument_isset(object, "oarea") && - vips_check_vector_length(class->nickname, - affine->oarea->n, 4)) + vips_check_vector_length(class->nickname, affine->oarea->n, 4)) return -1; - /* Can be set explicitly to NULL to mean default setting. + /* "interpolate" be set explicitly to NULL to mean default setting. */ - if (!affine->interpolate) - affine->interpolate = vips_interpolate_new("bilinear"); + affine->affine_interpolate = affine->interpolate; + if (affine->affine_interpolate) + g_object_ref(affine->affine_interpolate); + else + affine->affine_interpolate = vips_interpolate_new("bilinear"); in = resample->in; /* Set up transform. */ - window_size = vips_interpolate_get_window_size(affine->interpolate); + window_size = vips_interpolate_get_window_size(affine->affine_interpolate); window_offset = - vips_interpolate_get_window_offset(affine->interpolate); + vips_interpolate_get_window_offset(affine->affine_interpolate); affine->trn.iarea.left = 0; affine->trn.iarea.top = 0; @@ -618,6 +632,7 @@ vips_affine_class_init(VipsAffineClass *class) VIPS_DEBUG_MSG("vips_affine_class_init\n"); + gobject_class->dispose = vips_affine_dispose; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -710,33 +725,24 @@ vips_affine_init(VipsAffine *affine) * @b: transformation matrix coefficient * @c: transformation matrix coefficient * @d: transformation matrix coefficient - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @interpolate: #VipsInterpolate, interpolate pixels with this - * * @oarea: #VipsArrayInt, output rectangle - * * @idx: %gdouble, input horizontal offset - * * @idy: %gdouble, input vertical offset - * * @odx: %gdouble, output horizontal offset - * * @ody: %gdouble, output vertical offset - * * @extend: #VipsExtend how to generate new pixels - * * @background: #VipsArrayDouble colour for new pixels - * * @premultiplied: %gboolean, images are already premultiplied + * @...: `NULL`-terminated list of optional named arguments * * This operator performs an affine transform on an image using @interpolate. * * The transform is: * - * |[ - * X = @a * (x + @idx) + @b * (y + @idy) + @odx - * Y = @c * (x + @idx) + @d * (y + @idy) + @doy + * ``` + * X = @a * (x + @idx) + @b * (y + @idy) + @odx + * Y = @c * (x + @idx) + @d * (y + @idy) + @doy + * ``` + * + * where: * - * where: - * x and y are the coordinates in input image. - * X and Y are the coordinates in output image. - * (0,0) is the upper left corner. - * ]| + * ``` + * x and y are the coordinates in input image. + * X and Y are the coordinates in output image. + * (0,0) is the upper left corner. + * ``` * * The section of the output space defined by @oarea is written to * @out. @oarea is a four-element int array of left, top, width, height. @@ -744,21 +750,33 @@ vips_affine_init(VipsAffine *affine) * transformed input image. * * By default, new pixels are filled with @background. This defaults to - * zero (black). You can set other extend types with @extend. #VIPS_EXTEND_COPY - * is better for image upsizing. + * zero (black). You can set other extend types with @extend. + * [enum@Vips.Extend.COPY] is better for image upsizing. * * @interpolate defaults to bilinear. * * @idx, @idy, @odx, @ody default to zero. * - * Image are normally treated as unpremultiplied, so this operation can be used - * directly on PNG images. If your images have been through vips_premultiply(), - * set @premultiplied. + * Image are normally treated as unpremultiplied, so this operation can be + * used directly on PNG images. If your images have been through + * [method@Image.premultiply], set @premultiplied. * * This operation does not change xres or yres. The image resolution needs to * be updated by the application. * - * See also: vips_shrink(), vips_resize(), #VipsInterpolate. + * ::: tip "Optional arguments" + * * @interpolate: [class@Interpolate], interpolate pixels with this + * * @oarea: [struct@ArrayInt], output rectangle + * * @idx: `gdouble`, input horizontal offset + * * @idy: `gdouble`, input vertical offset + * * @odx: `gdouble`, output horizontal offset + * * @ody: `gdouble`, output vertical offset + * * @extend: [enum@Extend], how to generate new pixels + * * @background: [struct@ArrayDouble] colour for new pixels + * * @premultiplied: `gboolean`, images are already premultiplied + * + * ::: seealso + * [method@Image.shrink], [method@Image.resize], [class@Interpolate]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/interpolate.c b/libvips/resample/interpolate.c index 13e3575e47..51592bfcd4 100644 --- a/libvips/resample/interpolate.c +++ b/libvips/resample/interpolate.c @@ -63,13 +63,15 @@ #include /** - * SECTION: interpolator - * @short_description: various interpolators: nearest, bilinear, and - * some non-linear - * @stability: Stable - * @include: vips/vips.h + * VipsInterpolate: * - * A number of image interpolators. + * An abstract base class for the various interpolation functions. + * + * Use `vips --list classes` to see all the interpolators available. + * + * An interpolator consists of a function to perform the interpolation, plus + * some extra data fields which tells libvips how to call the function and + * what data it needs. */ G_DEFINE_ABSTRACT_TYPE(VipsInterpolate, vips_interpolate, VIPS_TYPE_OBJECT); @@ -83,12 +85,13 @@ G_DEFINE_ABSTRACT_TYPE(VipsInterpolate, vips_interpolate, VIPS_TYPE_OBJECT); * @y: interpolate value at this position * * An interpolation function. It should read source pixels from @in with - * VIPS_REGION_ADDR(), it can look left and up from (x, y) by @window_offset + * [func@REGION_ADDR], it can look left and up from (x, y) by @window_offset * pixels and it can access pixels in a window of size @window_size. * * The interpolated value should be written to the pixel pointed to by @out. * - * See also: #VipsInterpolateClass. + * ::: seealso + * [struct@VipsInterpolateClass]. */ /** @@ -99,32 +102,27 @@ G_DEFINE_ABSTRACT_TYPE(VipsInterpolate, vips_interpolate, VIPS_TYPE_OBJECT); * @get_window_offset: return the window offset for this method * @window_offset: or just set this for a constant window offset * - * The abstract base class for the various VIPS interpolation functions. - * Use "vips --list classes" to see all the interpolators available. - * - * An interpolator consists of a function to perform the interpolation, plus - * some extra data fields which tell vips how to call the function and what - * data it needs. - * * @window_size is the size of the window that the interpolator needs. For * example, a bicubic interpolator needs to see a window of 4x4 pixels to be * able to interpolate a value. * * You can either have a function in @get_window_size which returns the window - * that a specific interpolator needs, or you can leave @get_window_size %NULL + * that a specific interpolator needs, or you can leave @get_window_size `NULL` * and set a constant value in @window_size. * * @window_offset is how much to offset the window up and left of (x, y). For - * example, a bicubic interpolator will want a @window_offset of 1. + * example, a bicubic interpolator will want an @window_offset of 1. * * You can either have a function in @get_window_offset which returns the * offset that a specific interpolator needs, or you can leave - * @get_window_offset %NULL and set a constant value in @window_offset. + * @get_window_offset `NULL` and set a constant value in @window_offset. * - * You also need to set @nickname and @description in #VipsObject. + * You also need to set [property@VipsObject:nickname] and + * [property@VipsObject:description] in [class@Object]. * - * See also: #VipsInterpolateMethod, #VipsObject, - * vips_interpolate_bilinear_static(). + * ::: seealso + * [callback@InterpolateMethod], [class@Object] or + * [func@Interpolate.bilinear_static]. */ #ifdef DEBUG @@ -209,7 +207,7 @@ vips_interpolate_init(VipsInterpolate *interpolate) * @y: interpolate value at this position * * Look up the @interpolate method in the class and call it. Use - * vips_interpolate_get_method() to get a direct pointer to the function and + * [method@Interpolate.get_method] to get a direct pointer to the function and * avoid the lookup overhead. * * You need to set @in and @out up correctly. @@ -230,7 +228,7 @@ vips_interpolate(VipsInterpolate *interpolate, * @interpolate: interpolator to use * * Look up the @interpolate method in the class and return it. Use this - * instead of vips_interpolate() to cache method dispatch. + * instead of [func@interpolate] to cache method dispatch. * * Returns: a pointer to the interpolation function */ @@ -283,14 +281,14 @@ vips_interpolate_get_window_offset(VipsInterpolate *interpolate) /** * VIPS_TRANSFORM_SHIFT: * - * Many of the vips interpolators use fixed-point arithmetic for coordinate + * Many of the libvips interpolators use fixed-point arithmetic for coordinate * calculation. This is how many bits of precision they use. */ /** * VIPS_TRANSFORM_SCALE: * - * #VIPS_TRANSFORM_SHIFT as a multiplicative constant. + * [const@TRANSFORM_SHIFT] as a multiplicative constant. */ /** @@ -303,7 +301,7 @@ vips_interpolate_get_window_offset(VipsInterpolate *interpolate) /** * VIPS_INTERPOLATE_SCALE: * - * #VIPS_INTERPOLATE_SHIFT as a multiplicative constant. + * [const@INTERPOLATE_SHIFT] as a multiplicative constant. */ /* VipsInterpolateNearest class @@ -619,7 +617,7 @@ vips_interpolate_bilinear_static(void) return interpolate; } -/* Called on startup: register the base vips interpolators. +/* Called on startup: register the base libvips interpolators. */ void vips__interpolate_init(void) @@ -643,11 +641,12 @@ vips__interpolate_init(void) * @nickname: nickname for interpolator * * Look up an interpolator from a nickname and make one. You need to free the - * result with g_object_unref() when you're done with it. + * result with [method@GObject.Object.unref] when you're done with it. * - * See also: vips_type_find(). + * ::: seealso + * [func@type_find]. * - * Returns: an interpolator, or %NULL on error. + * Returns: an interpolator, or `NULL` on error. */ VipsInterpolate * vips_interpolate_new(const char *nickname) diff --git a/libvips/resample/mapim.c b/libvips/resample/mapim.c index 8f7ebb8ee0..da879adddf 100644 --- a/libvips/resample/mapim.c +++ b/libvips/resample/mapim.c @@ -285,8 +285,8 @@ vips_mapim_region_minmax(VipsRegion *region, VipsRect *r, VipsRect *bounds) TYPE px = p1[0]; \ TYPE py = p1[1]; \ \ - if (VIPS_ISNAN(px) || \ - VIPS_ISNAN(py) || \ + if (isnan(px) || \ + isnan(py) || \ px < -1 || \ px >= clip_width || \ py < -1 || \ @@ -598,47 +598,48 @@ vips_mapim_init(VipsMapim *mapim) * @in: input image * @out: (out): output image * @index: index image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * This operator resamples @in using @index to look up pixels. * - * * @interpolate: interpolate pixels with this - * * @extend: #VipsExtend how to generate new pixels - * * @background: #VipsArrayDouble colour for new pixels - * * @premultiplied: %gboolean, images are already premultiplied + * @out is the same size as @index, with each pixel being fetched from that + * position in @in. That is: * - * This operator resamples @in using @index to look up pixels. @out is - * the same size as @index, with each pixel being fetched from that position in - * @in. That is: - * - * |[ + * ``` * out[x, y] = in[index[x, y]] - * ]| + * ``` * * If @index has one band, that band must be complex. Otherwise, @index must * have two bands of any format. * * Coordinates in @index are in pixels, with (0, 0) being the top-left corner - * of @in, and with y increasing down the image. Use vips_xyz() to build index - * images. + * of @in, and with y increasing down the image. Use [ctor@Image.xyz] to + * build index images. * * @interpolate defaults to bilinear. * * By default, new pixels are filled with @background. This defaults to - * zero (black). You can set other extend types with @extend. #VIPS_EXTEND_COPY + * zero (black). You can set other extend types with @extend. [enum@Vips.Extend.COPY] * is better for image upsizing. * * Image are normally treated as unpremultiplied, so this operation can be used - * directly on PNG images. If your images have been through vips_premultiply(), - * set @premultiplied. + * directly on PNG images. If your images have been through + * [method@Image.premultiply], set @premultiplied. * * This operation does not change xres or yres. The image resolution needs to * be updated by the application. * - * See vips_maplut() for a 1D equivalent of this operation. + * See [method@Image.maplut] for a 1D equivalent of this operation. + * + * ::: tip "Optional arguments" + * * @interpolate: [class@Interpolate], interpolate pixels with this + * * @extend: [enum@Vips.Extend], how to generate new pixels + * * @background: [struct@ArrayDouble], colour for new pixels + * * @premultiplied: `gboolean`, images are already premultiplied * - * See also: vips_xyz(), vips_affine(), vips_resize(), - * vips_maplut(), #VipsInterpolate. + * ::: seealso + * [ctor@Image.xyz], [method@Image.affine], [method@Image.resize], + * [method@Image.maplut], [class@Interpolate]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/meson.build b/libvips/resample/meson.build index dfeb95605f..22095df620 100644 --- a/libvips/resample/meson.build +++ b/libvips/resample/meson.build @@ -8,7 +8,9 @@ resample_sources = files( 'resize.c', 'shrink.c', 'shrinkh.c', + 'shrinkh_hwy.cpp', 'shrinkv.c', + 'shrinkv_hwy.cpp', 'reduce.c', 'reduceh.cpp', 'reduceh_hwy.cpp', diff --git a/libvips/resample/presample.h b/libvips/resample/presample.h index b2799beaf7..9a5f079b71 100644 --- a/libvips/resample/presample.h +++ b/libvips/resample/presample.h @@ -78,6 +78,13 @@ void vips_reduceh_uchar_hwy(VipsPel *pout, VipsPel *pin, void vips_reducev_uchar_hwy(VipsPel *pout, VipsPel *pin, int n, int ne, int lskip, const short *restrict k); +void vips_shrinkh_uchar_hwy(VipsPel *pout, VipsPel *pin, + int width, int hshrink, int bands); +void vips_shrinkv_add_line_uchar_hwy(VipsPel *pin, + int ne, unsigned int *restrict sum); +void vips_shrinkv_write_line_uchar_hwy(VipsPel *pout, + int ne, int vshrink, unsigned int *restrict sum); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/resample/quadratic.c b/libvips/resample/quadratic.c index e24b37e46a..6ea47193d9 100644 --- a/libvips/resample/quadratic.c +++ b/libvips/resample/quadratic.c @@ -53,38 +53,6 @@ #include "presample.h" -/* The transform we compute: - -x',y' = coordinates of srcim -x,y = coordinates of dstim -a .. l = coefficients - -x = x' + a : order 0 image shift only - + b x' + c y' : order 1 + affine transf. - + d x' y' : order 2 + bilinear transf. - + e x' x' + f y' y' : order 3 + quadratic transf. - -y = y' + g - + h y' + i x' - + j y' x' - + k y' y' + l x' x' - -input matrix: - - a g - -- - b h - c i - -- - d j - -- - e k - f l - -matrix height may be 1, 3, 4, 6 - - */ - typedef struct _VipsQuadratic { VipsResample parent_instance; @@ -141,16 +109,7 @@ vips_quadratic_gen(VipsRegion *out_region, int xhigh = VIPS_RECT_RIGHT(&out_region->valid); int yhigh = VIPS_RECT_BOTTOM(&out_region->valid); - VipsPel *q; - - int xo, yo; /* output coordinates, dstimage */ - int z; - double fxi, fyi; /* input coordinates */ - double dx, dy; /* xo derivative of input coord. */ - double ddx, ddy; /* 2nd xo derivative of input coord. */ - VipsRect image; - image.left = 0; image.top = 0; image.width = in->Xsize; @@ -158,10 +117,15 @@ vips_quadratic_gen(VipsRegion *out_region, if (vips_region_image(ir, &image)) return -1; - for (yo = ylow; yo < yhigh; yo++) { - fxi = 0.0; - fyi = 0.0; - dx = 0.0; + for (int yo = ylow; yo < yhigh; yo++) { + double fxi, fyi; /* input coordinates */ + double dx, dy; /* xo derivative of input coord. */ + double ddx, ddy; /* 2nd xo derivative of input coord. */ + VipsPel *q; + + fxi = xlow + vec[0]; /* order 0 */ + fyi = yo + vec[1]; + dx = 1.0; dy = 0.0; ddx = 0.0; ddy = 0.0; @@ -171,9 +135,9 @@ vips_quadratic_gen(VipsRegion *out_region, fxi += vec[10] * yo * yo + vec[8] * xlow * xlow; fyi += vec[11] * yo * yo + vec[9] * xlow * xlow; dx += vec[8]; - ddx += vec[8] * 2.0; + ddx = vec[8] * 2.0; dy += vec[9]; - ddy += vec[9] * 2.0; + ddy = vec[9] * 2.0; case 2: fxi += vec[6] * xlow * yo; @@ -188,23 +152,17 @@ vips_quadratic_gen(VipsRegion *out_region, dy += vec[3]; case 0: - fxi += vec[0]; - fyi += vec[1]; break; default: g_assert_not_reached(); } - printf("dx = %g, dy = %g\n", dx, dy); - q = VIPS_REGION_ADDR(out_region, xlow, yo); - for (xo = xlow; xo < xhigh; xo++) { - int xi, yi; - - xi = fxi; - yi = fyi; + for (int xo = xlow; xo < xhigh; xo++) { + int xi = fxi; + int yi = fyi; /* Clipping! */ @@ -212,12 +170,11 @@ vips_quadratic_gen(VipsRegion *out_region, yi < 0 || xi >= clip_width || yi >= clip_height) { - for (z = 0; z < ps; z++) + for (int z = 0; z < ps; z++) q[z] = 0; } else - interpolate_fn(quadratic->interpolate, - q, ir, fxi, fyi); + interpolate_fn(quadratic->interpolate, q, ir, fxi, fyi); q += ps; @@ -260,8 +217,7 @@ vips_quadratic_build(VipsObject *object) if (vips_check_uncoded(class->nickname, in) || vips_check_noncomplex(class->nickname, in) || - vips_check_matrix(class->nickname, - quadratic->coeff, &quadratic->mat)) + vips_check_matrix(class->nickname, quadratic->coeff, &quadratic->mat)) return -1; if (quadratic->mat->Xsize != 2) { @@ -292,8 +248,29 @@ vips_quadratic_build(VipsObject *object) return -1; } +#ifdef DEBUG + double *vec = VIPS_MATRIX(quadratic->mat, 0, 0); + printf("vips_quadratic_build:\n"); + printf("\ta = %g, g = %g\n", vec[0], vec[1]); + + if (quadratic->order > 0) { + printf("\t--------\n"); + printf("\tb = %g, h = %g\n", vec[2], vec[3]); + printf("\tc = %g, i = %g\n", vec[4], vec[5]); + } + if (quadratic->order > 1) { + printf("\t--------\n"); + printf("\td = %g, j = %g\n", vec[6], vec[7]); + } + if (quadratic->order > 2) { + printf("\t--------\n"); + printf("\te = %g, k = %g\n", vec[8], vec[9]); + printf("\tf = %g, l = %g\n", vec[10], vec[11]); + } +#endif /*DEBUG*/ + if (!quadratic->interpolate) - quadratic->interpolate = vips_interpolate_new("bilinear"); + quadratic->interpolate = vips_interpolate_new("bilinear"); // FIXME: Invalidates operation cache window_size = vips_interpolate_get_window_size(quadratic->interpolate); window_offset = vips_interpolate_get_window_offset(quadratic->interpolate); @@ -364,15 +341,53 @@ vips_quadratic_init(VipsQuadratic *quadratic) * @in: input image * @out: (out): output image * @coeff: horizontal quadratic - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments + * + * Transform an image with a 0, 1, 2, or 3rd order polynomial. + * + * The transform we compute: + * + * ``` + * x = x' + a : order 0 image shift only + * + b x' + c y' : order 1 + affine transf. + * + d x' y' : order 2 + bilinear transf. + * + e x' x' + f y' y' : order 3 + quadratic transf. + * + * y = y' + g + * + h y' + i x' + * + j y' x' + * + k y' y' + l x' x' + * ``` + * + * where: + * + * ``` + * x', y' = coordinates of srcim + * x, y = coordinates of dstim + * a .. l = coefficients + * ``` + * + * The coefficients are in the input matrix, ordered as: * - * Optional arguments: + * ``` + * a g + * -- + * b h + * c i + * -- + * d j + * -- + * e k + * f l + * ``` * - * * @interpolate: use this interpolator (default bilinear) + * The matrix height may be 1, 3, 4, 6 * - * This operation is unfinished and unusable, sorry. + * ::: tip "Optional arguments" + * * @interpolate: use this interpolator (default bilinear) * - * See also: vips_affine(). + * ::: seealso + * [method@Image.affine]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/reduce.c b/libvips/resample/reduce.c index 94fb8088b6..9d356fd299 100644 --- a/libvips/resample/reduce.c +++ b/libvips/resample/reduce.c @@ -69,73 +69,9 @@ * @VIPS_KERNEL_MKS2013: Convolve with Magic Kernel Sharp 2013. * @VIPS_KERNEL_MKS2021: Convolve with Magic Kernel Sharp 2021. * - * The resampling kernels vips supports. See vips_reduce(), for example. + * The resampling kernels vips supports. See [method@Image.reduce], for example. */ -/* gtk-doc does not see comments in C++ files, so we have these docs here. - */ - -/** - * vips_reducev: (method) - * @in: input image - * @out: (out): output image - * @vshrink: vertical reduce - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @kernel: #VipsKernel to use to interpolate (default: lanczos3) - * * @gap: reducing gap to use (default: 0.0) - * - * Reduce @in vertically by a float factor. The pixels in @out are - * interpolated with a 1D mask generated by @kernel. - * - * Set @gap to speed up reducing by having vips_shrinkv() to shrink - * with a box filter first. The bigger @gap, the closer the result - * to the fair resampling. The smaller @gap, the faster resizing. - * The default value is 0.0 (no optimization). - * - * This is a very low-level operation: see vips_resize() for a more - * convenient way to resize images. - * - * This operation does not change xres or yres. The image resolution needs to - * be updated by the application. - * - * See also: vips_shrink(), vips_resize(), vips_affine(). - * - * Returns: 0 on success, -1 on error - */ - -/** - * vips_reduceh: (method) - * @in: input image - * @out: (out): output image - * @hshrink: horizontal reduce - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @kernel: #VipsKernel to use to interpolate (default: lanczos3) - * * @gap: reducing gap to use (default: 0.0) - * - * Reduce @in horizontally by a float factor. The pixels in @out are - * interpolated with a 1D mask generated by @kernel. - * - * Set @gap to speed up reducing by having vips_shrinkh() to shrink - * with a box filter first. The bigger @gap, the closer the result - * to the fair resampling. The smaller @gap, the faster resizing. - * The default value is 0.0 (no optimization). - * - * This is a very low-level operation: see vips_resize() for a more - * convenient way to resize images. - * - * This operation does not change xres or yres. The image resolution needs to - * be updated by the application. - * - * See also: vips_shrink(), vips_resize(), vips_affine(). - * - * Returns: 0 on success, -1 on error - */ typedef struct _VipsReduce { VipsResample parent_instance; @@ -268,28 +204,29 @@ vips_reduce_init(VipsReduce *reduce) * @out: (out): output image * @hshrink: horizontal shrink * @vshrink: vertical shrink - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Reduce @in by a pair of factors with a pair of 1D kernels. * - * * @kernel: #VipsKernel to use to interpolate (default: lanczos3) - * * @gap: reducing gap to use (default: 0.0) + * This will not work well for shrink factors greater than three. * - * Reduce @in by a pair of factors with a pair of 1D kernels. This - * will not work well for shrink factors greater than three. - * - * Set @gap to speed up reducing by having vips_shrink() to shrink + * Set @gap to speed up reducing by having [method@Image.shrink] to shrink * with a box filter first. The bigger @gap, the closer the result * to the fair resampling. The smaller @gap, the faster resizing. * The default value is 0.0 (no optimization). * - * This is a very low-level operation: see vips_resize() for a more + * This is a very low-level operation: see [method@Image.resize] for a more * convenient way to resize images. * * This operation does not change xres or yres. The image resolution needs to * be updated by the application. * - * See also: vips_shrink(), vips_resize(), vips_affine(). + * ::: tip "Optional arguments" + * * @kernel: [enum@Kernel], kernel to interpolate with (default: lanczos3) + * * @gap: reducing gap to use (default: 0.0) + * + * ::: seealso + * [method@Image.shrink], [method@Image.resize], [method@Image.affine]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/reduceh.cpp b/libvips/resample/reduceh.cpp index 4e369c92e9..d98805247a 100644 --- a/libvips/resample/reduceh.cpp +++ b/libvips/resample/reduceh.cpp @@ -82,6 +82,10 @@ typedef struct _VipsReduceh { */ double hoffset; + /* The hshrink we do after integer reduction. + */ + double residual_hshrink; + /* Precalculated interpolation matrices. short (used for pel * sizes up to int), and double (for all others). We go to * scale + 1 so we can round-to-nearest safely. @@ -202,7 +206,7 @@ static void inline reduceh_notab(VipsReduceh *reduceh, typename LongT::type cx[MAX_POINT]; vips_reduce_make_mask(cx, reduceh->kernel, reduceh->n_point, - reduceh->hshrink, x); + reduceh->residual_hshrink, x); for (int z = 0; z < bands; z++) out[z] = reduce_sum(in + z, bands, cx, n); @@ -230,9 +234,9 @@ vips_reduceh_gen(VipsRegion *out_region, void *seq, r->width, r->height, r->left, r->top); #endif /*DEBUG*/ - s.left = r->left * reduceh->hshrink - reduceh->hoffset; + s.left = r->left * reduceh->residual_hshrink - reduceh->hoffset; s.top = r->top; - s.width = r->width * reduceh->hshrink + reduceh->n_point; + s.width = r->width * reduceh->residual_hshrink + reduceh->n_point; s.height = r->height; if (vips_region_prepare(ir, &s)) return -1; @@ -247,7 +251,7 @@ vips_reduceh_gen(VipsRegion *out_region, void *seq, q = VIPS_REGION_ADDR(out_region, r->left, r->top + y); - X = (r->left + 0.5) * reduceh->hshrink - 0.5 - + X = (r->left + 0.5) * reduceh->residual_hshrink - 0.5 - reduceh->hoffset; /* We want p0 to be the start (ie. x == 0) of the input @@ -319,7 +323,7 @@ vips_reduceh_gen(VipsRegion *out_region, void *seq, break; } - X += reduceh->hshrink; + X += reduceh->residual_hshrink; q += ps; } } @@ -350,9 +354,9 @@ vips_reduceh_uchar_vector_gen(VipsRegion *out_region, void *seq, r->width, r->height, r->left, r->top); #endif /*DEBUG*/ - s.left = r->left * reduceh->hshrink - reduceh->hoffset; + s.left = r->left * reduceh->residual_hshrink - reduceh->hoffset; s.top = r->top; - s.width = r->width * reduceh->hshrink + reduceh->n_point; + s.width = r->width * reduceh->residual_hshrink + reduceh->n_point; s.height = r->height; if (vips_region_prepare(ir, &s)) return -1; @@ -367,14 +371,14 @@ vips_reduceh_uchar_vector_gen(VipsRegion *out_region, void *seq, q = VIPS_REGION_ADDR(out_region, r->left, r->top + y); - X = (r->left + 0.5) * reduceh->hshrink - 0.5 - + X = (r->left + 0.5) * reduceh->residual_hshrink - 0.5 - reduceh->hoffset; p0 = VIPS_REGION_ADDR(ir, ir->valid.left, r->top + y) - ir->valid.left * ps; vips_reduceh_uchar_hwy(q, p0, reduceh->n_point, r->width, - bands, reduceh->matrixs, X, reduceh->hshrink); + bands, reduceh->matrixs, X, reduceh->residual_hshrink); } VIPS_GATE_STOP("vips_reduceh_uchar_vector_gen: work"); @@ -422,6 +426,10 @@ vips_reduceh_build(VipsObject *object) */ extra_pixels = width * reduceh->hshrink - in->Xsize; + /* The hshrink we do after integer reduction. + */ + reduceh->residual_hshrink = reduceh->hshrink; + if (reduceh->gap > 0.0 && reduceh->kernel != VIPS_KERNEL_NEAREST) { if (reduceh->gap < 1.0) { @@ -433,7 +441,7 @@ vips_reduceh_build(VipsObject *object) /* The int part of our reduce. */ int_hshrink = VIPS_MAX(1, - VIPS_FLOOR((double) in->Xsize / width / reduceh->gap)); + floor((double) in->Xsize / width / reduceh->gap)); if (int_hshrink > 1) { g_info("shrinkh by %d", int_hshrink); @@ -443,16 +451,16 @@ vips_reduceh_build(VipsObject *object) return -1; in = t[0]; - reduceh->hshrink /= int_hshrink; + reduceh->residual_hshrink /= int_hshrink; extra_pixels /= int_hshrink; } } - if (reduceh->hshrink == 1.0) + if (reduceh->residual_hshrink == 1.0) return vips_image_write(in, resample->out); reduceh->n_point = - vips_reduce_get_points(reduceh->kernel, reduceh->hshrink); + vips_reduce_get_points(reduceh->kernel, reduceh->residual_hshrink); g_info("reduceh: %d point mask", reduceh->n_point); if (reduceh->n_point > MAX_POINT) { vips_error(object_class->nickname, @@ -479,7 +487,7 @@ vips_reduceh_build(VipsObject *object) return -1; vips_reduce_make_mask(reduceh->matrixf[x], reduceh->kernel, - reduceh->n_point, reduceh->hshrink, + reduceh->n_point, reduceh->residual_hshrink, (float) x / VIPS_TRANSFORM_SCALE); for (int i = 0; i < reduceh->n_point; i++) @@ -502,7 +510,7 @@ vips_reduceh_build(VipsObject *object) /* Add new pixels around the input so we can interpolate at the edges. */ if (vips_embed(in, &t[2], - VIPS_CEIL(reduceh->n_point / 2.0) - 1, 0, + ceil(reduceh->n_point / 2.0) - 1, 0, in->Xsize + reduceh->n_point, in->Ysize, "extend", VIPS_EXTEND_COPY, nullptr)) @@ -621,9 +629,38 @@ vips_reduceh_init(VipsReduceh *reduceh) reduceh->kernel = VIPS_KERNEL_LANCZOS3; } -/* See reduce.c for the doc comment. +/** + * vips_reduceh: (method) + * @in: input image + * @out: (out): output image + * @hshrink: horizontal reduce + * @...: `NULL`-terminated list of optional named arguments + * + * Reduce @in horizontally by a float factor. + * + * The pixels in @out are + * interpolated with a 1D mask generated by @kernel. + * + * Set @gap to speed up reducing by having [method@Image.shrinkh] to shrink + * with a box filter first. The bigger @gap, the closer the result + * to the fair resampling. The smaller @gap, the faster resizing. + * The default value is 0.0 (no optimization). + * + * This is a very low-level operation: see [method@Image.resize] for a more + * convenient way to resize images. + * + * This operation does not change xres or yres. The image resolution needs to + * be updated by the application. + * + * ::: tip "Optional arguments" + * * @kernel: [enum@Kernel], to use to interpolate (default: lanczos3) + * * @gap: `gboolean`, reducing gap to use (default: 0.0) + * + * ::: seealso + * [method@Image.shrink], [method@Image.resize], [method@Image.affine]. + * + * Returns: 0 on success, -1 on error */ - int vips_reduceh(VipsImage *in, VipsImage **out, double hshrink, ...) { diff --git a/libvips/resample/reducev.cpp b/libvips/resample/reducev.cpp index 3cc3f6fbbe..f17d98737f 100644 --- a/libvips/resample/reducev.cpp +++ b/libvips/resample/reducev.cpp @@ -125,6 +125,10 @@ typedef struct _VipsReducev { */ double voffset; + /* The vshrink we do after integer reduction. + */ + double residual_vshrink; + /* Precalculated interpolation matrices. short (used for pel * sizes up to int), and double (for all others). We go to * scale + 1 so we can round-to-nearest safely. @@ -350,9 +354,9 @@ vips_reducev_compile_section(VipsReducev *reducev, Pass *pass, gboolean first) /* Some orcs seem to be unstable with many compilers active at once. */ - g_mutex_lock(vips__global_lock); + g_mutex_lock(&vips__global_lock); result = orc_program_compile(p); - g_mutex_unlock(vips__global_lock); + g_mutex_unlock(&vips__global_lock); if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) return -1; @@ -471,7 +475,7 @@ static void inline reducev_notab(VipsReducev *reducev, typename LongT::type cy[MAX_POINT]; vips_reduce_make_mask(cy, reducev->kernel, reducev->n_point, - reducev->vshrink, y); + reducev->residual_vshrink, y); for (int z = 0; z < ne; z++) out[z] = reduce_sum(in + z, l1, cy, n); @@ -501,15 +505,15 @@ vips_reducev_gen(VipsRegion *out_region, void *vseq, #endif /*DEBUG*/ s.left = r->left; - s.top = r->top * reducev->vshrink - reducev->voffset; + s.top = r->top * reducev->residual_vshrink - reducev->voffset; s.width = r->width; - s.height = r->height * reducev->vshrink + reducev->n_point; + s.height = r->height * reducev->residual_vshrink + reducev->n_point; if (vips_region_prepare(ir, &s)) return -1; VIPS_GATE_START("vips_reducev_gen: work"); - double Y = (r->top + 0.5) * reducev->vshrink - 0.5 - + double Y = (r->top + 0.5) * reducev->residual_vshrink - 0.5 - reducev->voffset; for (int y = 0; y < r->height; y++) { @@ -572,7 +576,7 @@ vips_reducev_gen(VipsRegion *out_region, void *vseq, break; } - Y += reducev->vshrink; + Y += reducev->residual_vshrink; } VIPS_GATE_STOP("vips_reducev_gen: work"); @@ -603,15 +607,15 @@ vips_reducev_uchar_vector_gen(VipsRegion *out_region, void *vseq, #endif /*DEBUG*/ s.left = r->left; - s.top = r->top * reducev->vshrink - reducev->voffset; + s.top = r->top * reducev->residual_vshrink - reducev->voffset; s.width = r->width; - s.height = r->height * reducev->vshrink + reducev->n_point; + s.height = r->height * reducev->residual_vshrink + reducev->n_point; if (vips_region_prepare(ir, &s)) return -1; VIPS_GATE_START("vips_reducev_uchar_vector_gen: work"); - double Y = (r->top + 0.5) * reducev->vshrink - 0.5 - + double Y = (r->top + 0.5) * reducev->residual_vshrink - 0.5 - reducev->voffset; for (int y = 0; y < r->height; y++) { @@ -629,7 +633,7 @@ vips_reducev_uchar_vector_gen(VipsRegion *out_region, void *vseq, q, p, reducev->n_point, ne, lskip, cys); - Y += reducev->vshrink; + Y += reducev->residual_vshrink; } VIPS_GATE_STOP("vips_reducev_uchar_vector_gen: work"); @@ -662,9 +666,9 @@ vips_reducev_vector_gen(VipsRegion *out_region, void *vseq, #endif /*DEBUG_PIXELS*/ s.left = r->left; - s.top = r->top * reducev->vshrink - reducev->voffset; + s.top = r->top * reducev->residual_vshrink - reducev->voffset; s.width = r->width; - s.height = r->height * reducev->vshrink + reducev->n_point; + s.height = r->height * reducev->residual_vshrink + reducev->n_point; if (vips_region_prepare(ir, &s)) return -1; @@ -680,7 +684,7 @@ vips_reducev_vector_gen(VipsRegion *out_region, void *vseq, VIPS_GATE_START("vips_reducev_vector_gen: work"); - double Y = (r->top + 0.5) * reducev->vshrink - 0.5 - + double Y = (r->top + 0.5) * reducev->residual_vshrink - 0.5 - reducev->voffset; for (int y = 0; y < r->height; y++) { @@ -727,7 +731,7 @@ vips_reducev_vector_gen(VipsRegion *out_region, void *vseq, printf("\t%d\n", *q); #endif /*DEBUG_PIXELS*/ - Y += reducev->vshrink; + Y += reducev->residual_vshrink; } VIPS_GATE_STOP("vips_reducev_vector_gen: work"); @@ -758,7 +762,7 @@ vips_reducev_vector_to_fixed_point(double *in, int *out, int n, int scale) fsum = 0.0; for (i = 0; i < n; i++) fsum += in[i]; - target = VIPS_RINT(fsum * scale); + target = rint(fsum * scale); /* As we rint() each scale element, we can get up to 0.5 error. * Therefore, by the end of the mask, we can be off by up to n/2. Our @@ -772,7 +776,7 @@ vips_reducev_vector_to_fixed_point(double *in, int *out, int n, int scale) guess = (high + low) / 2.0; for (i = 0; i < n; i++) - out[i] = VIPS_RINT(in[i] * guess); + out[i] = rint(in[i] * guess); sum = 0; for (i = 0; i < n; i++) @@ -808,7 +812,7 @@ vips_reducev_vector_to_fixed_point(double *in, int *out, int n, int scale) * first abs(extra_error) elements. */ int direction = extra_error > 0 ? 1 : -1; - int n_elements = VIPS_ABS(extra_error); + int n_elements = abs(extra_error); for (i = 0; i < n; i++) out[i] += each_error; @@ -848,14 +852,17 @@ vips_reducev_build(VipsObject *object) /* Output size. We need to always round to nearest, so round(), not * rint(). */ - height = VIPS_ROUND_UINT( - (double) in->Ysize / reducev->vshrink); + height = VIPS_ROUND_UINT((double) in->Ysize / reducev->vshrink); /* How many pixels we are inventing in the input, -ve for * discarding. */ extra_pixels = height * reducev->vshrink - in->Ysize; + /* The vshrink we do after integer reduction. + */ + reducev->residual_vshrink = reducev->vshrink; + if (reducev->gap > 0.0 && reducev->kernel != VIPS_KERNEL_NEAREST) { if (reducev->gap < 1.0) { @@ -867,7 +874,7 @@ vips_reducev_build(VipsObject *object) /* The int part of our reduce. */ int_vshrink = VIPS_MAX(1, - VIPS_FLOOR((double) in->Ysize / height / reducev->gap)); + floor((double) in->Ysize / height / reducev->gap)); if (int_vshrink > 1) { g_info("shrinkv by %d", int_vshrink); @@ -877,16 +884,16 @@ vips_reducev_build(VipsObject *object) return -1; in = t[0]; - reducev->vshrink /= int_vshrink; extra_pixels /= int_vshrink; + reducev->residual_vshrink /= int_vshrink; } } - if (reducev->vshrink == 1.0) + if (reducev->residual_vshrink == 1.0) return vips_image_write(in, resample->out); reducev->n_point = - vips_reduce_get_points(reducev->kernel, reducev->vshrink); + vips_reduce_get_points(reducev->kernel, reducev->residual_vshrink); g_info("reducev: %d point mask", reducev->n_point); if (reducev->n_point > MAX_POINT) { vips_error(object_class->nickname, @@ -904,21 +911,19 @@ vips_reducev_build(VipsObject *object) /* Build the tables of pre-computed coefficients. */ for (int y = 0; y < VIPS_TRANSFORM_SCALE + 1; y++) { - reducev->matrixf[y] = - VIPS_ARRAY(object, reducev->n_point, double); - reducev->matrixs[y] = - VIPS_ARRAY(object, reducev->n_point, short); + reducev->matrixf[y] = VIPS_ARRAY(object, reducev->n_point, double); + reducev->matrixs[y] = VIPS_ARRAY(object, reducev->n_point, short); if (!reducev->matrixf[y] || !reducev->matrixs[y]) return -1; vips_reduce_make_mask(reducev->matrixf[y], reducev->kernel, - reducev->n_point, reducev->vshrink, + reducev->n_point, reducev->residual_vshrink, (float) y / VIPS_TRANSFORM_SCALE); for (int i = 0; i < reducev->n_point; i++) - reducev->matrixs[y][i] = (short) (reducev->matrixf[y][i] * - VIPS_INTERPOLATE_SCALE); + reducev->matrixs[y][i] = + (short) (reducev->matrixf[y][i] * VIPS_INTERPOLATE_SCALE); #ifdef DEBUG printf("vips_reducev_build: mask %d\n ", y); for (int i = 0; i < reducev->n_point; i++) @@ -936,7 +941,7 @@ vips_reducev_build(VipsObject *object) /* Add new pixels around the input so we can interpolate at the edges. */ if (vips_embed(in, &t[2], - 0, VIPS_CEIL(reducev->n_point / 2.0) - 1, + 0, ceil(reducev->n_point / 2.0) - 1, in->Xsize, in->Ysize + reducev->n_point, "extend", VIPS_EXTEND_COPY, nullptr)) @@ -1108,9 +1113,38 @@ vips_reducev_init(VipsReducev *reducev) reducev->kernel = VIPS_KERNEL_LANCZOS3; } -/* See reduce.c for the doc comment. +/** + * vips_reducev: (method) + * @in: input image + * @out: (out): output image + * @vshrink: vertical reduce + * @...: `NULL`-terminated list of optional named arguments + * + * Reduce @in vertically by a float factor. + * + * The pixels in @out are + * interpolated with a 1D mask generated by @kernel. + * + * Set @gap to speed up reducing by having [method@Image.shrinkv] to shrink + * with a box filter first. The bigger @gap, the closer the result + * to the fair resampling. The smaller @gap, the faster resizing. + * The default value is 0.0 (no optimization). + * + * This is a very low-level operation: see [method@Image.resize] for a more + * convenient way to resize images. + * + * This operation does not change xres or yres. The image resolution needs to + * be updated by the application. + * + * ::: tip "Optional arguments" + * * @kernel: [enum@Kernel], to use to interpolate (default: lanczos3) + * * @gap: `gboolean`, reducing gap to use (default: 0.0) + * + * ::: seealso + * [method@Image.shrink], [method@Image.resize], [method@Image.affine]. + * + * Returns: 0 on success, -1 on error */ - int vips_reducev(VipsImage *in, VipsImage **out, double vshrink, ...) { diff --git a/libvips/resample/resample.c b/libvips/resample/resample.c index 8393b27523..c13ec6f6a8 100644 --- a/libvips/resample/resample.c +++ b/libvips/resample/resample.c @@ -52,43 +52,6 @@ #include "presample.h" -/** - * SECTION: resample - * @short_description: resample images in various ways - * @stability: Stable - * @include: vips/vips.h - * - * These operations build on each other in a set of layers. - * - * First, vips_affine() applies an affine transform to an image. This is any - * sort of 2D transform which preserves straight lines; so any combination of - * stretch, sheer, rotate and translate. You supply an interpolator for it to - * use to generate pixels, see vips_interpolate_new(). It will not produce - * good results for very large shrinks: you'll see aliasing. - * - * vips_reduce() is like vips_affine(), but it can only shrink images, it can't - * enlarge, rotate, or skew. It's very fast and uses an adaptive kernel for - * interpolation. - * - * vips_shrink() is a fast block shrinker. It can quickly reduce images by - * large integer factors. It will give poor results for small size reductions: - * again, you'll see aliasing. - * - * Next, vips_resize() specialises in the common task of image reduce and - * enlarge. It strings together combinations of vips_shrink(), vips_reduce(), - * vips_affine() and others to implement a general, high-quality image - * resizer. - * - * Finally, vips_thumbnail() combines load and resize in one operation, and adds - * colour management and correct handling of alpha transparency. Because load - * and resize happen together, it can exploit tricks like JPEG and TIFF - * shrink-on-load, giving a (potentially) huge speedup. vips_thumbnail_image() - * is only there for emergencies, don't use it unless you really have to. - * - * As a separate thing, `vips_mapim() can apply arbitrary 2D image transforms - * to an image. - */ - /** * VipsSize: * @VIPS_SIZE_BOTH: size both up and down @@ -99,7 +62,8 @@ * Controls whether an operation should upsize, downsize, both up and * downsize, or force a size. * - * See also: vips_thumbnail(). + * ::: seealso + * [ctor@Image.thumbnail]. */ G_DEFINE_ABSTRACT_TYPE(VipsResample, vips_resample, VIPS_TYPE_OPERATION); diff --git a/libvips/resample/resize.c b/libvips/resample/resize.c index 40cfc65633..7d50fb4c97 100644 --- a/libvips/resample/resize.c +++ b/libvips/resample/resize.c @@ -171,17 +171,17 @@ vips_resize_build(VipsObject *object) /* The int part of our scale. */ if (resize->gap < 1.0) { - int_hshrink = VIPS_FLOOR(1.0 / hscale); - int_vshrink = VIPS_FLOOR(1.0 / vscale); + int_hshrink = floor(1.0 / hscale); + int_vshrink = floor(1.0 / vscale); } else { target_width = VIPS_ROUND_UINT(in->Xsize * hscale); target_height = VIPS_ROUND_UINT(in->Ysize * vscale); - int_hshrink = VIPS_FLOOR( + int_hshrink = floor( (double) in->Xsize / target_width / resize->gap); - int_vshrink = VIPS_FLOOR( + int_vshrink = floor( (double) in->Ysize / target_height / resize->gap); } @@ -252,12 +252,12 @@ vips_resize_build(VipsObject *object) vips_object_local(object, interpolate); if (resize->kernel == VIPS_KERNEL_NEAREST && - hscale == VIPS_FLOOR(hscale) && - vscale == VIPS_FLOOR(vscale)) { + hscale == floor(hscale) && + vscale == floor(vscale)) { /* Fast, integral nearest neighbour enlargement */ - if (vips_zoom(in, &t[4], VIPS_FLOOR(hscale), - VIPS_FLOOR(vscale), NULL)) + if (vips_zoom(in, &t[4], floor(hscale), + floor(vscale), NULL)) return -1; in = t[4]; } @@ -400,31 +400,27 @@ vips_resize_init(VipsResize *resize) * @in: input image * @out: (out): output image * @scale: scale factor - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @vscale: %gdouble vertical scale factor - * * @kernel: #VipsKernel to reduce with - * * @gap: reducing gap to use (default: 2.0) + * @...: `NULL`-terminated list of optional named arguments * * Resize an image. * - * Set @gap to speed up downsizing by having vips_shrink() to shrink + * Set @gap to speed up downsizing by having [method@Image.shrink] to shrink * with a box filter first. The bigger @gap, the closer the result * to the fair resampling. The smaller @gap, the faster resizing. * The default value is 2.0 (very close to fair resampling * while still being faster in many cases). * - * vips_resize() normally uses #VIPS_KERNEL_LANCZOS3 for the final reduce, you - * can change this with @kernel. Downsizing is done with centre convention. + * [method@Image.resize] normally uses [enum@Vips.Kernel.LANCZOS3] for the final + * reduce, you can change this with @kernel. Downsizing is done with centre + * convention. * - * When upsizing (@scale > 1), the operation uses vips_affine() with - * a #VipsInterpolate selected depending on @kernel. It will use - * #VipsInterpolateBicubic for #VIPS_KERNEL_CUBIC and above. It adds a - * 0.5 pixel displacement to the input pixels to get centre convention scaling. + * When upsizing (@scale > 1), the operation uses [method@Image.affine] with + * a [class@Interpolate] selected depending on @kernel. It will use + * [class@Interpolate] "bicubic" for [enum@Vips.Kernel.CUBIC] and above. It + * adds a 0.5 pixel displacement to the input pixels to get centre convention + * scaling. * - * vips_resize() normally maintains the image aspect ratio. If you set + * [method@Image.resize] normally maintains the image aspect ratio. If you set * @vscale, that factor is used for the vertical scale and @scale for the * horizontal. * @@ -436,9 +432,15 @@ vips_resize_init(VipsResize *resize) * be updated by the application. * * This operation does not premultiply alpha. If your image has an alpha - * channel, you should use vips_premultiply() on it first. + * channel, you should use [method@Image.premultiply] on it first. + * + * ::: tip "optional arguments" + * * @vscale: `gdouble`, vertical scale factor + * * @kernel: [enum@Kernel], to reduce with + * * @gap: `gdouble`, reducing gap to use (default: 2.0) * - * See also: vips_premultiply(), vips_shrink(), vips_reduce(). + * ::: seealso + * [method@Image.premultiply], [method@Image.shrink], [method@Image.reduce]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/shrink.c b/libvips/resample/shrink.c index 7b0e13982b..74d2def9d5 100644 --- a/libvips/resample/shrink.c +++ b/libvips/resample/shrink.c @@ -187,24 +187,25 @@ vips_shrink_init(VipsShrink *shrink) * @out: (out): output image * @hshrink: horizontal shrink * @vshrink: vertical shrink - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Shrink @in by a pair of factors with a simple box filter. * - * * @ceil: round-up output dimensions + * For non-integer factors, [method@Image.shrink] will first shrink by the + * integer part with a box filter, then use [method@Image.reduce] to shrink + * by the remaining fractional part. * - * Shrink @in by a pair of factors with a simple box filter. For non-integer - * factors, vips_shrink() will first shrink by the integer part with a box - * filter, then use vips_reduce() to shrink by the - * remaining fractional part. - * - * This is a very low-level operation: see vips_resize() for a more + * This is a very low-level operation: see [method@Image.resize] for a more * convenient way to resize images. * * This operation does not change xres or yres. The image resolution needs to * be updated by the application. * - * See also: vips_resize(), vips_reduce(). + * ::: tip "Optional arguments" + * * @ceil: `gboolean`, round-up output dimensions + * + * ::: seealso + * [method@Image.resize], [method@Image.reduce]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/shrinkh.c b/libvips/resample/shrinkh.c index 4b2231ff42..6049a0e916 100644 --- a/libvips/resample/shrinkh.c +++ b/libvips/resample/shrinkh.c @@ -55,6 +55,7 @@ #include #include +#include #include #include @@ -72,9 +73,24 @@ typedef VipsResampleClass VipsShrinkhClass; G_DEFINE_TYPE(VipsShrinkh, vips_shrinkh, VIPS_TYPE_RESAMPLE); -#define INNER(BANDS) \ - sum += p[x1]; \ - x1 += BANDS; +/* Fixed-point arithmetic path for uchar images. + */ +#define UCHAR_SHRINK(BANDS) \ + { \ + unsigned char *restrict p = (unsigned char *) in; \ + unsigned char *restrict q = (unsigned char *) out; \ +\ + for (x = 0; x < width; x++) { \ + for (b = 0; b < BANDS; b++) { \ + int sum = amend; \ + for (x1 = b; x1 < ne; x1 += BANDS) \ + sum += p[x1]; \ + q[b] = (sum * multiplier) >> 24; \ + } \ + p += ne; \ + q += BANDS; \ + } \ + } /* Integer shrink. */ @@ -85,13 +101,10 @@ G_DEFINE_TYPE(VipsShrinkh, vips_shrinkh, VIPS_TYPE_RESAMPLE); \ for (x = 0; x < width; x++) { \ for (b = 0; b < BANDS; b++) { \ - ACC_TYPE sum; \ -\ - sum = 0; \ - x1 = b; \ - VIPS_UNROLL(shrink->hshrink, INNER(BANDS)); \ - q[b] = (sum + shrink->hshrink / 2) / \ - shrink->hshrink; \ + ACC_TYPE sum = amend; \ + for (x1 = b; x1 < ne; x1 += BANDS) \ + sum += p[x1]; \ + q[b] = sum / shrink->hshrink; \ } \ p += ne; \ q += BANDS; \ @@ -107,11 +120,9 @@ G_DEFINE_TYPE(VipsShrinkh, vips_shrinkh, VIPS_TYPE_RESAMPLE); \ for (x = 0; x < width; x++) { \ for (b = 0; b < bands; b++) { \ - double sum; \ -\ - sum = 0.0; \ - x1 = b; \ - VIPS_UNROLL(shrink->hshrink, INNER(bands)); \ + double sum = 0.0; \ + for (x1 = b; x1 < ne; x1 += bands) \ + sum += p[x1]; \ q[b] = sum / shrink->hshrink; \ } \ p += ne; \ @@ -132,11 +143,15 @@ vips_shrinkh_gen2(VipsShrinkh *shrink, VipsRegion *out_region, VipsRegion *ir, VipsPel *out = VIPS_REGION_ADDR(out_region, left, top); VipsPel *in = VIPS_REGION_ADDR(ir, left * shrink->hshrink, top); + int amend = shrink->hshrink / 2; + int x; int x1, b; switch (resample->in->BandFmt) { - case VIPS_FORMAT_UCHAR: + case VIPS_FORMAT_UCHAR: { + unsigned int multiplier = (1LL << 32) / ((1 << 8) * shrink->hshrink); + /* Generate a special path for 1, 3 and 4 band uchar data. The * compiler will be able to vectorise these. * @@ -145,20 +160,20 @@ vips_shrinkh_gen2(VipsShrinkh *shrink, VipsRegion *out_region, VipsRegion *ir, */ switch (bands) { case 1: - ISHRINK(int, unsigned char, 1); + UCHAR_SHRINK(1); break; case 3: - ISHRINK(int, unsigned char, 3); + UCHAR_SHRINK(3); break; case 4: - ISHRINK(int, unsigned char, 4); + UCHAR_SHRINK(4); break; default: - ISHRINK(int, unsigned char, bands); + UCHAR_SHRINK(bands); break; } break; - + } case VIPS_FORMAT_CHAR: ISHRINK(int, char, bands); break; @@ -169,10 +184,10 @@ vips_shrinkh_gen2(VipsShrinkh *shrink, VipsRegion *out_region, VipsRegion *ir, ISHRINK(int, short, bands); break; case VIPS_FORMAT_UINT: - ISHRINK(double, unsigned int, bands); + ISHRINK(gint64, unsigned int, bands); break; case VIPS_FORMAT_INT: - ISHRINK(double, int, bands); + ISHRINK(gint64, int, bands); break; case VIPS_FORMAT_FLOAT: FSHRINK(float); @@ -248,6 +263,73 @@ vips_shrinkh_gen(VipsRegion *out_region, return 0; } +#ifdef HAVE_HWY +static int +vips_shrinkh_uchar_vector_gen(VipsRegion *out_region, + void *seq, void *a, void *b, gboolean *stop) +{ + /* How do we chunk up the image? We don't want to prepare the whole of + * the input region corresponding to *r since it could be huge. + * + * Reading a line at a time could cause a lot of overcomputation, depending + * on what's upstream from us. In SMALLTILE, output scanlines could be + * quite small. + * + * Use fatstrip height as a compromise. + */ + const int dy = vips__fatstrip_height; + + VipsImage *in = (VipsImage *) a; + VipsShrinkh *shrink = (VipsShrinkh *) b; + VipsRegion *ir = (VipsRegion *) seq; + VipsRect *r = &out_region->valid; + const int bands = in->Bands; + + int y, y1; + +#ifdef DEBUG + printf("vips_shrinkh_uchar_vector_gen: generating %d x %d at %d x %d\n", + r->width, r->height, r->left, r->top); +#endif /*DEBUG*/ + + for (y = 0; y < r->height; y += dy) { + int chunk_height = VIPS_MIN(dy, r->height - y); + + VipsRect s; + + s.left = r->left * shrink->hshrink; + s.top = r->top + y; + s.width = r->width * shrink->hshrink; + s.height = chunk_height; +#ifdef DEBUG + printf("vips_shrinkh_uchar_vector_gen: requesting %d lines from %d\n", + s.height, s.top); +#endif /*DEBUG*/ + if (vips_region_prepare(ir, &s)) + return -1; + + VIPS_GATE_START("vips_shrinkh_uchar_vector_gen: work"); + + // each output line + for (y1 = 0; y1 < chunk_height; y1++) { + // top of this line in the output + int top = r->top + y + y1; + + VipsPel *q = VIPS_REGION_ADDR(out_region, r->left, top); + VipsPel *p = VIPS_REGION_ADDR(ir, s.left, top); + + vips_shrinkh_uchar_hwy(q, p, r->width, shrink->hshrink, bands); + } + + VIPS_GATE_STOP("vips_shrinkh_uchar_vector_gen: work"); + } + + VIPS_COUNT_PIXELS(out_region, "vips_shrinkh_uchar_vector_gen"); + + return 0; +} +#endif /*HAVE_HWY*/ + static int vips_shrinkh_build(VipsObject *object) { @@ -258,6 +340,7 @@ vips_shrinkh_build(VipsObject *object) vips_object_local_array(object, 2); VipsImage *in; + VipsGenerateFn generate; if (VIPS_OBJECT_CLASS(vips_shrinkh_parent_class)->build(object)) return -1; @@ -284,6 +367,20 @@ vips_shrinkh_build(VipsObject *object) return -1; in = t[1]; + /* For uchar input, try to make a vector path. + */ +#ifdef HAVE_HWY + if (in->BandFmt == VIPS_FORMAT_UCHAR && + vips_vector_isenabled()) { + generate = vips_shrinkh_uchar_vector_gen; + g_info("shrinkh: using vector path"); + } + else +#endif /*HAVE_HWY*/ + /* Default to the C path. + */ + generate = vips_shrinkh_gen; + if (vips_image_pipelinev(resample->out, VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) return -1; @@ -295,7 +392,7 @@ vips_shrinkh_build(VipsObject *object) * fractional part), we just see the integer part here. */ resample->out->Xsize = shrink->ceil - ? VIPS_CEIL((double) resample->in->Xsize / shrink->hshrink) + ? ceil((double) resample->in->Xsize / shrink->hshrink) : VIPS_ROUND_UINT((double) resample->in->Xsize / shrink->hshrink); if (resample->out->Xsize <= 0) { vips_error(class->nickname, @@ -310,7 +407,7 @@ vips_shrinkh_build(VipsObject *object) #endif /*DEBUG*/ if (vips_image_generate(resample->out, - vips_start_one, vips_shrinkh_gen, vips_stop_one, + vips_start_one, generate, vips_stop_one, in, shrink)) return -1; @@ -369,22 +466,24 @@ vips_shrinkh_init(VipsShrinkh *shrink) * @in: input image * @out: (out): output image * @hshrink: horizontal shrink - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @ceil: round-up output dimensions - * - * Shrink @in horizontally by an integer factor. Each pixel in the output is + * Shrink @in horizontally by an integer factor. + * Each pixel in the output is * the average of the corresponding line of @hshrink pixels in the input. * - * This is a very low-level operation: see vips_resize() for a more + * This is a very low-level operation: see [method@Image.resize] for a more * convenient way to resize images. * * This operation does not change xres or yres. The image resolution needs to * be updated by the application. * - * See also: vips_shrinkv(), vips_shrink(), vips_resize(), vips_affine(). + * ::: tip "Optional arguments" + * * @ceil: `gboolean`, round-up output dimensions + * + * ::: seealso + * [method@Image.shrinkv], [method@Image.shrink], [method@Image.resize], + * [method@Image.affine]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/shrinkh_hwy.cpp b/libvips/resample/shrinkh_hwy.cpp new file mode 100644 index 0000000000..41df4b1320 --- /dev/null +++ b/libvips/resample/shrinkh_hwy.cpp @@ -0,0 +1,129 @@ +/* 15/11/24 kleisauke + * - from shrinkv_hwy.cpp + */ + +/* + + 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 + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "presample.h" + +#ifdef HAVE_HWY + +#undef HWY_TARGET_INCLUDE +#define HWY_TARGET_INCLUDE "libvips/resample/shrinkh_hwy.cpp" +#include +#include + +namespace HWY_NAMESPACE { + +using namespace hwy::HWY_NAMESPACE; + +using DU32 = ScalableTag; +constexpr Rebind du8x32; +constexpr DU32 du32; + +constexpr int64_t max_uint32 = 1LL << 32; +constexpr int32_t max_bits = 1 << 8; + +HWY_ATTR void +vips_shrinkh_uchar_hwy(VipsPel *pout, VipsPel *pin, + int32_t width, int32_t hshrink, int32_t bands) +{ +#if HWY_TARGET != HWY_SCALAR + const auto multiplier = Set(du32, max_uint32 / (max_bits * hshrink)); + const auto amend = Set(du32, hshrink / 2); + + int32_t ix = 0; + + for (int32_t x = 0; x < width; ++x) { + auto *HWY_RESTRICT p = (uint8_t *) pin + ix * bands; + auto *HWY_RESTRICT q = (uint8_t *) pout + x * bands; + + auto sum0 = amend; + + int32_t xx = 0; + for (; xx + 2 <= hshrink; xx += 2) { + auto pix0 = PromoteTo(du32, LoadU(du8x32, p)); + p += bands; + auto pix1 = PromoteTo(du32, LoadU(du8x32, p)); + p += bands; + + pix0 = Add(pix0, pix1); + sum0 = Add(sum0, pix0); + } + for (; xx < hshrink; ++xx) { + auto pix0 = PromoteTo(du32, LoadU(du8x32, p)); + p += bands; + + sum0 = Add(sum0, pix0); + } + + sum0 = Mul(sum0, multiplier); + + /* The final 32->8 conversion. + */ + sum0 = ShiftRight<24>(sum0); + + auto demoted = DemoteTo(du8x32, sum0); + StoreU(demoted, du8x32, q); + + ix += hshrink; + } +#endif +} + +} /*namespace HWY_NAMESPACE*/ + +#if HWY_ONCE +HWY_EXPORT(vips_shrinkh_uchar_hwy); + +void +vips_shrinkh_uchar_hwy(VipsPel *pout, VipsPel *pin, + int width, int hshrink, int bands) +{ + /* clang-format off */ + HWY_DYNAMIC_DISPATCH(vips_shrinkh_uchar_hwy)(pout, pin, + width, hshrink, bands); + /* clang-format on */ +} +#endif /*HWY_ONCE*/ + +#endif /*HAVE_HWY*/ diff --git a/libvips/resample/shrinkv.c b/libvips/resample/shrinkv.c index ad69a71273..9b0f1c1df3 100644 --- a/libvips/resample/shrinkv.c +++ b/libvips/resample/shrinkv.c @@ -49,8 +49,6 @@ * - use a double sum buffer for int32 types * 22/4/22 kleisauke * - add @ceil option - * 12/8/23 jcupitt - * - improve chunking for small shrinks */ /* @@ -95,6 +93,7 @@ #include #include +#include #include #include @@ -149,7 +148,7 @@ vips_shrinkv_start(VipsImage *out, void *a, void *b) seq->ir = vips_region_new(in); - /* Big enough for the largest intermediate .. a whole scanline. + /* Big enough for the largest intermediate .. a couple of scanlines. */ seq->sum = VIPS_ARRAY(NULL, shrink->sizeof_line_buffer, VipsPel); @@ -158,7 +157,7 @@ vips_shrinkv_start(VipsImage *out, void *a, void *b) #define ADD(ACC_TYPE, TYPE) \ { \ - ACC_TYPE *restrict sum = (ACC_TYPE *) seq->sum; \ + ACC_TYPE *restrict sum = (ACC_TYPE *) seq->sum + sz * y; \ TYPE *restrict p = (TYPE *) in; \ \ for (x = 0; x < sz; x++) \ @@ -169,7 +168,7 @@ vips_shrinkv_start(VipsImage *out, void *a, void *b) */ static void vips_shrinkv_add_line(VipsShrinkv *shrink, VipsShrinkvSequence *seq, - VipsRegion *ir, int left, int top, int width) + VipsRegion *ir, int left, int top, int width, int y) { VipsResample *resample = VIPS_RESAMPLE(shrink); const int bands = resample->in->Bands * @@ -193,10 +192,10 @@ vips_shrinkv_add_line(VipsShrinkv *shrink, VipsShrinkvSequence *seq, ADD(int, short); break; case VIPS_FORMAT_UINT: - ADD(double, unsigned int); + ADD(gint64, unsigned int); break; case VIPS_FORMAT_INT: - ADD(double, int); + ADD(gint64, int); break; case VIPS_FORMAT_FLOAT: ADD(double, float); @@ -216,22 +215,36 @@ vips_shrinkv_add_line(VipsShrinkv *shrink, VipsShrinkvSequence *seq, } } +/* Fixed-point arithmetic path for uchar images. + */ +#define UCHAR_AVG() \ + { \ + int *restrict sum = (int *) seq->sum + sz * y; \ + unsigned char *restrict q = (unsigned char *) out; \ + int amend = shrink->vshrink / 2; \ + unsigned int multiplier = (1LL << 32) / ((1 << 8) * shrink->vshrink); \ +\ + for (x = 0; x < sz; x++) \ + q[x] = ((sum[x] + amend) * multiplier) >> 24; \ + } + /* Integer average. */ #define IAVG(ACC_TYPE, TYPE) \ { \ - ACC_TYPE *restrict sum = (ACC_TYPE *) seq->sum; \ + ACC_TYPE *restrict sum = (ACC_TYPE *) seq->sum + sz * y; \ TYPE *restrict q = (TYPE *) out; \ + int amend = shrink->vshrink / 2; \ \ for (x = 0; x < sz; x++) \ - q[x] = (sum[x] + shrink->vshrink / 2) / shrink->vshrink; \ + q[x] = (sum[x] + amend) / shrink->vshrink; \ } /* Float average. */ #define FAVG(TYPE) \ { \ - double *restrict sum = (double *) seq->sum; \ + double *restrict sum = (double *) seq->sum + sz * y; \ TYPE *restrict q = (TYPE *) out; \ \ for (x = 0; x < sz; x++) \ @@ -242,7 +255,7 @@ vips_shrinkv_add_line(VipsShrinkv *shrink, VipsShrinkvSequence *seq, */ static void vips_shrinkv_write_line(VipsShrinkv *shrink, VipsShrinkvSequence *seq, - VipsRegion *out_region, int left, int top, int width) + VipsRegion *out_region, int left, int top, int width, int y) { VipsResample *resample = VIPS_RESAMPLE(shrink); const int bands = resample->in->Bands * @@ -254,7 +267,7 @@ vips_shrinkv_write_line(VipsShrinkv *shrink, VipsShrinkvSequence *seq, VipsPel *out = VIPS_REGION_ADDR(out_region, left, top); switch (resample->in->BandFmt) { case VIPS_FORMAT_UCHAR: - IAVG(int, unsigned char); + UCHAR_AVG(); break; case VIPS_FORMAT_CHAR: IAVG(int, char); @@ -266,10 +279,10 @@ vips_shrinkv_write_line(VipsShrinkv *shrink, VipsShrinkvSequence *seq, IAVG(int, short); break; case VIPS_FORMAT_UINT: - IAVG(double, unsigned int); + IAVG(gint64, unsigned int); break; case VIPS_FORMAT_INT: - IAVG(double, int); + IAVG(gint64, int); break; case VIPS_FORMAT_FLOAT: FAVG(float); @@ -298,16 +311,16 @@ vips_shrinkv_gen(VipsRegion *out_region, VipsRegion *ir = seq->ir; VipsRect *r = &out_region->valid; - /* How do we chunk up the output image? We don't want to prepare the - * whole of the input region corresponding to *r since it could be huge. + /* How do we chunk up the image? We don't want to prepare the whole of + * the input region corresponding to *r since it could be huge. * - * We also don't want to fetch a line at a time, since that can make - * upstream coordinate changes very expensive. + * Reading a line at a time could cause a lot of overcomputation, depending + * on what's upstream from us. In SMALLTILE, output scanlines could be + * quite small. * - * Instead, aim for a minimum of tile_height on the input image. + * Use fatstrip height as a compromise. */ - int input_target = VIPS_MAX(shrink->vshrink, r->height); - int dy = input_target / shrink->vshrink; + int dy = vips__fatstrip_height; int y, y1, y2; @@ -319,37 +332,43 @@ vips_shrinkv_gen(VipsRegion *out_region, for (y = 0; y < r->height; y += dy) { int chunk_height = VIPS_MIN(dy, r->height - y); - VipsRect s; + memset(seq->sum, 0, shrink->sizeof_line_buffer); - s.left = r->left; - s.top = (r->top + y) * shrink->vshrink; - s.width = r->width; - s.height = chunk_height * shrink->vshrink; + const int start = (r->top + y) * shrink->vshrink; + const int end = (r->top + y + chunk_height) * shrink->vshrink; + + for (y1 = start; y1 < end; y1 += dy) { + VipsRect s; + + s.left = r->left; + s.top = y1; + s.width = r->width; + s.height = VIPS_MIN(dy, end - y1); #ifdef DEBUG - printf("vips_shrinkv_gen: requesting %d lines from %d\n", - s.height, s.top); + printf("vips_shrinkv_gen: requesting %d lines from %d\n", + s.height, s.top); #endif /*DEBUG*/ - if (vips_region_prepare(ir, &s)) - return -1; + if (vips_region_prepare(ir, &s)) + return -1; - VIPS_GATE_START("vips_shrinkv_gen: work"); + VIPS_GATE_START("vips_shrinkv_gen: work"); - // each output line - for (y1 = 0; y1 < chunk_height; y1++) { - // top of this line in the input - int top = s.top + y1 * shrink->vshrink; + for (y2 = 0; y2 < s.height; y2++) { + int chunk_y = (y1 + y2 - start) / shrink->vshrink; - memset(seq->sum, 0, shrink->sizeof_line_buffer); - - // each line in the corresponding area of input - for (y2 = 0; y2 < shrink->vshrink; y2++) vips_shrinkv_add_line(shrink, seq, ir, - s.left, top + y2, s.width); + s.left, y1 + y2, s.width, chunk_y); + } - vips_shrinkv_write_line(shrink, seq, out_region, - r->left, r->top + y + y1, r->width); + VIPS_GATE_STOP("vips_shrinkv_gen: work"); } + VIPS_GATE_START("vips_shrinkv_gen: work"); + + for (y1 = 0; y1 < chunk_height; y1++) + vips_shrinkv_write_line(shrink, seq, out_region, + r->left, r->top + y + y1, r->width, y1); + VIPS_GATE_STOP("vips_shrinkv_gen: work"); } @@ -358,6 +377,92 @@ vips_shrinkv_gen(VipsRegion *out_region, return 0; } +#ifdef HAVE_HWY +static int +vips_shrinkv_uchar_vector_gen(VipsRegion *out_region, + void *vseq, void *a, void *b, gboolean *stop) +{ + VipsShrinkvSequence *seq = (VipsShrinkvSequence *) vseq; + VipsImage *in = (VipsImage *) a; + VipsShrinkv *shrink = (VipsShrinkv *) b; + VipsRegion *ir = seq->ir; + VipsRect *r = &out_region->valid; + const int bands = in->Bands; + int ne = r->width * bands; + + /* How do we chunk up the image? We don't want to prepare the whole of + * the input region corresponding to *r since it could be huge. + * + * Reading a line at a time could cause a lot of overcomputation, depending + * on what's upstream from us. In SMALLTILE, output scanlines could be + * quite small. + * + * Use fatstrip height as a compromise. + */ + int dy = vips__fatstrip_height; + + int y, y1, y2; + +#ifdef DEBUG + printf("vips_shrinkv_uchar_vector_gen: generating %d x %d at %d x %d\n", + r->width, r->height, r->left, r->top); +#endif /*DEBUG*/ + + for (y = 0; y < r->height; y += dy) { + int chunk_height = VIPS_MIN(dy, r->height - y); + + memset(seq->sum, 0, shrink->sizeof_line_buffer); + + const int start = (r->top + y) * shrink->vshrink; + const int end = (r->top + y + chunk_height) * shrink->vshrink; + + for (y1 = start; y1 < end; y1 += dy) { + VipsRect s; + + s.left = r->left; + s.top = y1; + s.width = r->width; + s.height = VIPS_MIN(dy, end - y1); +#ifdef DEBUG + printf( + "vips_shrinkv_uchar_vector_gen: requesting %d lines from %d\n", + s.height, s.top); +#endif /*DEBUG*/ + if (vips_region_prepare(ir, &s)) + return -1; + + VIPS_GATE_START("vips_shrinkv_uchar_vector_gen: work"); + + for (y2 = 0; y2 < s.height; y2++) { + VipsPel *p = VIPS_REGION_ADDR(ir, r->left, y1 + y2); + int chunk_y = (y1 + y2 - start) / shrink->vshrink; + + vips_shrinkv_add_line_uchar_hwy(p, ne, + (unsigned int *) seq->sum + ne * chunk_y); + } + + VIPS_GATE_STOP("vips_shrinkv_uchar_vector_gen: work"); + } + + VIPS_GATE_START("vips_shrinkv_uchar_vector_gen: work"); + + for (y1 = 0; y1 < chunk_height; y1++) { + VipsPel *q = VIPS_REGION_ADDR(out_region, r->left, + r->top + y + y1); + + vips_shrinkv_write_line_uchar_hwy(q, ne, shrink->vshrink, + (unsigned int *) seq->sum + ne * y1); + } + + VIPS_GATE_STOP("vips_shrinkv_uchar_vector_gen: work"); + } + + VIPS_COUNT_PIXELS(out_region, "vips_shrinkv_uchar_vector_gen"); + + return 0; +} +#endif /*HAVE_HWY*/ + static int vips_shrinkv_build(VipsObject *object) { @@ -367,6 +472,8 @@ vips_shrinkv_build(VipsObject *object) VipsImage **t = (VipsImage **) vips_object_local_array(object, 4); VipsImage *in; + VipsGenerateFn generate; + size_t acc_size; if (VIPS_OBJECT_CLASS(vips_shrinkv_parent_class)->build(object)) return -1; @@ -393,11 +500,45 @@ vips_shrinkv_build(VipsObject *object) return -1; in = t[1]; + /* Determine the accumulator size based on the band format. + */ + switch (resample->in->BandFmt) { + case VIPS_FORMAT_UINT: + case VIPS_FORMAT_INT: + acc_size = sizeof(gint64); + break; + case VIPS_FORMAT_FLOAT: + case VIPS_FORMAT_COMPLEX: + case VIPS_FORMAT_DOUBLE: + case VIPS_FORMAT_DPCOMPLEX: + acc_size = sizeof(double); + break; + default: + acc_size = sizeof(int); + break; + } + + if (vips_band_format_iscomplex(resample->in->BandFmt)) + acc_size *= 2; + /* We have to keep a line buffer as we sum columns. */ shrink->sizeof_line_buffer = - in->Xsize * in->Bands * - vips_format_sizeof(VIPS_FORMAT_DPCOMPLEX); + in->Xsize * in->Bands * vips__fatstrip_height * acc_size; + + /* For uchar input, try to make a vector path. + */ +#ifdef HAVE_HWY + if (in->BandFmt == VIPS_FORMAT_UCHAR && + vips_vector_isenabled()) { + generate = vips_shrinkv_uchar_vector_gen; + g_info("shrinkv: using vector path"); + } + else +#endif /*HAVE_HWY*/ + /* Default to the C path. + */ + generate = vips_shrinkv_gen; /* SMALLTILE or we'll need huge input areas for our output. In seq * mode, the linecache above will keep us sequential. @@ -414,7 +555,7 @@ vips_shrinkv_build(VipsObject *object) * fractional part), we just see the integer part here. */ t[2]->Ysize = shrink->ceil - ? VIPS_CEIL((double) resample->in->Ysize / shrink->vshrink) + ? ceil((double) resample->in->Ysize / shrink->vshrink) : VIPS_ROUND_UINT((double) resample->in->Ysize / shrink->vshrink); if (t[2]->Ysize <= 0) { vips_error(class->nickname, @@ -430,7 +571,7 @@ vips_shrinkv_build(VipsObject *object) #endif /*DEBUG*/ if (vips_image_generate(t[2], - vips_shrinkv_start, vips_shrinkv_gen, vips_shrinkv_stop, + vips_shrinkv_start, generate, vips_shrinkv_stop, in, shrink)) return -1; @@ -514,22 +655,25 @@ vips_shrinkv_init(VipsShrinkv *shrink) * @in: input image * @out: (out): output image * @vshrink: vertical shrink - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Shrink @in vertically by an integer factor. * - * * @ceil: round-up output dimensions - * - * Shrink @in vertically by an integer factor. Each pixel in the output is + * Each pixel in the output is * the average of the corresponding column of @vshrink pixels in the input. * - * This is a very low-level operation: see vips_resize() for a more + * This is a very low-level operation: see [method@Image.resize] for a more * convenient way to resize images. * * This operation does not change xres or yres. The image resolution needs to * be updated by the application. * - * See also: vips_shrinkh(), vips_shrink(), vips_resize(), vips_affine(). + * ::: tip "Optional arguments" + * * @ceil: `gboolean`, round-up output dimensions + * + * ::: seealso + * [method@Image.shrinkh], [method@Image.shrink], [method@Image.resize], + * [method@Image.affine]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/shrinkv_hwy.cpp b/libvips/resample/shrinkv_hwy.cpp new file mode 100644 index 0000000000..99f57ce68b --- /dev/null +++ b/libvips/resample/shrinkv_hwy.cpp @@ -0,0 +1,216 @@ +/* 14/11/24 kleisauke + * - from reducev_hwy.cpp + */ + +/* + + 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 + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "presample.h" + +#ifdef HAVE_HWY + +#undef HWY_TARGET_INCLUDE +#define HWY_TARGET_INCLUDE "libvips/resample/shrinkv_hwy.cpp" +#include +#include + +namespace HWY_NAMESPACE { + +using namespace hwy::HWY_NAMESPACE; + +using DU32 = ScalableTag; +using DU16 = ScalableTag; +constexpr Rebind du8x16; +#if HWY_ARCH_RVV || (HWY_ARCH_ARM_A64 && HWY_TARGET <= HWY_SVE) +constexpr Rebind du8x32; +#endif +constexpr DU16 du16; +constexpr DU32 du32; + +constexpr int64_t max_uint32 = 1LL << 32; +constexpr int32_t max_bits = 1 << 8; + +#if defined(HAVE_HWY_1_1_0) && \ + (HWY_ARCH_RVV || (HWY_ARCH_ARM_A64 && HWY_TARGET <= HWY_SVE)) +#define InterleaveLower InterleaveWholeLower +#define InterleaveUpper InterleaveWholeUpper +#endif + +HWY_ATTR void +vips_shrinkv_add_line_uchar_hwy(VipsPel *pin, + int32_t ne, uint32_t *HWY_RESTRICT sum) +{ +#if HWY_TARGET != HWY_SCALAR +#if !defined(HAVE_HWY_1_1_0) && \ + (HWY_ARCH_RVV || (HWY_ARCH_ARM_A64 && HWY_TARGET <= HWY_SVE)) + /* Ensure we do not cross 128-bit block boundaries on RVV/SVE. + */ + const int32_t N = 8; +#else + const int32_t N = Lanes(du16); +#endif + + const auto zero = Zero(du16); + auto *HWY_RESTRICT p = (uint8_t *) pin; + + /* Main sum loop: unrolled. + */ + int32_t x = 0; + for (; x + N <= ne; x += N) { + auto pix0 = PromoteTo(du16, LoadU(du8x16, p + x)); + + auto sum0 = LoadU(du32, &sum[x + 0 * N / 2]); + auto sum1 = LoadU(du32, &sum[x + 1 * N / 2]); + + sum0 = Add(sum0, BitCast(du32, InterleaveLower(du16, pix0, zero))); + sum1 = Add(sum1, BitCast(du32, InterleaveUpper(du16, pix0, zero))); + + StoreU(sum0, du32, &sum[x + 0 * N / 2]); + StoreU(sum1, du32, &sum[x + 1 * N / 2]); + } + + /* `ne` was not a multiple of the vector length `N`; + * proceed one by one. + */ + for (; x < ne; ++x) + sum[x] += p[x]; +#endif +} + +HWY_ATTR void +vips_shrinkv_write_line_uchar_hwy(VipsPel *pout, + int32_t ne, int32_t vshrink, uint32_t *HWY_RESTRICT sum) +{ +#if HWY_TARGET != HWY_SCALAR +#if !defined(HAVE_HWY_1_1_0) && \ + (HWY_ARCH_RVV || (HWY_ARCH_ARM_A64 && HWY_TARGET <= HWY_SVE)) + /* Ensure we do not cross 128-bit block boundaries on RVV/SVE. + */ + const int32_t N = 8; +#else + const int32_t N = Lanes(du16); +#endif + + const uint32_t multiplier = max_uint32 / (max_bits * vshrink); + const uint32_t amend = vshrink / 2; + + const auto multiplier_v = Set(du32, multiplier); + const auto amend_v = Set(du32, amend); + + /* Main write loop: unrolled. + */ + int32_t x = 0; + for (; x + N <= ne; x += N) { + auto *HWY_RESTRICT q = (uint8_t *) pout + x; + + auto sum0 = LoadU(du32, &sum[x + 0 * N / 2]); + auto sum1 = LoadU(du32, &sum[x + 1 * N / 2]); + + sum0 = Add(sum0, amend_v); + sum1 = Add(sum1, amend_v); + + sum0 = Mul(sum0, multiplier_v); + sum1 = Mul(sum1, multiplier_v); + + /* The final 32->8 conversion. + */ + sum0 = ShiftRight<24>(sum0); + sum1 = ShiftRight<24>(sum1); + +#if HWY_ARCH_RVV || (HWY_ARCH_ARM_A64 && HWY_TARGET <= HWY_SVE) + /* RVV/SVE defines demotion as writing to the upper or lower half + * of each lane, rather than compacting them within a vector. + */ + auto demoted0 = DemoteTo(du8x32, sum0); + auto demoted1 = DemoteTo(du8x32, sum1); + + StoreU(demoted0, du8x32, q + 0 * N / 2); + StoreU(demoted1, du8x32, q + 1 * N / 2); +#else + auto demoted0 = ReorderDemote2To(du16, sum0, sum1); + auto demoted = DemoteTo(du8x16, demoted0); + + StoreU(demoted, du8x16, q); +#endif + } + + /* `ne` was not a multiple of the vector length `N`; + * proceed one by one. + */ + for (; x < ne; ++x) { + auto *HWY_RESTRICT q = (uint8_t *) pout + x; + + *q = ((sum[x] + amend) * multiplier) >> 24; + } +#endif +} + +#undef InterleaveLower +#undef InterleaveUpper + +} /*namespace HWY_NAMESPACE*/ + +#if HWY_ONCE +HWY_EXPORT(vips_shrinkv_add_line_uchar_hwy); +HWY_EXPORT(vips_shrinkv_write_line_uchar_hwy); + +void +vips_shrinkv_add_line_uchar_hwy(VipsPel *pin, + int ne, unsigned int *restrict sum) +{ + /* clang-format off */ + HWY_DYNAMIC_DISPATCH(vips_shrinkv_add_line_uchar_hwy)(pin, + ne, sum); + /* clang-format on */ +} + +void +vips_shrinkv_write_line_uchar_hwy(VipsPel *pout, + int ne, int vshrink, unsigned int *restrict sum) +{ + /* clang-format off */ + HWY_DYNAMIC_DISPATCH(vips_shrinkv_write_line_uchar_hwy)(pout, + ne, vshrink, sum); + /* clang-format on */ +} +#endif /*HWY_ONCE*/ + +#endif /*HAVE_HWY*/ diff --git a/libvips/resample/similarity.c b/libvips/resample/similarity.c index 3508df846a..97215ee55a 100644 --- a/libvips/resample/similarity.c +++ b/libvips/resample/similarity.c @@ -220,24 +220,24 @@ vips_similarity_init(VipsSimilarity *similarity) * vips_similarity: (method) * @in: input image * @out: (out): output image - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * This operator calls [method@Image.affine] for you, calculating the matrix + * for the affine transform from @scale and @angle. Other parameters are + * passed on to [method@Image.affine] unaltered. * - * * @scale: %gdouble, scale by this factor - * * @angle: %gdouble, rotate by this many degrees clockwise - * * @interpolate: #VipsInterpolate, interpolate pixels with this - * * @background: #VipsArrayDouble colour for new pixels - * * @idx: %gdouble, input horizontal offset - * * @idy: %gdouble, input vertical offset - * * @odx: %gdouble, output horizontal offset - * * @ody: %gdouble, output vertical offset + * ::: tip "Optional arguments" + * * @scale: `gdouble`, scale by this factor + * * @angle: `gdouble`, rotate by this many degrees clockwise + * * @interpolate: [class@Interpolate], interpolate pixels with this + * * @background: [struct@ArrayDouble] colour for new pixels + * * @idx: `gdouble`, input horizontal offset + * * @idy: `gdouble`, input vertical offset + * * @odx: `gdouble`, output horizontal offset + * * @ody: `gdouble`, output vertical offset * - * This operator calls vips_affine() for you, calculating the matrix for the - * affine transform from @scale and @angle. Other parameters are passed on to - * vips_affine() unaltered. - * - * See also: vips_affine(), #VipsInterpolate. + * ::: seealso + * [method@Image.affine], [class@Interpolate]. * * Returns: 0 on success, -1 on error */ @@ -289,23 +289,24 @@ vips_rotate_init(VipsRotate *rotate) * vips_rotate: (method) * @in: input image * @out: (out): output image - * @angle: %gdouble, rotate by this many degrees clockwise - * @...: %NULL-terminated list of optional named arguments + * @angle: `gdouble`, rotate by this many degrees clockwise + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * This operator calls [method@Image.affine] for you, calculating the matrix + * for the affine transform from @scale and @angle. * - * * @interpolate: #VipsInterpolate, interpolate pixels with this - * * @background: #VipsArrayDouble colour for new pixels - * * @idx: %gdouble, input horizontal offset - * * @idy: %gdouble, input vertical offset - * * @odx: %gdouble, output horizontal offset - * * @ody: %gdouble, output vertical offset + * Other parameters are passed on to [method@Image.affine] unaltered. * - * This operator calls vips_affine() for you, calculating the matrix for the - * affine transform from @scale and @angle. Other parameters are passed on to - * vips_affine() unaltered. + * ::: tip "Optional arguments" + * * @interpolate: [class@Interpolate], interpolate pixels with this + * * @background: [struct@ArrayDouble], colour for new pixels + * * @idx: `gdouble`, input horizontal offset + * * @idy: `gdouble`, input vertical offset + * * @odx: `gdouble`, output horizontal offset + * * @ody: `gdouble`, output vertical offset * - * See also: vips_affine(), #VipsInterpolate. + * ::: seealso + * [method@Image.affine], [class@Interpolate]. * * Returns: 0 on success, -1 on error */ diff --git a/libvips/resample/templates.h b/libvips/resample/templates.h index b8c4f9c4f5..ae347dbb52 100644 --- a/libvips/resample/templates.h +++ b/libvips/resample/templates.h @@ -323,7 +323,7 @@ static void inline calculate_coefficients_catmull(double c[4], const double x) */ static double inline cubic_filter(double x, double B, double C) { - const double ax = VIPS_FABS(x); + const double ax = fabs(x); const double ax2 = ax * ax; const double ax3 = ax2 * ax; @@ -361,7 +361,7 @@ static double inline filter(double x); template <> double inline filter(double x) { - x = VIPS_FABS(x); + x = fabs(x); if (x < 1.0) return 1.0 - x; @@ -404,7 +404,7 @@ double inline filter(double x) template <> double inline filter(double x) { - x = VIPS_FABS(x); + x = fabs(x); if (x >= 2.5) return 0.0; @@ -421,7 +421,7 @@ double inline filter(double x) template <> double inline filter(double x) { - x = VIPS_FABS(x); + x = fabs(x); if (x >= 4.5) return 0.0; diff --git a/libvips/resample/thumbnail.c b/libvips/resample/thumbnail.c index 195f20636f..36144e8bc5 100644 --- a/libvips/resample/thumbnail.c +++ b/libvips/resample/thumbnail.c @@ -116,8 +116,8 @@ typedef struct _VipsThumbnail { gboolean no_rotate; VipsInteresting crop; gboolean linear; - char *export_profile; - char *import_profile; + char *output_profile; + char *input_profile; VipsIntent intent; VipsFailOn fail_on; @@ -486,7 +486,7 @@ vips_thumbnail_find_jpegshrink(VipsThumbnail *thumbnail, /* Shrink-on-load is a simple block shrink and will add quite a bit of * extra sharpness to the image. We want to block shrink to a - * bit above our target, then vips_shrink() / vips_reduce() to the + * bit above our target, then vips_shrink / vips_reduce() to the * final size. * * Leave at least a factor of two for the final resize step. @@ -680,10 +680,10 @@ vips_thumbnail_build(VipsObject *object) * auto_rotate. */ if (vips_object_argument_isset(object, "no_rotate")) - thumbnail->auto_rotate = !thumbnail->no_rotate; + thumbnail->auto_rotate = !thumbnail->no_rotate; // FIXME: Invalidates operation cache if (!vips_object_argument_isset(object, "height")) - thumbnail->height = thumbnail->width; + thumbnail->height = thumbnail->width; // FIXME: Invalidates operation cache /* Open and do any pre-shrinking. */ @@ -695,8 +695,8 @@ vips_thumbnail_build(VipsObject *object) */ preshrunk_page_height = vips_image_get_page_height(in); - needs_icc_transform = thumbnail->export_profile && - (thumbnail->import_profile || + needs_icc_transform = thumbnail->output_profile && + (thumbnail->input_profile || vips_image_get_typeof(in, VIPS_META_ICC_NAME)); /* RAD needs special unpacking. @@ -716,20 +716,20 @@ vips_thumbnail_build(VipsObject *object) */ have_imported = FALSE; if (thumbnail->linear) { - /* If we are doing colour management (there's an import + /* If we are doing colour management (there's an input * profile), then we can use XYZ PCS as the resize space. */ if (in->Coding == VIPS_CODING_NONE && (in->BandFmt == VIPS_FORMAT_UCHAR || in->BandFmt == VIPS_FORMAT_USHORT) && (vips_image_get_typeof(in, VIPS_META_ICC_NAME) || - thumbnail->import_profile)) { + thumbnail->input_profile)) { g_info("importing to XYZ PCS"); - if (thumbnail->import_profile) - g_info("fallback input profile %s", thumbnail->import_profile); + if (thumbnail->input_profile) + g_info("fallback input profile %s", thumbnail->input_profile); if (vips_icc_import(in, &t[2], - "input_profile", thumbnail->import_profile, + "input_profile", thumbnail->input_profile, "embedded", TRUE, "intent", thumbnail->intent, "pcs", VIPS_PCS_XYZ, @@ -783,7 +783,7 @@ vips_thumbnail_build(VipsObject *object) * page_height or we'll have pixels straddling page boundaries. */ if (in->Ysize > preshrunk_page_height) { - int target_page_height = VIPS_RINT(preshrunk_page_height / vshrink); + int target_page_height = rint(preshrunk_page_height / vshrink); int target_image_height = target_page_height * thumbnail->n_loaded_pages; @@ -827,7 +827,7 @@ vips_thumbnail_build(VipsObject *object) * accidentally turn into an animated image later. */ if (thumbnail->n_loaded_pages > 1) { - int output_page_height = VIPS_RINT(preshrunk_page_height / vshrink); + int output_page_height = rint(preshrunk_page_height / vshrink); if (vips_copy(in, &t[8], NULL)) return -1; @@ -844,11 +844,11 @@ vips_thumbnail_build(VipsObject *object) if (have_imported) { /* We are in PCS. Export with the output profile, if any (this * will export with the embedded input profile if there's no - * export profile). + * output profile). */ g_info("exporting to device space with a profile"); if (vips_icc_export(in, &t[9], - "output_profile", thumbnail->export_profile, + "output_profile", thumbnail->output_profile, "intent", thumbnail->intent, "depth", 8, NULL)) @@ -859,8 +859,8 @@ vips_thumbnail_build(VipsObject *object) /* We can transform to the output with a pair of ICC profiles. */ g_info("transforming with supplied profiles"); - if (vips_icc_transform(in, &t[9], thumbnail->export_profile, - "input_profile", thumbnail->import_profile, + if (vips_icc_transform(in, &t[9], thumbnail->output_profile, + "input_profile", thumbnail->input_profile, "intent", thumbnail->intent, "embedded", TRUE, "depth", 8, @@ -869,14 +869,14 @@ vips_thumbnail_build(VipsObject *object) in = t[9]; } - else if (thumbnail->export_profile) { + else if (thumbnail->output_profile) { /* We are in one of the resize space (sRGB, scRGB, B_W, GREY16, etc.) * and need to go to PCS, then export. */ - g_info("exporting with %s", thumbnail->export_profile); + g_info("exporting with %s", thumbnail->output_profile); if (vips_colourspace(in, &t[9], VIPS_INTERPRETATION_XYZ, NULL) || vips_icc_export(t[9], &t[10], - "output_profile", thumbnail->export_profile, + "output_profile", thumbnail->output_profile, "intent", thumbnail->intent, "depth", 8, NULL)) @@ -885,7 +885,7 @@ vips_thumbnail_build(VipsObject *object) } else if (thumbnail->linear) { /* We are in one of the scRGB or GREY16 spaces and there's - * no export profile. Output to sRGB or B_W. + * no output profile. Output to sRGB or B_W. */ VipsInterpretation interpretation; @@ -1012,18 +1012,18 @@ vips_thumbnail_class_init(VipsThumbnailClass *class) G_STRUCT_OFFSET(VipsThumbnail, linear), FALSE); - VIPS_ARG_STRING(class, "import_profile", 118, - _("Import profile"), - _("Fallback import profile"), + VIPS_ARG_STRING(class, "input_profile", 118, + _("Input profile"), + _("Fallback input profile"), VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET(VipsThumbnail, import_profile), + G_STRUCT_OFFSET(VipsThumbnail, input_profile), NULL); - VIPS_ARG_STRING(class, "export_profile", 119, - _("Export profile"), - _("Fallback export profile"), + VIPS_ARG_STRING(class, "output_profile", 119, + _("Output profile"), + _("Fallback output profile"), VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET(VipsThumbnail, export_profile), + G_STRUCT_OFFSET(VipsThumbnail, output_profile), NULL); VIPS_ARG_ENUM(class, "intent", 120, @@ -1046,12 +1046,30 @@ vips_thumbnail_class_init(VipsThumbnailClass *class) * This is now replaced (though still functional) with "no-rotate", * see above. */ - VIPS_ARG_BOOL(class, "auto_rotate", 121, + VIPS_ARG_BOOL(class, "auto_rotate", 130, _("Auto rotate"), _("Use orientation tags to rotate image upright"), VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED, G_STRUCT_OFFSET(VipsThumbnail, auto_rotate), TRUE); + + /* Renamed as input-profile and output-profile for consistency with the + * rest of the API. + */ + + VIPS_ARG_STRING(class, "import_profile", 131, + _("Import profile"), + _("Fallback import profile"), + VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED, + G_STRUCT_OFFSET(VipsThumbnail, input_profile), + NULL); + + VIPS_ARG_STRING(class, "export_profile", 132, + _("Export profile"), + _("Fallback export profile"), + VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED, + G_STRUCT_OFFSET(VipsThumbnail, output_profile), + NULL); } static void @@ -1212,28 +1230,18 @@ vips_thumbnail_file_init(VipsThumbnailFile *file) * @filename: file to read from * @out: (out): output image * @width: target width in pixels - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Make a thumbnail from a file. * - * * @height: %gint, target height in pixels - * * @size: #VipsSize, upsize, downsize, both or force - * * @no_rotate: %gboolean, don't rotate upright using orientation tag - * * @crop: #VipsInteresting, shrink and crop to fill target - * * @linear: %gboolean, perform shrink in linear light - * * @import_profile: %gchararray, fallback import ICC profile - * * @export_profile: %gchararray, export ICC profile - * * @intent: #VipsIntent, rendering intent - * * @fail_on: #VipsFailOn, load error types to fail on - * - * Make a thumbnail from a file. Shrinking is done in three stages: using any - * shrink-on-load features available in the file import library, using a block + * Shrinking is done in three stages: using any + * shrink-on-load features available in the image load library, using a block * shrink, and using a lanczos3 shrink. At least the final 200% is done with * lanczos3. The output should be high quality, and the operation should be * quick. * - * See vips_thumbnail_buffer() to thumbnail from a memory buffer, or - * vips_thumbnail_source() to thumbnail from an arbitrary byte source. + * See [ctor@Image.thumbnail_buffer] to thumbnail from a memory buffer, or + * [ctor@Image.thumbnail_source] to thumbnail from an arbitrary byte source. * * By default, libvips will only use the first frame of animated or multipage * images. To thumbnail all pages or frames, pass `n=-1` to the loader in @@ -1244,21 +1252,19 @@ vips_thumbnail_file_init(VipsThumbnailFile *file) * @height to a very large number to ignore that dimension. * * If you set @crop, then the output image will fill the whole of the @width x - * @height rectangle, with any excess cropped away. See vips_smartcrop() for + * @height rectangle, with any excess cropped away. See [method@Image.smartcrop] for * details on the cropping strategy. * * Normally the operation will upsize or downsize as required to fit the image - * inside or outside the target size. If @size is set - * to #VIPS_SIZE_UP, the operation will only upsize and will just - * copy if asked to downsize. - * If @size is set - * to #VIPS_SIZE_DOWN, the operation will only downsize and will just - * copy if asked to upsize. - * If @size is #VIPS_SIZE_FORCE, the image aspect ratio will be broken and the - * image will be forced to fit the target. + * inside or outside the target size. If @size is set to [enum@Vips.Size.UP], + * the operation will only upsize and will just copy if asked to downsize. + * If @size is set to [enum@Vips.Size.DOWN], the operation will only downsize + * and will just copy if asked to upsize. + * If @size is [enum@Vips.Size.FORCE], the image aspect ratio will be broken + * and the image will be forced to fit the target. * * Normally any orientation tags on the input image (such as EXIF tags) are - * interpreted to rotate the image upright. If you set @no_rotate to %TRUE, + * interpreted to rotate the image upright. If you set @no_rotate to `TRUE`, * these tags will not be interpreted. * * Shrinking is normally done in sRGB colourspace. Set @linear to shrink in @@ -1266,19 +1272,31 @@ vips_thumbnail_file_init(VipsThumbnailFile *file) * also be far slower, since tricks like JPEG shrink-on-load cannot be used in * linear space. * - * If you set @export_profile to the filename of an ICC profile, the image + * If you set @output_profile to the filename of an ICC profile, the image * will be transformed to the target colourspace before writing to the - * output. You can also give an @import_profile which will be used if the + * output. You can also give an @input_profile which will be used if the * input image has no ICC profile, or if the profile embedded in the * input image is broken. * * Use @intent to set the rendering intent for any ICC transform. The default - * is #VIPS_INTENT_RELATIVE. + * is [enum@Vips.Intent.RELATIVE]. * * Use @fail_on to control the types of error that will cause loading to fail. - * The default is #VIPS_FAIL_ON_NONE, ie. thumbnail is permissive. + * The default is [enum@Vips.FailOn.NONE], ie. thumbnail is permissive. + * + * ::: tip "Optional arguments" + * * @height: `gint`, target height in pixels + * * @size: [enum@Size], upsize, downsize, both or force + * * @no_rotate: `gboolean`, don't rotate upright using orientation tag + * * @crop: [enum@Interesting], shrink and crop to fill target + * * @linear: `gboolean`, perform shrink in linear light + * * @input_profile: `gchararray`, fallback input ICC profile + * * @output_profile: `gchararray`, output ICC profile + * * @intent: [enum@Intent], rendering intent + * * @fail_on: [enum@FailOn], load error types to fail on * - * See also: vips_thumbnail_buffer(). + * ::: seealso + * [ctor@Image.thumbnail_buffer]. * * Returns: 0 on success, -1 on error. */ @@ -1467,26 +1485,27 @@ vips_thumbnail_buffer_init(VipsThumbnailBuffer *buffer) * @len: (type gsize): size of memory area * @out: (out): output image * @width: target width in pixels - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: + * Exactly as [ctor@Image.thumbnail], but read from a memory buffer. * - * * @height: %gint, target height in pixels - * * @size: #VipsSize, upsize, downsize, both or force - * * @no_rotate: %gboolean, don't rotate upright using orientation tag - * * @crop: #VipsInteresting, shrink and crop to fill target - * * @linear: %gboolean, perform shrink in linear light - * * @import_profile: %gchararray, fallback import ICC profile - * * @export_profile: %gchararray, export ICC profile - * * @intent: #VipsIntent, rendering intent - * * @fail_on: #VipsFailOn, load error types to fail on - * * @option_string: %gchararray, extra loader options + * One extra optional argument, @option_string, lets you pass options to the + * underlying loader. * - * Exactly as vips_thumbnail(), but read from a memory buffer. One extra - * optional argument, @option_string, lets you pass options to the underlying - * loader. + * ::: tip "Optional arguments" + * * @height: `gint`, target height in pixels + * * @size: [enum@Size], upsize, downsize, both or force + * * @no_rotate: `gboolean`, don't rotate upright using orientation tag + * * @crop: [enum@Interesting], shrink and crop to fill target + * * @linear: `gboolean`, perform shrink in linear light + * * @input_profile: `gchararray`, fallback input ICC profile + * * @output_profile: `gchararray`, output ICC profile + * * @intent: [enum@Intent], rendering intent + * * @fail_on: [enum@FailOn], load error types to fail on + * * @option_string: `gchararray`, extra loader options * - * See also: vips_thumbnail(). + * ::: seealso + * [ctor@Image.thumbnail]. * * Returns: 0 on success, -1 on error. */ @@ -1679,26 +1698,28 @@ vips_thumbnail_source_init(VipsThumbnailSource *source) * @source: source to thumbnail * @out: (out): output image * @width: target width in pixels - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: + * @...: `NULL`-terminated list of optional named arguments * - * * @height: %gint, target height in pixels - * * @size: #VipsSize, upsize, downsize, both or force - * * @no_rotate: %gboolean, don't rotate upright using orientation tag - * * @crop: #VipsInteresting, shrink and crop to fill target - * * @linear: %gboolean, perform shrink in linear light - * * @import_profile: %gchararray, fallback import ICC profile - * * @export_profile: %gchararray, export ICC profile - * * @intent: #VipsIntent, rendering intent - * * @fail_on: #VipsFailOn, load error types to fail on - * * @option_string: %gchararray, extra loader options + * Exactly as [ctor@Image.thumbnail], but read from a source. * - * Exactly as vips_thumbnail(), but read from a source. One extra + * One extra * optional argument, @option_string, lets you pass options to the underlying * loader. * - * See also: vips_thumbnail(). + * ::: tip "Optional arguments" + * * @height: `gint`, target height in pixels + * * @size: [enum@Size], upsize, downsize, both or force + * * @no_rotate: `gboolean`, don't rotate upright using orientation tag + * * @crop: [enum@Interesting], shrink and crop to fill target + * * @linear: `gboolean`, perform shrink in linear light + * * @input_profile: `gchararray`, fallback input ICC profile + * * @output_profile: `gchararray`, output ICC profile + * * @intent: [enum@Intent], rendering intent + * * @fail_on: [enum@FailOn], load error types to fail on + * * @option_string: `gchararray`, extra loader options + * + * ::: seealso + * [ctor@Image.thumbnail]. * * Returns: 0 on success, -1 on error. */ @@ -1795,28 +1816,28 @@ vips_thumbnail_image_init(VipsThumbnailImage *image) * @in: input image * @out: (out): output image * @width: target width in pixels - * @...: %NULL-terminated list of optional named arguments + * @...: `NULL`-terminated list of optional named arguments * - * Optional arguments: - * - * * @height: %gint, target height in pixels - * * @size: #VipsSize, upsize, downsize, both or force - * * @no_rotate: %gboolean, don't rotate upright using orientation tag - * * @crop: #VipsInteresting, shrink and crop to fill target - * * @linear: %gboolean, perform shrink in linear light - * * @import_profile: %gchararray, fallback import ICC profile - * * @export_profile: %gchararray, export ICC profile - * * @intent: #VipsIntent, rendering intent - * * @fail_on: #VipsFailOn, load error types to fail on - * - * Exactly as vips_thumbnail(), but read from an existing image. + * Exactly as [ctor@Image.thumbnail], but read from an existing image. * * This operation * is not able to exploit shrink-on-load features of image load libraries, so - * it can be much slower than `vips_thumbnail()` and produce poorer quality - * output. Only use it if you really have to. + * it can be much slower than [ctor@Image.thumbnail] and produce poorer quality + * output. Only use this operation if you really have to. + * + * ::: tip "Optional arguments" + * * @height: `gint`, target height in pixels + * * @size: [enum@Size], upsize, downsize, both or force + * * @no_rotate: `gboolean`, don't rotate upright using orientation tag + * * @crop: [enum@Interesting], shrink and crop to fill target + * * @linear: `gboolean`, perform shrink in linear light + * * @input_profile: `gchararray`, fallback input ICC profile + * * @output_profile: `gchararray`, output ICC profile + * * @intent: [enum@Intent], rendering intent + * * @fail_on: [enum@FailOn], load error types to fail on * - * See also: vips_thumbnail(). + * ::: seealso + * [ctor@Image.thumbnail]. * * Returns: 0 on success, -1 on error. */ diff --git a/man/vipsthumbnail.1 b/man/vipsthumbnail.1 index b14ac4f2fd..d42942018c 100644 --- a/man/vipsthumbnail.1 +++ b/man/vipsthumbnail.1 @@ -5,7 +5,7 @@ vipsthumbnail \- make thumbnails of image files .B vipsthumbnail [flags] imagefile1 imagefile2 ... .SH DESCRIPTION .B vipsthumbnail(1) -processes each +processes each .B imagefile in turn, shrinking each image to fit within a 128 by 128 pixel square. The shrunk image is written to a new file named @@ -17,9 +17,9 @@ For example: $ vipsthumbnail fred.png jim.tif -will read image files +will read image files .B fred.png -and +and .B jim.tif and write thumbnails to the files .B tn_fred.jpg @@ -30,36 +30,36 @@ and will read image file .B fred.jpg -and write a 64 x 64 pixel thumbnail to the file +and write a 64 x 64 pixel thumbnail to the file .B thumbnails/fred.png. .SH OPTIONS .TP .B -s N, --size=N -Set the output thumbnail size to -.B N -x -.B N -pixels. +Set the output thumbnail size to +.B N +x +.B N +pixels. You can use "MxN" to specify a rectangular bounding box. The image is shrunk so that it just fits within this area, images -which are smaller than this are expanded. +which are smaller than this are expanded. Use "xN" or "Mx" to just resize on -one axis. +one axis. Append "<" to only resize if the input image is smaller than the target, append ">" to only resize if the input image is larger than the target. .TP -.B -o FORMAT, --output=FORMAT +.B -o FORMAT, --output=FORMAT Set the output format string. The input filename has any file type suffix -removed, then that value is substituted into +removed, then that value is substituted into .B FORMAT replacing -.B %s. -If +.B %s. +If .B FORMAT is a relative path, the name of the input directory is prepended. In other words, any path in @@ -75,7 +75,7 @@ prepended. You can add format options too, for example will write JPEG images with Q set to 20. .TP -.B -e PROFILE, --eprofile=PROFILE +.B -e PROFILE, --eprofile=PROFILE Export thumbnails with this ICC profile. Images are only colour-transformed if there is both an output and an input profile available. The input profile can either be embedded in the input image or supplied with the @@ -83,8 +83,8 @@ either be embedded in the input image or supplied with the option. .TP -.B -i PROFILE, --iprofile=PROFILE -Import images with this ICC profile, if no profile is embedded in the image. +.B -i PROFILE, --iprofile=PROFILE +Import images with this ICC profile, if no profile is embedded in the image. Images are only colour-transformed if there is both an output and an input profile available. The output profile should be supplied with the @@ -94,20 +94,20 @@ option. .TP .B -c, --crop Crop the output image down. The image is shrunk so as to completely fill the -bounding box in both axes, then any excess is cropped off. +bounding box in both axes, then any excess is cropped off. .TP .B -d, --delete Delete the output profile from the image. This can save a small amount of -space. +space. .TP .B -t, --rotate -Auto-rotate images using EXIF orientation tags. +Auto-rotate images using EXIF orientation tags. .TP .B -a, --linear -Shrink images in linear light colour space. This can be much slower. +Shrink images in linear light colour space. This can be much slower. .SH RETURN VALUE returns 0 on success and non-zero on error. Error can mean one or more diff --git a/meson.build b/meson.build index 5f56fb9b74..19ffe04882 100644 --- a/meson.build +++ b/meson.build @@ -36,15 +36,15 @@ i18n = import('i18n') # if we're optimising (eg. release mode) we turn off cast checks and g_asserts if get_option('optimization') not in ['0', 'g'] - add_project_arguments('-DG_DISABLE_CAST_CHECKS', language : ['cpp', 'c']) - add_project_arguments('-DG_DISABLE_CHECKS', language : ['cpp', 'c']) - add_project_arguments('-DG_DISABLE_ASSERT', language : ['cpp', 'c']) + add_project_arguments('-DG_DISABLE_CAST_CHECKS', language: ['cpp', 'c']) + add_project_arguments('-DG_DISABLE_CHECKS', language: ['cpp', 'c']) + add_project_arguments('-DG_DISABLE_ASSERT', language: ['cpp', 'c']) endif # in debug mode we automatically enable leak checks # also true for 'debugoptimized' if get_option('debug') - add_project_arguments('-DDEBUG_LEAK', language : ['cpp', 'c']) + add_project_arguments('-DDEBUG_LEAK', language: ['cpp', 'c']) endif host_os = host_machine.system() @@ -52,7 +52,7 @@ cc = meson.get_compiler('c') cpp = meson.get_compiler('cpp') # Prevent use of void* pointer arithmetic to support MSVC -add_project_arguments(cc.get_supported_arguments('-Werror=pointer-arith'), language : ['cpp', 'c']) +add_project_arguments(cc.get_supported_arguments('-Werror=pointer-arith'), language: ['cpp', 'c']) # libFuzzer related things fuzzing_engine = get_option('fuzzing_engine') @@ -61,7 +61,7 @@ if fuzzing_engine == 'libfuzzer' error('fuzzing_engine libfuzzer requires "-fsanitize=fuzzer"') endif fuzzer_args = ['-fsanitize=fuzzer-no-link', '-fsanitize=fuzzer'] - add_project_arguments(cc.first_supported_argument(fuzzer_args), language : ['cpp', 'c']) + add_project_arguments(cc.first_supported_argument(fuzzer_args), language: ['cpp', 'c']) endif glib_dep = dependency('glib-2.0', version: '>=2.52') @@ -115,9 +115,7 @@ module_dir = lib_dir / 'vips-modules-@0@.@1@'.format(version_major, version_mino cfg_var = configuration_data() cfg_var.set_quoted('G_LOG_DOMAIN', 'VIPS') -if modules_enabled - cfg_var.set('ENABLE_MODULES', '1') -endif +cfg_var.set('ENABLE_MODULES', modules_enabled) # Detect and set symbol visibility if get_option('default_library') == 'shared' and host_os in ['windows', 'cygwin'] @@ -152,10 +150,9 @@ h( v4f B ) } ''' -if cpp.compiles(vector_arithmetic_check, name: 'Has vector arithmetic', dependencies: m_dep) and \ - cpp.compiles(signed_constants_check, name: 'Has signed constants in vector templates', dependencies: m_dep) - cfg_var.set('HAVE_VECTOR_ARITH', '1') -endif +have_vector_artih = cpp.compiles(vector_arithmetic_check, name: 'Has vector arithmetic', dependencies: m_dep) and \ + cpp.compiles(signed_constants_check, name: 'Has signed constants in vector templates', dependencies: m_dep) +cfg_var.set('HAVE_VECTOR_ARITH', have_vector_artih) # HAVE_TARGET_CLONES target_clones_check = ''' @@ -175,38 +172,32 @@ if meson.can_run_host_binaries() else have_target_clones = cc.links(target_clones_check, args: '-Werror', name: 'Has target_clones attribute') endif -if have_target_clones - cfg_var.set('HAVE_TARGET_CLONES', '1') -endif +cfg_var.set('HAVE_TARGET_CLONES', have_target_clones) func_names = [ '_aligned_malloc', 'posix_memalign', 'memalign' ] foreach func_name : func_names - if cc.has_function(func_name) - cfg_var.set('HAVE_' + func_name.to_upper(), '1') - endif + cfg_var.set('HAVE_' + func_name.to_upper(), cc.has_function(func_name)) endforeach -if cc.has_function('pthread_setattr_default_np', args: '-D_GNU_SOURCE', prefix: '#include ', dependencies: thread_dep) - cfg_var.set('HAVE_PTHREAD_DEFAULT_NP', '1') -endif +cfg_var.set('HAVE_PTHREAD_DEFAULT_NP', cc.has_function('pthread_setattr_default_np', args: '-D_GNU_SOURCE', prefix: '#include ', dependencies: thread_dep)) # needed by rsvg and others zlib_dep = dependency('zlib', version: '>=0.4', required: get_option('zlib')) if zlib_dep.found() external_deps += zlib_dep - cfg_var.set('HAVE_ZLIB', '1') + cfg_var.set('HAVE_ZLIB', true) endif libarchive_dep = dependency('libarchive', version: '>=3.0.0', required: get_option('archive')) if libarchive_dep.found() external_deps += libarchive_dep - cfg_var.set('HAVE_LIBARCHIVE', '1') + cfg_var.set('HAVE_LIBARCHIVE', true) endif fftw_dep = dependency('fftw3', required: get_option('fftw')) if fftw_dep.found() external_deps += fftw_dep - cfg_var.set('HAVE_FFTW', '1') + cfg_var.set('HAVE_FFTW', true) endif # TODO: simplify this when requiring meson>=0.60.0 @@ -220,7 +211,7 @@ magick_module = false if magick_found magick_module = modules_enabled and not get_option('magick-module').disabled() if magick_module - cfg_var.set('MAGICK_MODULE', '1') + cfg_var.set('MAGICK_MODULE', true) module_deps += magick_dep else external_deps += magick_dep @@ -231,50 +222,37 @@ if magick_found # GM uses magick_include = magick7 ? '#include ' : '#include ' if magick7 - cfg_var.set('HAVE_MAGICK7', '1') + cfg_var.set('HAVE_MAGICK7', true) else # come here for imagemagick6, and graphicsmagick1.x, which also uses # the im6 API - cfg_var.set('HAVE_MAGICK6', '1') - if cc.has_member('struct _ImageInfo', 'number_scenes', prefix: magick_include, dependencies: magick_dep) - cfg_var.set('HAVE_NUMBER_SCENES', '1') - endif + cfg_var.set('HAVE_MAGICK6', true) + cfg_var.set('HAVE_NUMBER_SCENES', cc.has_member('struct _ImageInfo', 'number_scenes', prefix: magick_include, dependencies: magick_dep)) func_names = [ 'InheritException', 'AcquireExceptionInfo', 'SetImageProperty', 'SetImageExtent', 'AcquireImage', 'GetVirtualPixels', 'ResetImageProfileIterator', 'ResetImageAttributeIterator', 'ResetImagePropertyIterator', 'MagickCoreGenesis', 'SetImageOption', 'BlobToStringInfo', 'OptimizePlusImageLayers', 'OptimizeImageTransparency', 'GetMagicInfo' ] foreach func_name : func_names - if cc.has_function(func_name, prefix: magick_include, dependencies: magick_dep) - cfg_var.set('HAVE_' + func_name.to_upper(), '1') - endif + cfg_var.set('HAVE_' + func_name.to_upper(), cc.has_function(func_name, prefix: magick_include, dependencies: magick_dep)) endforeach - if cc.compiles(magick_include + '\nColorspaceType colorspace = CMYColorspace;', name: 'Has CMYColorspace', dependencies: magick_dep) - cfg_var.set('HAVE_CMYCOLORSPACE', '1') - endif - if cc.compiles(magick_include + '\nColorspaceType colorspace = HCLpColorspace;', name: 'Has HCLpColorspace', dependencies: magick_dep) - cfg_var.set('HAVE_HCLPCOLORSPACE', '1') - endif + cfg_var.set('HAVE_CMYCOLORSPACE', cc.compiles(magick_include + '\nColorspaceType colorspace = CMYColorspace;', name: 'Has CMYColorspace', dependencies: magick_dep)) + cfg_var.set('HAVE_HCLPCOLORSPACE', cc.compiles(magick_include + '\nColorspaceType colorspace = HCLpColorspace;', name: 'Has HCLpColorspace', dependencies: magick_dep)) # GetImageMagick() takes two args under GM, three under IM - if cc.compiles(magick_include + '\nint main() {(void)GetImageMagick(NULL, 0, NULL);}', name: 'GetImageMagick takes three arguments', dependencies: magick_dep) - cfg_var.set('HAVE_GETIMAGEMAGICK3', '1') - endif + cfg_var.set('HAVE_GETIMAGEMAGICK3', cc.compiles(magick_include + '\nint main() {(void)GetImageMagick(NULL, 0, NULL);}', name: 'GetImageMagick takes three arguments', dependencies: magick_dep)) endif - if 'load' in get_option('magick-features') - cfg_var.set('ENABLE_MAGICKLOAD', '1') - endif + magick_features = [ 'load', 'save' ] + foreach feature : magick_features + cfg_var.set('ENABLE_MAGICK' + feature.to_upper(), feature in get_option('magick-features')) + endforeach + if 'save' in get_option('magick-features') - cfg_var.set('ENABLE_MAGICKSAVE', '1') - if cc.has_function('ImportImagePixels', prefix: magick_include, dependencies: magick_dep) - cfg_var.set('HAVE_IMPORTIMAGEPIXELS', '1') - endif - if cc.has_function('ImagesToBlob', prefix: magick_include, dependencies: magick_dep) - cfg_var.set('HAVE_IMAGESTOBLOB', '1') - endif + cfg_var.set('HAVE_IMPORTIMAGEPIXELS', cc.has_function('ImportImagePixels', prefix: magick_include, dependencies: magick_dep)) + cfg_var.set('HAVE_IMAGESTOBLOB', cc.has_function('ImagesToBlob', prefix: magick_include, dependencies: magick_dep)) endif endif cfitsio_dep = dependency('cfitsio', required: get_option('cfitsio')) if cfitsio_dep.found() external_deps += cfitsio_dep - cfg_var.set('HAVE_CFITSIO', '1') + cfg_var.set('HAVE_CFITSIO', true) endif # quant package we use @@ -283,7 +261,7 @@ quantisation_package = disabler() imagequant_dep = dependency('imagequant', required: get_option('imagequant')) if imagequant_dep.found() external_deps += imagequant_dep - cfg_var.set('HAVE_IMAGEQUANT', '1') + cfg_var.set('HAVE_IMAGEQUANT', true) quantisation_package = imagequant_dep endif @@ -293,7 +271,7 @@ if not quantisation_package.found() quantizr_dep = dependency('quantizr', required: get_option('quantizr')) if quantizr_dep.found() external_deps += quantizr_dep - cfg_var.set('HAVE_QUANTIZR', '1') + cfg_var.set('HAVE_QUANTIZR', true) quantisation_package = quantizr_dep endif endif @@ -303,49 +281,35 @@ if quantisation_package.found() cgif_dep = dependency('cgif', version: '>=0.2.0', required: get_option('cgif')) if cgif_dep.found() external_deps += cgif_dep - cfg_var.set('HAVE_CGIF', '1') - if cc.compiles('#include \nint i = CGIF_ATTR_NO_LOOP;', name: 'Has CGIF_ATTR_NO_LOOP', dependencies: cgif_dep) - cfg_var.set('HAVE_CGIF_ATTR_NO_LOOP', '1') - endif - if cc.compiles('#include \nint i = CGIF_FRAME_ATTR_INTERLACED;', name: 'Has CGIF_FRAME_ATTR_INTERLACED', dependencies: cgif_dep) - cfg_var.set('HAVE_CGIF_FRAME_ATTR_INTERLACED', '1') - endif - if cc.compiles('#include \nint i = CGIF_GEN_KEEP_IDENT_FRAMES;', name: 'Has CGIF_GEN_KEEP_IDENT_FRAMES', dependencies: cgif_dep) - cfg_var.set('HAVE_CGIF_GEN_KEEP_IDENT_FRAMES', '1') - endif + cfg_var.set('HAVE_CGIF', true) + cfg_var.set('HAVE_CGIF_ATTR_NO_LOOP', cc.get_define('CGIF_ATTR_NO_LOOP', prefix: '#include ', dependencies: cgif_dep) != '') + cfg_var.set('HAVE_CGIF_FRAME_ATTR_INTERLACED', cc.get_define('CGIF_FRAME_ATTR_INTERLACED', prefix: '#include ', dependencies: cgif_dep) != '') + cfg_var.set('HAVE_CGIF_GEN_KEEP_IDENT_FRAMES', cc.get_define('CGIF_GEN_KEEP_IDENT_FRAMES', prefix: '#include ', dependencies: cgif_dep) != '') endif endif libexif_dep = dependency('libexif', version: '>=0.6', required: get_option('exif')) if libexif_dep.found() external_deps += libexif_dep - cfg_var.set('HAVE_EXIF', '1') + cfg_var.set('HAVE_EXIF', true) # some libexif packages need include , some just # how annoying - if cc.has_header('exif-data.h', dependencies: libexif_dep) - # libexif includes don't need libexif prefix - cfg_var.set('UNTAGGED_EXIF', '1') - endif + # libexif includes don't need libexif prefix + cfg_var.set('UNTAGGED_EXIF', cc.has_header('exif-data.h', dependencies: libexif_dep)) # 0.6.22 adds a couple of EXIF 2.3 ASCII tags - if libexif_dep.version().version_compare('>=0.6.22') - cfg_var.set('HAVE_EXIF_0_6_22', '1') - endif + cfg_var.set('HAVE_EXIF_0_6_22', libexif_dep.version().version_compare('>=0.6.22')) # 0.6.23 adds some OffsetTime* and GPS* ASCII tags - if libexif_dep.version().version_compare('>=0.6.23') - cfg_var.set('HAVE_EXIF_0_6_23', '1') - endif + cfg_var.set('HAVE_EXIF_0_6_23', libexif_dep.version().version_compare('>=0.6.23')) endif libjpeg_dep = dependency('libjpeg', required: get_option('jpeg')) if libjpeg_dep.found() external_deps += libjpeg_dep - cfg_var.set('HAVE_JPEG', '1') + cfg_var.set('HAVE_JPEG', true) # features like trellis quant are exposed as extension parameters ... # mozjpeg 3.2 and later have #define JPEG_C_PARAM_SUPPORTED, but we must # work with earlier versions - if cc.has_function('jpeg_c_bool_param_supported', prefix: '#include \n#include ', dependencies: libjpeg_dep) - cfg_var.set('HAVE_JPEG_EXT_PARAMS', '1') - endif + cfg_var.set('HAVE_JPEG_EXT_PARAMS', cc.has_function('jpeg_c_bool_param_supported', prefix: '#include \n#include ', dependencies: libjpeg_dep)) endif # png package we use @@ -362,7 +326,7 @@ if not spng_dep.found() endif if not get_option('spng').disabled() and spng_dep.found() external_deps += spng_dep - cfg_var.set('HAVE_SPNG', '1') + cfg_var.set('HAVE_SPNG', true) png_package = spng_dep endif @@ -371,10 +335,8 @@ if not png_package.found() png_dep = dependency('libpng', version: '>=1.2.9', required: get_option('png')) if png_dep.found() external_deps += png_dep - cfg_var.set('HAVE_PNG', '1') - if cc.has_function('png_set_chunk_malloc_max', prefix: '#include ', dependencies: png_dep) - cfg_var.set('HAVE_PNG_SET_CHUNK_MALLOC_MAX', '1') - endif + cfg_var.set('HAVE_PNG', true) + cfg_var.set('HAVE_PNG_SET_CHUNK_MALLOC_MAX', cc.has_function('png_set_chunk_malloc_max', prefix: '#include ', dependencies: png_dep)) png_package = png_dep endif endif @@ -387,13 +349,13 @@ if libwebp_dep.found() external_deps += libwebp_dep external_deps += dependency('libwebpmux', version: '>=0.6') external_deps += dependency('libwebpdemux', version: '>=0.6') - cfg_var.set('HAVE_LIBWEBP', '1') + cfg_var.set('HAVE_LIBWEBP', true) endif pangocairo_dep = dependency('pangocairo', version: '>=1.32.6', required: get_option('pangocairo')) if pangocairo_dep.found() external_deps += pangocairo_dep - cfg_var.set('HAVE_PANGOCAIRO', '1') + cfg_var.set('HAVE_PANGOCAIRO', true) endif # text rendering with fontconfig requires pangoft2 @@ -403,17 +365,19 @@ fontconfig_found = pangoft2_dep.found() and fontconfig_dep.found() and pangocair if fontconfig_found external_deps += pangoft2_dep external_deps += fontconfig_dep - cfg_var.set('HAVE_FONTCONFIG', '1') + cfg_var.set('HAVE_FONTCONFIG', true) endif libtiff_dep = dependency('libtiff-4', required: get_option('tiff')) if libtiff_dep.found() external_deps += libtiff_dep - cfg_var.set('HAVE_TIFF', '1') + cfg_var.set('HAVE_TIFF', true) # ZSTD and WEBP in TIFF added in libtiff 4.0.10 - if cc.get_define('COMPRESSION_WEBP', prefix: '#include ', dependencies: libtiff_dep) != '' - cfg_var.set('HAVE_TIFF_COMPRESSION_WEBP', '1') - endif + cfg_var.set('HAVE_TIFF_COMPRESSION_WEBP', cc.get_define('COMPRESSION_WEBP', prefix: '#include ', dependencies: libtiff_dep) != '') + # TIFFOpenOptions added in libtiff 4.5.0 + cfg_var.set('HAVE_TIFF_OPEN_OPTIONS', cc.has_function('TIFFOpenOptionsAlloc', prefix: '#include ', dependencies: libtiff_dep)) + # TIFFOpenOptionsSetMaxCumulatedMemAlloc added in libtiff 4.7.0 + cfg_var.set('HAVE_TIFF_OPEN_OPTIONS_SET_MAX_CUMULATED_MEM_ALLOC', cc.has_function('TIFFOpenOptionsSetMaxCumulatedMemAlloc', prefix: '#include ', dependencies: libtiff_dep)) endif # 2.40.3 so we get the UNLIMITED open flag @@ -423,54 +387,51 @@ librsvg_found = librsvg_dep.found() and cairo_dep.found() if librsvg_found external_deps += librsvg_dep external_deps += cairo_dep - cfg_var.set('HAVE_RSVG', '1') + cfg_var.set('HAVE_RSVG', true) + # rsvg_handle_set_stylesheet added in librsvg 2.48.0 + cfg_var.set('HAVE_RSVG_HANDLE_SET_STYLESHEET', cc.has_function('rsvg_handle_set_stylesheet', dependencies: librsvg_dep)) endif -openslide_dep = dependency('openslide', version: '>=3.3.0', required: get_option('openslide')) +openslide_dep = dependency('openslide', version: '>=3.4.0', required: get_option('openslide')) openslide_module = false if openslide_dep.found() openslide_module = modules_enabled and not get_option('openslide-module').disabled() if openslide_module - cfg_var.set('OPENSLIDE_MODULE', '1') + cfg_var.set('OPENSLIDE_MODULE', true) module_deps += openslide_dep else external_deps += openslide_dep endif - cfg_var.set('HAVE_OPENSLIDE', '1') - if openslide_dep.version().version_compare('>=3.4.0') - cfg_var.set('HAVE_OPENSLIDE_3_4', '1') - endif - - if cc.has_function('openslide_get_icc_profile_size', dependencies: openslide_dep) - cfg_var.set('HAVE_OPENSLIDE_ICC', '1') - endif + cfg_var.set('HAVE_OPENSLIDE', true) + cfg_var.set('HAVE_OPENSLIDE_ICC', cc.has_function('openslide_get_icc_profile_size', dependencies: openslide_dep)) + cfg_var.set('HAVE_OPENSLIDE_CACHE_CREATE', cc.has_function('openslide_cache_create', dependencies: openslide_dep)) endif matio_dep = dependency('matio', required: get_option('matio')) if matio_dep.found() external_deps += matio_dep - cfg_var.set('HAVE_MATIO', '1') + cfg_var.set('HAVE_MATIO', true) endif # lcms ... refuse to use lcms1 lcms_dep = dependency('lcms2', required: get_option('lcms')) if lcms_dep.found() external_deps += lcms_dep - cfg_var.set('HAVE_LCMS2', '1') + cfg_var.set('HAVE_LCMS2', true) endif # require 1.2.2 since 1.2.1 has a broken ImfCloseTiledInputFile() openexr_dep = dependency('OpenEXR', version: '>=1.2.2', required: get_option('openexr')) if openexr_dep.found() external_deps += openexr_dep - cfg_var.set('HAVE_OPENEXR', '1') + cfg_var.set('HAVE_OPENEXR', true) endif # 2.4 is the first one to have working threading and tiling libopenjp2_dep = dependency('libopenjp2', version: '>=2.4', required: get_option('openjpeg')) if libopenjp2_dep.found() external_deps += libopenjp2_dep - cfg_var.set('HAVE_LIBOPENJP2', '1') + cfg_var.set('HAVE_LIBOPENJP2', true) endif # simd package we use @@ -481,11 +442,9 @@ simd_package = disabler() libhwy_dep = dependency('libhwy', version: '>=1.0.5', required: get_option('highway')) if libhwy_dep.found() external_deps += libhwy_dep - cfg_var.set('HAVE_HWY', '1') + cfg_var.set('HAVE_HWY', true) # 1.1.0 adds `InterleaveWhole{Lower,Upper}` and `Dup128VecFromValues` - if libhwy_dep.version().version_compare('>=1.1.0') - cfg_var.set('HAVE_HWY_1_1_0', '1') - endif + cfg_var.set('HAVE_HWY_1_1_0', libhwy_dep.version().version_compare('>=1.1.0')) # Always disable SSSE3 since it is rare to have SSSE3 but not SSE4 disabled_targets = ['HWY_SSSE3'] # Optionally, build without AVX512 support (helps to reduce binary size at the cost of performance) @@ -502,12 +461,10 @@ if not simd_package.found() orc_dep = dependency('orc-0.4', version: '>=0.4.11', required: get_option('orc')) if orc_dep.found() external_deps += orc_dep - cfg_var.set('HAVE_ORC', '1') + cfg_var.set('HAVE_ORC', true) # 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 orc_dep.version().version_compare('>=0.4.31') - cfg_var.set('HAVE_ORC_CF_PROTECTION', '1') - endif + cfg_var.set('HAVE_ORC_CF_PROTECTION', orc_dep.version().version_compare('>=0.4.31')) simd_package = orc_dep endif endif @@ -520,7 +477,7 @@ pdf_loader = disabler() pdfium_dep = dependency('pdfium', version: '>=4200', required: get_option('pdfium')) if pdfium_dep.found() external_deps += pdfium_dep - cfg_var.set('HAVE_PDFIUM', '1') + cfg_var.set('HAVE_PDFIUM', true) pdf_loader = pdfium_dep endif @@ -529,68 +486,50 @@ libheif_module = false if libheif_dep.found() libheif_module = modules_enabled and not get_option('heif-module').disabled() if libheif_module - cfg_var.set('HEIF_MODULE', '1') + cfg_var.set('HEIF_MODULE', true) module_deps += libheif_dep else external_deps += libheif_dep endif - cfg_var.set('HAVE_HEIF', '1') + cfg_var.set('HAVE_HEIF', true) # added in 1.6.0 - if cpp.has_function('heif_image_handle_get_raw_color_profile', prefix: '#include ', dependencies: libheif_dep) - cfg_var.set('HAVE_HEIF_COLOR_PROFILE', '1') - endif - if cpp.has_function('heif_context_set_maximum_image_size_limit', prefix: '#include ', dependencies: libheif_dep) - cfg_var.set('HAVE_HEIF_SET_MAX_IMAGE_SIZE_LIMIT', '1') - endif + cfg_var.set('HAVE_HEIF_COLOR_PROFILE', cpp.has_function('heif_image_handle_get_raw_color_profile', prefix: '#include ', dependencies: libheif_dep)) + cfg_var.set('HAVE_HEIF_SET_MAX_IMAGE_SIZE_LIMIT', cpp.has_function('heif_context_set_maximum_image_size_limit', prefix: '#include ', dependencies: libheif_dep)) # added in 1.7.0 - if cpp.has_member('struct heif_decoding_options', 'convert_hdr_to_8bit', prefix: '#include ', dependencies: libheif_dep) - cfg_var.set('HAVE_HEIF_DECODING_OPTIONS_CONVERT_HDR_TO_8BIT', '1') - endif + cfg_var.set('HAVE_HEIF_DECODING_OPTIONS_CONVERT_HDR_TO_8BIT', cpp.has_member('struct heif_decoding_options', 'convert_hdr_to_8bit', prefix: '#include ', dependencies: libheif_dep)) # heif_main_brand added in 1.4.0, but heif_avif appeared in 1.7 ... just check # the libheif version number since testing for enums is annoying - if libheif_dep.version().version_compare('>=1.7.0') - cfg_var.set('HAVE_HEIF_AVIF', '1') - endif + cfg_var.set('HAVE_HEIF_AVIF', libheif_dep.version().version_compare('>=1.7.0')) # added in 1.10.0 - if cpp.has_function('heif_encoder_parameter_get_valid_integer_values', prefix: '#include ', dependencies: libheif_dep) - cfg_var.set('HAVE_HEIF_ENCODER_PARAMETER_GET_VALID_INTEGER_VALUES', '1') - endif + cfg_var.set('HAVE_HEIF_ENCODER_PARAMETER_GET_VALID_INTEGER_VALUES', cpp.has_function('heif_encoder_parameter_get_valid_integer_values', prefix: '#include ', dependencies: libheif_dep)) # added in 1.11.0 - if cpp.has_member('struct heif_encoding_options', 'output_nclx_profile', prefix: '#include ', dependencies: libheif_dep) - cfg_var.set('HAVE_HEIF_ENCODING_OPTIONS_OUTPUT_NCLX_PROFILE', '1') - endif - + cfg_var.set('HAVE_HEIF_ENCODING_OPTIONS_OUTPUT_NCLX_PROFILE', cpp.has_member('struct heif_encoding_options', 'output_nclx_profile', prefix: '#include ', dependencies: libheif_dep)) # heif_init added in 1.13.0 - if libheif_dep.version().version_compare('>=1.13.0') - cfg_var.set('HAVE_HEIF_INIT', '1') - endif + cfg_var.set('HAVE_HEIF_INIT', libheif_dep.version().version_compare('>=1.13.0')) + # heif_encoding_options.image_orientation added in 1.14.0 + cfg_var.set('HAVE_HEIF_ENCODING_OPTIONS_IMAGE_ORIENTATION', cpp.has_member('struct heif_encoding_options', 'image_orientation', prefix: '#include ', dependencies: libheif_dep)) # heif_error_success added in 1.17.0 - if libheif_dep.version().version_compare('>=1.17.0') - cfg_var.set('HAVE_HEIF_ERROR_SUCCESS', '1') - endif + cfg_var.set('HAVE_HEIF_ERROR_SUCCESS', libheif_dep.version().version_compare('>=1.17.0')) + # heif_get_disabled_security_limits added in 1.19.0 + cfg_var.set('HAVE_HEIF_GET_DISABLED_SECURITY_LIMITS', cpp.has_function('heif_get_disabled_security_limits', prefix: '#include ', dependencies: libheif_dep)) endif -libjxl_dep = dependency('libjxl', version: '>=0.6', required: get_option('jpeg-xl')) -libjxl_threads_dep = dependency('libjxl_threads', version: '>=0.6', required: get_option('jpeg-xl')) +# need v0.11+ for chunked write +libjxl_dep = dependency('libjxl', version: '>=0.11', required: get_option('jpeg-xl')) +libjxl_threads_dep = dependency('libjxl_threads', version: '>=0.11', required: get_option('jpeg-xl')) libjxl_found = libjxl_dep.found() and libjxl_threads_dep.found() libjxl_module = false if libjxl_found libjxl_module = modules_enabled and not get_option('jpeg-xl-module').disabled() if libjxl_module - cfg_var.set('LIBJXL_MODULE', '1') + cfg_var.set('LIBJXL_MODULE', true) module_deps += libjxl_dep module_deps += libjxl_threads_dep else external_deps += libjxl_dep external_deps += libjxl_threads_dep endif - cfg_var.set('HAVE_LIBJXL', '1') - if libjxl_dep.version().version_compare('>=0.7') - cfg_var.set('HAVE_LIBJXL_0_7', '1') - endif - if libjxl_dep.version().version_compare('>=0.9') - cfg_var.set('HAVE_LIBJXL_0_9', '1') - endif + cfg_var.set('HAVE_LIBJXL', true) endif # only if pdfium not found @@ -603,14 +542,14 @@ if not pdf_loader.found() if libpoppler_dep.found() and cairo_dep.found() libpoppler_module = modules_enabled and not get_option('poppler-module').disabled() if libpoppler_module - cfg_var.set('POPPLER_MODULE', '1') + cfg_var.set('POPPLER_MODULE', true) module_deps += libpoppler_dep module_deps += cairo_dep else external_deps += libpoppler_dep external_deps += cairo_dep endif - cfg_var.set('HAVE_POPPLER', '1') + cfg_var.set('HAVE_POPPLER', true) pdf_loader = libpoppler_dep endif endif @@ -653,55 +592,32 @@ endif libnifti_found = not get_option('nifti').disabled() and libnifti_dep.found() if libnifti_found external_deps += libnifti_dep - cfg_var.set('HAVE_NIFTI', '1') + cfg_var.set('HAVE_NIFTI', true) endif -if cc.has_header('sys/file.h') - cfg_var.set('HAVE_SYS_FILE_H', '1') -endif -if cc.has_header('sys/param.h') - cfg_var.set('HAVE_SYS_PARAM_H', '1') -endif -if cc.has_header('sys/mman.h') - cfg_var.set('HAVE_SYS_MMAN_H', '1') -endif -if cc.has_header('unistd.h') - cfg_var.set('HAVE_UNISTD_H', '1') -endif -if cc.has_header('io.h') - cfg_var.set('HAVE_IO_H', '1') -endif -if cc.has_header('direct.h') - cfg_var.set('HAVE_DIRECT_H', '1') -endif -if get_option('deprecated') - cfg_var.set('ENABLE_DEPRECATED', '1') -endif -if get_option('nsgif') - cfg_var.set('HAVE_NSGIF', '1') -endif -if get_option('ppm') - cfg_var.set('HAVE_PPM', '1') -endif -if get_option('analyze') - cfg_var.set('HAVE_ANALYZE', '1') -endif -if get_option('radiance') - cfg_var.set('HAVE_RADIANCE', '1') -endif +headers = [ 'sys/file.h', 'sys/param.h', 'sys/mman.h', 'unistd.h', 'io.h', 'direct.h' ] +foreach name : headers + cfg_var.set('HAVE_' + name.underscorify().to_upper(), cc.has_header(name)) +endforeach + +cfg_var.set('ENABLE_DEPRECATED', get_option('deprecated')) +cfg_var.set('HAVE_NSGIF', get_option('nsgif')) +cfg_var.set('HAVE_PPM', get_option('ppm')) +cfg_var.set('HAVE_ANALYZE', get_option('analyze')) +cfg_var.set('HAVE_RADIANCE', get_option('radiance')) gettext_domain = 'vips@0@.@1@'.format(version_major, version_minor) cfg_var.set_quoted('GETTEXT_PACKAGE', gettext_domain) cfg_var.set_quoted('VIPS_PREFIX', prefix_dir) cfg_var.set_quoted('VIPS_LIBDIR', lib_dir) if cc.has_function('ngettext') - cfg_var.set('ENABLE_NLS', 1) + cfg_var.set('ENABLE_NLS', true) have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset') else libintl_dep = cc.find_library('intl', required: false) if libintl_dep.found() other_deps += libintl_dep - cfg_var.set('ENABLE_NLS', 1) + cfg_var.set('ENABLE_NLS', true) have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset', prefix: '#include ', dependencies: libintl_dep) else have_bind_textdomain_codeset = false @@ -729,7 +645,7 @@ config_file = configure_file( config_dep = declare_dependency( sources: config_file, include_directories: include_directories('.'), - compile_args: '-DHAVE_CONFIG_H=1', + compile_args: '-DHAVE_CONFIG_H', ) libvips_deps = [config_dep] + external_deps + other_deps @@ -742,11 +658,11 @@ build_summary = { {'enable debug': [get_option('debug')], 'enable deprecated': [get_option('deprecated')], 'enable modules': [modules_enabled], - 'enable gtk-doc': [get_option('gtk_doc')], - 'enable doxygen': [get_option('doxygen')], + 'enable docs': [get_option('docs')], + 'enable C++ docs': [get_option('cpp-docs')], 'enable introspection': [enable_introspection], 'enable examples': [get_option('examples')], - 'enable cplusplus': [get_option('cplusplus')], + 'enable C++ binding': [get_option('cplusplus')], 'enable RAD load/save': [get_option('radiance')], 'enable Analyze7 load': [get_option('analyze')], 'enable PPM load/save': [get_option('ppm')], @@ -810,8 +726,8 @@ foreach section_title, section: build_features endforeach subdir('libvips') -if get_option('gtk_doc') - subdir('doc') +if get_option('docs') + subdir('doc') endif if get_option('examples') subdir('examples') diff --git a/meson_options.txt b/meson_options.txt index 76ba6f7ced..175a46c5e6 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -15,15 +15,15 @@ option('cplusplus', value: true, description: 'Build C++ API') -option('doxygen', +option('cpp-docs', type: 'boolean', value: false, - description: 'Build C++ documentation') + description: 'Build C++ documentation (requires doxygen)') -option('gtk_doc', +option('docs', type: 'boolean', value: false, - description: 'Build GTK-doc documentation') + description: 'Build API reference and tools documentation (requires gi-docgen)') option('modules', type: 'feature', diff --git a/po/POTFILES.in b/po/POTFILES.in index 56edc92bb2..b6e0bbd415 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -249,7 +249,6 @@ libvips/foreign/jpegload.c libvips/foreign/jpegsave.c libvips/foreign/jxlload.c libvips/foreign/jxlsave.c -libvips/foreign/magick2vips.c libvips/foreign/magick6load.c libvips/foreign/magick7load.c libvips/foreign/magick.c @@ -264,6 +263,7 @@ libvips/foreign/niftisave.c libvips/foreign/nsgifload.c libvips/foreign/openexr2vips.c libvips/foreign/openexrload.c +libvips/foreign/openslideconnection.c libvips/foreign/openslideload.c libvips/foreign/pdf.c libvips/foreign/pdfiumload.c @@ -377,6 +377,7 @@ libvips/mosaicing/lrmerge.c libvips/mosaicing/lrmosaic.c libvips/mosaicing/match.c libvips/mosaicing/matrixinvert.c +libvips/mosaicing/matrixmultiply.c libvips/mosaicing/merge.c libvips/mosaicing/mosaic1.c libvips/mosaicing/mosaic.c @@ -400,7 +401,9 @@ libvips/resample/resample.c libvips/resample/resize.c libvips/resample/shrink.c libvips/resample/shrinkh.c +libvips/resample/shrinkh_hwy.cpp libvips/resample/shrinkv.c +libvips/resample/shrinkv_hwy.cpp libvips/resample/similarity.c libvips/resample/thumbnail.c libvips/resample/transform.c diff --git a/po/de.po b/po/de.po index a42e64f172..abc4bcbb58 100644 --- a/po/de.po +++ b/po/de.po @@ -7,9 +7,8 @@ # msgid "" msgstr "" -"Project-Id-Version: libvips-doc 7.36.5-1\n" -"Report-Msgid-Bugs-To: VIPSIP@JISCMAIL.AC.UK\n" -"POT-Creation-Date: 2012-03-08 21:02+0000\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-01-30 14:51+0000\n" "PO-Revision-Date: 2014-03-12 21:58+0100\n" "Last-Translator: Chris Leick \n" "Language-Team: Debian German \n" @@ -19,3478 +18,8796 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: libvips/arithmetic/abs.c:215 # http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650& # db=man&fname=/usr/share/catman/p_man/cat3/il_c/ilAbsImg.z +#: libvips/arithmetic/abs.c:200 msgid "absolute value of an image" msgstr "absoluter Wert eines Bildes" -#: libvips/arithmetic/statistic.c:147 -msgid "VIPS statistic operations" -msgstr "statistische VIPS-Transaktionen" +#: libvips/arithmetic/add.c:178 +msgid "add two images" +msgstr "zwei Bilder hinzufügen" -#: libvips/arithmetic/statistic.c:151 libvips/arithmetic/unary.c:87 -#: libvips/conversion/bandmean.c:197 libvips/conversion/cast.c:474 -#: libvips/conversion/tilecache.c:422 libvips/conversion/extract.c:194 -#: libvips/conversion/extract.c:353 libvips/conversion/embed.c:516 -#: libvips/conversion/rot.c:355 libvips/conversion/flip.c:240 -#: libvips/conversion/copy.c:318 libvips/conversion/recomb.c:200 -#: libvips/conversion/replicate.c:196 libvips/conversion/cache.c:106 -#: libvips/conversion/bandjoin.c:171 libvips/foreign/foreign.c:1379 -msgid "Input" -msgstr "Eingabe" +#: libvips/arithmetic/arithmetic.c:392 +#, c-format +msgid "not one band or %d bands" +msgstr "nicht ein Band oder %d Bänder" -#: libvips/arithmetic/statistic.c:152 libvips/conversion/cast.c:475 -#: libvips/conversion/tilecache.c:423 libvips/conversion/extract.c:195 -#: libvips/conversion/extract.c:354 libvips/conversion/embed.c:517 -#: libvips/conversion/rot.c:356 libvips/conversion/flip.c:241 -#: libvips/conversion/copy.c:319 libvips/conversion/replicate.c:197 -#: libvips/conversion/cache.c:107 -msgid "Input image" -msgstr "Eingabebild" +#: libvips/arithmetic/arithmetic.c:397 libvips/foreign/spngsave.c:423 +msgid "bad bands" +msgstr "falsche Bänder" -#: libvips/arithmetic/im_point_bilinear.c:74 -msgid "coords outside image" -msgstr "Koordinaten außerhalb des Bildes" +#: libvips/arithmetic/arithmetic.c:725 +msgid "arithmetic operations" +msgstr "arithmetische Transaktionen" -#. Name -#: libvips/arithmetic/arith_dispatch.c:298 -msgid "absolute value" -msgstr "absoluter Wert" +#: libvips/arithmetic/arithmetic.c:731 libvips/arithmetic/avg.c:235 +#: libvips/arithmetic/deviate.c:237 libvips/arithmetic/hist_find.c:431 +#: libvips/arithmetic/hist_find_indexed.c:475 +#: libvips/arithmetic/hist_find_ndim.c:313 libvips/arithmetic/hough.c:179 +#: libvips/arithmetic/max.c:452 libvips/arithmetic/measure.c:201 +#: libvips/arithmetic/min.c:452 libvips/arithmetic/stats.c:442 +#: libvips/colour/CMYK2XYZ.c:126 libvips/colour/colour.c:415 +#: libvips/colour/colourspace.c:563 libvips/colour/scRGB2BW.c:243 +#: libvips/colour/scRGB2sRGB.c:276 libvips/colour/scRGB2XYZ.c:197 +#: libvips/colour/sRGB2scRGB.c:294 libvips/colour/XYZ2CMYK.c:125 +#: libvips/colour/XYZ2scRGB.c:206 libvips/conversion/conversion.c:346 +#: libvips/conversion/switch.c:202 libvips/convolution/canny.c:448 +#: libvips/convolution/convolution.c:134 libvips/convolution/correlation.c:162 +#: libvips/convolution/edge.c:223 libvips/convolution/gaussblur.c:138 +#: libvips/convolution/sharpen.c:328 libvips/create/create.c:124 +#: libvips/foreign/foreign.c:1215 libvips/freqfilt/freqfilt.c:104 +#: libvips/histogram/case.c:252 libvips/histogram/hist_entropy.c:117 +#: libvips/histogram/hist_equal.c:120 libvips/histogram/hist_local.c:367 +#: libvips/histogram/hist_norm.c:147 libvips/histogram/histogram.c:232 +#: libvips/histogram/hist_plot.c:339 libvips/histogram/maplut.c:750 +#: libvips/histogram/stdif.c:300 libvips/iofuncs/system.c:284 +#: libvips/morphology/morph.c:959 libvips/morphology/rank.c:564 +#: libvips/mosaicing/global_balance.c:1930 libvips/mosaicing/match.c:208 +#: libvips/mosaicing/matrixinvert.c:449 libvips/mosaicing/merge.c:134 +#: libvips/mosaicing/mosaic1.c:510 libvips/mosaicing/mosaic.c:191 +#: libvips/mosaicing/remosaic.c:170 libvips/resample/resample.c:146 +#: libvips/resample/thumbnail.c:968 +msgid "Output" +msgstr "Ausgabe" -#. Name -#: libvips/arithmetic/arith_dispatch.c:317 libvips/arithmetic/add.c:186 -msgid "add two images" -msgstr "zwei Bilder hinzufügen" +#: libvips/arithmetic/arithmetic.c:732 libvips/arithmetic/hough.c:180 +#: libvips/colour/CMYK2XYZ.c:127 libvips/colour/colour.c:416 +#: libvips/colour/colourspace.c:564 libvips/colour/scRGB2BW.c:244 +#: libvips/colour/scRGB2sRGB.c:277 libvips/colour/scRGB2XYZ.c:198 +#: libvips/colour/sRGB2scRGB.c:295 libvips/colour/XYZ2CMYK.c:126 +#: libvips/colour/XYZ2scRGB.c:207 libvips/conversion/conversion.c:347 +#: libvips/conversion/switch.c:203 libvips/convolution/canny.c:449 +#: libvips/convolution/convolution.c:135 libvips/convolution/correlation.c:163 +#: libvips/convolution/edge.c:224 libvips/convolution/gaussblur.c:139 +#: libvips/convolution/sharpen.c:329 libvips/create/create.c:125 +#: libvips/foreign/foreign.c:1216 libvips/freqfilt/freqfilt.c:105 +#: libvips/histogram/case.c:253 libvips/histogram/hist_equal.c:121 +#: libvips/histogram/hist_local.c:368 libvips/histogram/hist_norm.c:148 +#: libvips/histogram/histogram.c:233 libvips/histogram/hist_plot.c:340 +#: libvips/histogram/maplut.c:751 libvips/histogram/stdif.c:301 +#: libvips/iofuncs/system.c:285 libvips/morphology/morph.c:960 +#: libvips/morphology/rank.c:565 libvips/mosaicing/global_balance.c:1931 +#: libvips/mosaicing/match.c:209 libvips/mosaicing/merge.c:135 +#: libvips/mosaicing/mosaic1.c:511 libvips/mosaicing/mosaic.c:192 +#: libvips/mosaicing/remosaic.c:171 libvips/resample/resample.c:147 +#: libvips/resample/thumbnail.c:969 +msgid "Output image" +msgstr "Ausgabebild" -#. Name -#: libvips/arithmetic/arith_dispatch.c:342 -msgid "average value of image" -msgstr "Durchschnittswert des Bildes" +#: libvips/arithmetic/avg.c:227 +msgid "find image average" +msgstr "Bildmittelwert finden" -#. Name -#: libvips/arithmetic/arith_dispatch.c:431 -msgid "standard deviation of image" -msgstr "Standardabweichung des Bildes" +#: libvips/arithmetic/avg.c:236 libvips/arithmetic/deviate.c:238 +#: libvips/arithmetic/max.c:453 libvips/arithmetic/min.c:453 +#: libvips/histogram/hist_entropy.c:118 +msgid "Output value" +msgstr "Ausgabewert" -# im_exptra() transforms element x of input to -# pow(e, x) in output. -#. Name -#: libvips/arithmetic/arith_dispatch.c:450 -msgid "10^pel of image" -msgstr "10^pel des Bildes" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:469 -msgid "e^pel of image" -msgstr "e^pel des Bildes" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:498 -msgid "x^pel of image" -msgstr "x^pel des Bildes" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:527 -msgid "[x,y,z]^pel of image" -msgstr "[x,y,z]^pel des Bildes" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:546 libvips/arithmetic/divide.c:225 -msgid "divide two images" -msgstr "zwei Bilder teilen" +#: libvips/arithmetic/binary.c:89 +msgid "binary operations" +msgstr "binäre Transaktionen" -#. Name -#: libvips/arithmetic/arith_dispatch.c:565 -msgid "photographic negative" -msgstr "Fotonegativ" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:596 -msgid "calculate a*in + b = outfile" -msgstr "Berechnen von a*in + b = Ausgabedatei" - -#: libvips/arithmetic/arith_dispatch.c:622 -msgid "vectors not equal length" -msgstr "Vektoren ungleicher Länge" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:633 -msgid "calculate a*in + b -> out, a and b vectors" -msgstr "Berechnen von a*in + b -> out, a und b Vektoren" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:652 -msgid "log10 of image" -msgstr "log10 des Bildes" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:671 -msgid "ln of image" -msgstr "ln des Bildes" +#: libvips/arithmetic/binary.c:96 libvips/arithmetic/find_trim.c:216 +#: libvips/arithmetic/measure.c:221 libvips/colour/colour.c:684 +#: libvips/conversion/extract.c:200 libvips/draw/draw_flood.c:593 +#: libvips/draw/draw_rect.c:173 libvips/draw/draw_smudge.c:215 +msgid "Left" +msgstr "links" -#. Name -#: libvips/arithmetic/arith_dispatch.c:690 -msgid "tan of image (angles in degrees)" -msgstr "Tangens des Bildes (Winkel in Grad)" +#: libvips/arithmetic/binary.c:97 +msgid "Left-hand image argument" +msgstr "linksseitiges Bildargument" -#. Name -#: libvips/arithmetic/arith_dispatch.c:709 -msgid "atan of image (result in degrees)" -msgstr "Arkustangens des Bildes (Ergebnis in Grad)" +#: libvips/arithmetic/binary.c:102 libvips/colour/colour.c:690 +msgid "Right" +msgstr "rechts" -#. Name -#: libvips/arithmetic/arith_dispatch.c:728 -msgid "cos of image (angles in degrees)" -msgstr "Kosinus des Bildes (Winkel in Grad)" +#: libvips/arithmetic/binary.c:103 +msgid "Right-hand image argument" +msgstr "rechtsseitiges Bildargument" -#. Name -#: libvips/arithmetic/arith_dispatch.c:747 -msgid "acos of image (result in degrees)" -msgstr "Arkuskosinus des Bildes (Ergebnis in Grad)" +#: libvips/arithmetic/boolean.c:269 +#, fuzzy +msgid "boolean operation on two images" +msgstr "eine Wahr-/Falsch-Transaktion für ein Bilderpaar" -# hinter diesem String folgt ein Flag. -#. Name -#: libvips/arithmetic/arith_dispatch.c:766 -msgid "round to smallest integer value not less than" -msgstr "auf kleinsten ganzzahligen Wert runden, nicht weniger als" +#: libvips/arithmetic/boolean.c:277 libvips/arithmetic/boolean.c:577 +#: libvips/arithmetic/complex.c:258 libvips/arithmetic/complex.c:538 +#: libvips/arithmetic/complex.c:771 libvips/arithmetic/math2.c:241 +#: libvips/arithmetic/math2.c:471 libvips/arithmetic/math.c:261 +#: libvips/arithmetic/relational.c:246 libvips/arithmetic/relational.c:611 +#: libvips/conversion/bandbool.c:238 tools/vips.c:627 +msgid "Operation" +msgstr "Transaktion" -# hinter diesem String folgt ein Flag. -#. Name -#: libvips/arithmetic/arith_dispatch.c:785 -msgid "round to largest integer value not greater than" -msgstr "auf größten ganzzahligen Wert runden, nicht größer als" +#: libvips/arithmetic/boolean.c:278 libvips/arithmetic/boolean.c:578 +#: libvips/conversion/bandbool.c:239 +#, fuzzy +msgid "Boolean to perform" +msgstr "Boolesch zur Durchführung" -# hinter diesem String folgt ein Flag. -#. Name -#: libvips/arithmetic/arith_dispatch.c:804 -msgid "round to nearest integer value" -msgstr "auf nächsten ganzzahligen Wert runden" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:823 -msgid "sin of image (angles in degrees)" -msgstr "Sinus des Bildes (Winkel in Grad)" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:842 -msgid "average image bands" -msgstr "durchschnittliche Bildbänder" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:861 -msgid "unit vector in direction of value" -msgstr "Einheitsvektor in Richtung des Wertes" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:880 -msgid "asin of image (result in degrees)" -msgstr "Arkussinus des Bildes (Ergebnis in Grad)" - -#. Name -#: libvips/arithmetic/arith_dispatch.c:905 -msgid "maximum value of image" -msgstr "Maximalwert des Bildes" +#: libvips/arithmetic/boolean.c:569 +msgid "boolean operations against a constant" +msgstr "boolesche Transaktionen mit einer Konstante" -#. Name -#: libvips/arithmetic/arith_dispatch.c:940 -msgid "position of maximum value of image" -msgstr "Position des Maximalwerts des Bildes" +# http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650& +# db=man&fname=/usr/share/catman/p_man/cat3/il_c/ilAbsImg.z +#: libvips/arithmetic/clamp.c:155 +#, fuzzy +msgid "clamp values of an image" +msgstr "absoluter Wert eines Bildes" -#: libvips/arithmetic/arith_dispatch.c:968 -msgid "position of maximum value of image, averaging in case of draw" -msgstr "" -"Position des Maximalwerts des Bildes, durchschnittlich im Fall des Zeichnens" +#: libvips/arithmetic/clamp.c:162 +#, fuzzy +msgid "Min" +msgstr "primär" -#: libvips/arithmetic/arith_dispatch.c:1012 -msgid "position and value of n maxima of image" -msgstr "Position und Wert von n Maxima des Bildes" +#: libvips/arithmetic/clamp.c:163 +#, fuzzy +msgid "Minimum value" +msgstr "Minimalwert des Bildes" -#: libvips/arithmetic/arith_dispatch.c:1046 -msgid "position and value of n minima of image" -msgstr "Position und Wert von n Minima des Bildes" +#: libvips/arithmetic/clamp.c:169 +msgid "Max" +msgstr "" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1094 -msgid "measure averages of a grid of patches" -msgstr "Durchschnittsmaße eine Gitters aus Flickstücken" +#: libvips/arithmetic/clamp.c:170 +#, fuzzy +msgid "Maximum value" +msgstr "Maximalwert des Bildes" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1119 -msgid "minimum value of image" -msgstr "Minimalwert des Bildes" +#: libvips/arithmetic/complex.c:251 +msgid "perform a complex operation on an image" +msgstr "eine komplexe Transaktion mit einem Bild durchführen" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1147 -msgid "position of minimum value of image" -msgstr "Position des Minimalwerts des Bildes" +#: libvips/arithmetic/complex.c:259 libvips/arithmetic/complex.c:772 +#, fuzzy +msgid "Complex to perform" +msgstr "komplex durchzuführen" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1166 -msgid "remainder after integer division" -msgstr "Rest nach Ganzzahldivision" +#: libvips/arithmetic/complex.c:531 +#, fuzzy +msgid "complex binary operations on two images" +msgstr "eine komplexe Transaktion mit einem Bild durchführen" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1195 -msgid "remainder after integer division by a constant" -msgstr "Rest nach Ganzzahldivision durch eine Konstante" +#: libvips/arithmetic/complex.c:539 +#, fuzzy +msgid "Binary complex operation to perform" +msgstr "durchzuführende Rundungstransakktion" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1224 -msgid "remainder after integer division by a vector of constants" -msgstr "Rest nach Ganzzahldivision durch einen Vektor von Konstanten" +#: libvips/arithmetic/complex.c:762 +msgid "get a component from a complex image" +msgstr "einen Bestandteil eines komplexen Bildes holen" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1244 libvips/arithmetic/multiply.c:172 -msgid "multiply two images" -msgstr "zwei Bilder multiplizieren" +#: libvips/arithmetic/complex.c:978 +msgid "form a complex image from two real images" +msgstr "ein komplexes Bild aus zwei echten Bildern erstellen" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1265 -msgid "pel^x of image" -msgstr "pel^x des Bildes" +#: libvips/arithmetic/deviate.c:229 +#, fuzzy +msgid "find image standard deviation" +msgstr "Standardabweichung des Bildes" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1286 -msgid "pel^[x,y,z] of image" -msgstr "pel^[x,y,z] des Bildes" +#: libvips/arithmetic/divide.c:210 +msgid "divide two images" +msgstr "zwei Bilder teilen" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1317 -msgid "many image statistics in one pass" -msgstr "viele Bildstatistiken in einem Durchgang" +#: libvips/arithmetic/find_trim.c:183 +msgid "search an image for non-edge areas" +msgstr "" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1336 libvips/arithmetic/subtract.c:161 -msgid "subtract two images" -msgstr "zwei Bilder subtrahieren" +#: libvips/arithmetic/find_trim.c:189 libvips/arithmetic/getpoint.c:153 +#: libvips/arithmetic/measure.c:195 libvips/arithmetic/nary.c:87 +#: libvips/arithmetic/statistic.c:167 libvips/arithmetic/unary.c:88 +#: libvips/colour/CMYK2XYZ.c:120 libvips/colour/colour.c:480 +#: libvips/colour/colour.c:573 libvips/colour/colourspace.c:557 +#: libvips/colour/scRGB2BW.c:237 libvips/colour/scRGB2sRGB.c:270 +#: libvips/colour/scRGB2XYZ.c:191 libvips/colour/sRGB2scRGB.c:288 +#: libvips/colour/XYZ2CMYK.c:119 libvips/colour/XYZ2scRGB.c:200 +#: libvips/conversion/addalpha.c:90 libvips/conversion/arrayjoin.c:394 +#: libvips/conversion/autorot.c:207 libvips/conversion/bandbool.c:232 +#: libvips/conversion/bandfold.c:161 libvips/conversion/bandjoin.c:201 +#: libvips/conversion/bandjoin.c:436 libvips/conversion/bandmean.c:212 +#: libvips/conversion/bandrank.c:254 libvips/conversion/bandunfold.c:164 +#: libvips/conversion/byteswap.c:238 libvips/conversion/cache.c:108 +#: libvips/conversion/cast.c:530 libvips/conversion/copy.c:271 +#: libvips/conversion/embed.c:568 libvips/conversion/extract.c:194 +#: libvips/conversion/extract.c:432 libvips/conversion/falsecolour.c:380 +#: libvips/conversion/flatten.c:419 libvips/conversion/flip.c:240 +#: libvips/conversion/gamma.c:142 libvips/conversion/grid.c:199 +#: libvips/conversion/msb.c:247 libvips/conversion/premultiply.c:261 +#: libvips/conversion/recomb.c:224 libvips/conversion/replicate.c:196 +#: libvips/conversion/rot45.c:268 libvips/conversion/rot.c:365 +#: libvips/conversion/scale.c:155 libvips/conversion/sequential.c:243 +#: libvips/conversion/smartcrop.c:433 libvips/conversion/subsample.c:267 +#: libvips/conversion/tilecache.c:398 libvips/conversion/transpose3d.c:167 +#: libvips/conversion/unpremultiply.c:323 libvips/conversion/wrap.c:119 +#: libvips/conversion/zoom.c:373 libvips/convolution/canny.c:442 +#: libvips/convolution/convolution.c:128 libvips/convolution/correlation.c:150 +#: libvips/convolution/edge.c:217 libvips/convolution/gaussblur.c:132 +#: libvips/convolution/sharpen.c:322 libvips/create/buildlut.c:263 +#: libvips/create/invertlut.c:288 libvips/foreign/foreign.c:1894 +#: libvips/freqfilt/freqfilt.c:98 libvips/histogram/hist_entropy.c:111 +#: libvips/histogram/hist_equal.c:114 libvips/histogram/hist_ismonotonic.c:118 +#: libvips/histogram/hist_local.c:361 libvips/histogram/hist_match.c:161 +#: libvips/histogram/hist_norm.c:141 libvips/histogram/hist_plot.c:333 +#: libvips/histogram/hist_unary.c:88 libvips/histogram/maplut.c:744 +#: libvips/histogram/percent.c:109 libvips/histogram/stdif.c:294 +#: libvips/iofuncs/ginputsource.c:274 libvips/iofuncs/sbuf.c:88 +#: libvips/iofuncs/system.c:277 libvips/morphology/morphology.c:121 +#: libvips/mosaicing/global_balance.c:1924 libvips/mosaicing/matrixinvert.c:443 +#: libvips/mosaicing/remosaic.c:164 libvips/resample/resample.c:140 +#: libvips/resample/thumbnail.c:1782 +msgid "Input" +msgstr "Eingabe" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1384 -msgid "pixelwise linear regression" -msgstr "bildpunktweise lineare Regression" +#: libvips/arithmetic/find_trim.c:190 +#, fuzzy +msgid "Image to find_trim" +msgstr "Bilddateiname" -#. Name -#: libvips/arithmetic/arith_dispatch.c:1403 -msgid "phase of cross power spectrum of two complex images" -msgstr "Phase des Kreuzleistungsspektrums zweier komplexer Bilder" +#: libvips/arithmetic/find_trim.c:195 libvips/histogram/percent.c:122 +msgid "Threshold" +msgstr "" -#: libvips/arithmetic/linear.c:249 -msgid "calculate (a * in + b)" -msgstr "(a * in + b) berechnen" +#: libvips/arithmetic/find_trim.c:196 +msgid "Object threshold" +msgstr "" -#: libvips/arithmetic/linear.c:257 -msgid "a" -msgstr "a" +#: libvips/arithmetic/find_trim.c:202 libvips/conversion/arrayjoin.c:415 +#: libvips/conversion/embed.c:595 libvips/conversion/flatten.c:425 +#: libvips/conversion/insert.c:499 libvips/conversion/join.c:270 +#: libvips/foreign/foreign.c:1908 libvips/foreign/pdfiumload.c:723 +#: libvips/foreign/popplerload.c:573 libvips/resample/affine.c:699 +#: libvips/resample/mapim.c:574 libvips/resample/similarity.c:133 +msgid "Background" +msgstr "Hintergrund" -#: libvips/arithmetic/linear.c:258 -msgid "Multiply by this" -msgstr "hiermit multiplizieren" +#: libvips/arithmetic/find_trim.c:203 libvips/conversion/embed.c:596 +#, fuzzy +msgid "Color for background pixels" +msgstr "Farbe für neue Bildpunkte" -#: libvips/arithmetic/linear.c:264 -msgid "b" -msgstr "b" +#: libvips/arithmetic/find_trim.c:209 +msgid "Line art mode" +msgstr "" -#: libvips/arithmetic/linear.c:265 -msgid "Add this" -msgstr "dies hinzufügen" +#: libvips/arithmetic/find_trim.c:210 +msgid "Enable line art mode" +msgstr "" -#: libvips/arithmetic/remainder.c:178 -msgid "remainder after integer division of two images" -msgstr "Rest nach Ganzzahldivision zweier Bilder" +#: libvips/arithmetic/find_trim.c:217 +#, fuzzy +msgid "Left edge of image" +msgstr "linker Rand des Teilbilds im Hauptbild" -#: libvips/arithmetic/remainder.c:327 -msgid "remainder after integer division of an image and a constant" -msgstr "Rest nach Ganzzahldivision eines Bildes und einer Konstante" +#: libvips/arithmetic/find_trim.c:223 libvips/arithmetic/measure.c:228 +#: libvips/conversion/extract.c:207 libvips/draw/draw_flood.c:600 +#: libvips/draw/draw_rect.c:180 libvips/draw/draw_smudge.c:222 +msgid "Top" +msgstr "oben" -#: libvips/arithmetic/im_maxpos_vec.c:121 -#: libvips/arithmetic/im_maxpos_vec.c:186 -msgid "scalar images only" -msgstr "nur skalare Bilder" +#: libvips/arithmetic/find_trim.c:224 libvips/arithmetic/measure.c:229 +#: libvips/conversion/extract.c:208 +msgid "Top edge of extract area" +msgstr "obere Kante eines extrahierten Bereichs" -#: libvips/arithmetic/im_maxpos_vec.c:126 -#: libvips/arithmetic/im_maxpos_vec.c:191 -msgid "single band images only" -msgstr "nur Einzelbandbilder" +#: libvips/arithmetic/find_trim.c:230 libvips/arithmetic/hough_line.c:147 +#: libvips/arithmetic/measure.c:235 libvips/conversion/copy.c:284 +#: libvips/conversion/embed.c:574 libvips/conversion/extract.c:214 +#: libvips/conversion/smartcrop.c:439 libvips/create/black.c:140 +#: libvips/create/fractsurf.c:104 libvips/create/gaussnoise.c:167 +#: libvips/create/logmat.c:208 libvips/create/perlin.c:294 +#: libvips/create/point.c:141 libvips/create/sdf.c:304 +#: libvips/create/text.c:567 libvips/create/worley.c:307 +#: libvips/create/xyz.c:191 libvips/draw/draw_flood.c:607 +#: libvips/draw/draw_rect.c:187 libvips/draw/draw_smudge.c:229 +#: libvips/foreign/rawload.c:146 libvips/histogram/hist_local.c:373 +#: libvips/histogram/stdif.c:308 libvips/iofuncs/image.c:1102 +#: libvips/morphology/rank.c:570 +msgid "Width" +msgstr "Breite" -#: libvips/arithmetic/im_maxpos_vec.c:131 -#: libvips/arithmetic/im_maxpos_vec.c:196 -msgid "uncoded images only" -msgstr "nur unkodierte Bilder" +#: libvips/arithmetic/find_trim.c:231 libvips/arithmetic/measure.c:236 +#: libvips/conversion/extract.c:215 libvips/conversion/smartcrop.c:440 +msgid "Width of extract area" +msgstr "Breite des extrahierten Bereichs" -#: libvips/arithmetic/im_maxpos_vec.c:136 -#: libvips/arithmetic/im_maxpos_vec.c:201 -msgid "invalid argument" -msgstr "ungültiges Argument" +#: libvips/arithmetic/find_trim.c:237 libvips/arithmetic/hough_line.c:154 +#: libvips/arithmetic/measure.c:242 libvips/conversion/copy.c:291 +#: libvips/conversion/embed.c:581 libvips/conversion/extract.c:221 +#: libvips/conversion/smartcrop.c:446 libvips/create/black.c:147 +#: libvips/create/fractsurf.c:111 libvips/create/gaussnoise.c:174 +#: libvips/create/perlin.c:301 libvips/create/point.c:148 +#: libvips/create/sdf.c:311 libvips/create/text.c:574 +#: libvips/create/worley.c:314 libvips/create/xyz.c:198 +#: libvips/draw/draw_flood.c:614 libvips/draw/draw_rect.c:194 +#: libvips/draw/draw_smudge.c:236 libvips/foreign/rawload.c:153 +#: libvips/histogram/hist_local.c:380 libvips/histogram/stdif.c:315 +#: libvips/iofuncs/image.c:1109 libvips/morphology/rank.c:577 +msgid "Height" +msgstr "Höhe" -#: libvips/arithmetic/min.c:317 -msgid "find image minimum" -msgstr "Minimum des Bildes finden" +#: libvips/arithmetic/find_trim.c:238 libvips/arithmetic/measure.c:243 +#: libvips/conversion/extract.c:222 libvips/conversion/smartcrop.c:447 +msgid "Height of extract area" +msgstr "Höhe des extrahierten Bereichs" -#: libvips/arithmetic/min.c:325 libvips/arithmetic/arithmetic.c:382 -#: libvips/arithmetic/stats.c:423 libvips/arithmetic/measure.c:202 -#: libvips/arithmetic/max.c:324 libvips/arithmetic/avg.c:218 -#: libvips/arithmetic/deviate.c:219 libvips/conversion/conversion.c:89 -#: libvips/foreign/foreign.c:897 -msgid "Output" -msgstr "Ausgabe" +#: libvips/arithmetic/getpoint.c:149 +#, fuzzy +msgid "read a point from an image" +msgstr "Band aus einem Bild extrahieren" -#: libvips/arithmetic/min.c:326 libvips/arithmetic/max.c:325 -#: libvips/arithmetic/avg.c:219 libvips/arithmetic/deviate.c:220 -msgid "Output value" +#: libvips/arithmetic/getpoint.c:154 libvips/arithmetic/statistic.c:168 +#: libvips/arithmetic/unary.c:89 libvips/colour/CMYK2XYZ.c:121 +#: libvips/colour/colour.c:481 libvips/colour/colour.c:574 +#: libvips/colour/colourspace.c:558 libvips/colour/scRGB2BW.c:238 +#: libvips/colour/scRGB2sRGB.c:271 libvips/colour/scRGB2XYZ.c:192 +#: libvips/colour/sRGB2scRGB.c:289 libvips/colour/XYZ2CMYK.c:120 +#: libvips/colour/XYZ2scRGB.c:201 libvips/conversion/addalpha.c:91 +#: libvips/conversion/autorot.c:208 libvips/conversion/bandfold.c:162 +#: libvips/conversion/bandjoin.c:437 libvips/conversion/bandunfold.c:165 +#: libvips/conversion/byteswap.c:239 libvips/conversion/cache.c:109 +#: libvips/conversion/cast.c:531 libvips/conversion/copy.c:272 +#: libvips/conversion/embed.c:569 libvips/conversion/extract.c:195 +#: libvips/conversion/extract.c:433 libvips/conversion/falsecolour.c:381 +#: libvips/conversion/flatten.c:420 libvips/conversion/flip.c:241 +#: libvips/conversion/gamma.c:143 libvips/conversion/grid.c:200 +#: libvips/conversion/msb.c:248 libvips/conversion/premultiply.c:262 +#: libvips/conversion/replicate.c:197 libvips/conversion/rot45.c:269 +#: libvips/conversion/rot.c:366 libvips/conversion/scale.c:156 +#: libvips/conversion/sequential.c:244 libvips/conversion/smartcrop.c:434 +#: libvips/conversion/subsample.c:268 libvips/conversion/tilecache.c:399 +#: libvips/conversion/transpose3d.c:168 libvips/conversion/unpremultiply.c:324 +#: libvips/conversion/wrap.c:120 libvips/conversion/zoom.c:374 +#: libvips/convolution/canny.c:443 libvips/convolution/edge.c:218 +#: libvips/convolution/gaussblur.c:133 libvips/convolution/sharpen.c:323 +#: libvips/freqfilt/freqfilt.c:99 libvips/histogram/hist_equal.c:115 +#: libvips/histogram/hist_local.c:362 libvips/histogram/hist_norm.c:142 +#: libvips/histogram/hist_plot.c:334 libvips/histogram/hist_unary.c:89 +#: libvips/histogram/maplut.c:745 libvips/histogram/percent.c:110 +#: libvips/histogram/stdif.c:295 libvips/mosaicing/global_balance.c:1925 +#: libvips/mosaicing/remosaic.c:165 +msgid "Input image" +msgstr "Eingabebild" + +#: libvips/arithmetic/getpoint.c:159 libvips/arithmetic/max.c:480 +#: libvips/arithmetic/min.c:480 +#, fuzzy +msgid "Output array" msgstr "Ausgabewert" -#: libvips/arithmetic/min.c:332 libvips/arithmetic/max.c:331 -#: libvips/conversion/embed.c:522 +#: libvips/arithmetic/getpoint.c:160 libvips/arithmetic/max.c:481 +#: libvips/arithmetic/min.c:481 +#, fuzzy +msgid "Array of output values" +msgstr "Feld von Eingabebildern" + +#: libvips/arithmetic/getpoint.c:166 libvips/arithmetic/max.c:459 +#: libvips/arithmetic/min.c:459 libvips/conversion/composite.cpp:1733 +#: libvips/conversion/embed.c:656 libvips/conversion/wrap.c:125 +#: libvips/draw/draw_flood.c:566 libvips/draw/draw_image.c:275 +#: libvips/draw/draw_mask.c:338 msgid "x" msgstr "x" -#: libvips/arithmetic/min.c:333 -msgid "Horizontal position of minimum" -msgstr "horizontale Position des Minimums" +#: libvips/arithmetic/getpoint.c:167 libvips/arithmetic/getpoint.c:174 +#, fuzzy +msgid "Point to read" +msgstr "keine Punkte zum Mitteln" -#: libvips/arithmetic/min.c:339 libvips/arithmetic/max.c:338 -#: libvips/conversion/embed.c:529 +#: libvips/arithmetic/getpoint.c:173 libvips/arithmetic/max.c:466 +#: libvips/arithmetic/min.c:466 libvips/conversion/composite.cpp:1740 +#: libvips/conversion/embed.c:663 libvips/conversion/wrap.c:132 +#: libvips/draw/draw_flood.c:573 libvips/draw/draw_image.c:282 +#: libvips/draw/draw_mask.c:345 msgid "y" msgstr "y" -#: libvips/arithmetic/min.c:340 -msgid "Vertical position of minimum" -msgstr "vertikale Position des Minimums" +#: libvips/arithmetic/getpoint.c:180 +#, fuzzy +msgid "unpack_complex" +msgstr "Maske zu komplex" -#: libvips/arithmetic/boolean.c:209 -msgid "a boolean operation on a pair of images" -msgstr "eine Wahr-/Falsch-Transaktion für ein Bilderpaar" +#: libvips/arithmetic/getpoint.c:181 +msgid "Complex pixels should be unpacked" +msgstr "" -#: libvips/arithmetic/boolean.c:217 libvips/arithmetic/boolean.c:519 -#: libvips/arithmetic/math2.c:204 libvips/arithmetic/math2.c:401 -#: libvips/arithmetic/math.c:205 libvips/arithmetic/relational.c:227 -#: libvips/arithmetic/relational.c:560 libvips/arithmetic/complex.c:222 -#: libvips/arithmetic/complex.c:476 -msgid "Operation" -msgstr "Transaktion" +#: libvips/arithmetic/hist_find.c:422 +#, fuzzy +msgid "find image histogram" +msgstr "Minimum des Bildes finden" -#: libvips/arithmetic/boolean.c:218 libvips/arithmetic/boolean.c:520 -msgid "boolean to perform" -msgstr "Boolesch zur Durchführung" +#: libvips/arithmetic/hist_find.c:432 +#: libvips/arithmetic/hist_find_indexed.c:476 +#: libvips/arithmetic/hist_find_ndim.c:314 +#, fuzzy +msgid "Output histogram" +msgstr "Ausgabebild" -#: libvips/arithmetic/boolean.c:511 -msgid "boolean operations against a constant" -msgstr "boolesche Transaktionen mit einer Konstante" +#: libvips/arithmetic/hist_find.c:437 libvips/conversion/extract.c:438 +#: libvips/conversion/msb.c:253 libvips/histogram/hist_equal.c:126 +#: libvips/histogram/maplut.c:762 +msgid "Band" +msgstr "Band" -#: libvips/arithmetic/arithmetic.c:164 -#, c-format -msgid "not one band or %d bands" -msgstr "nicht ein Band oder %d Bänder" +#: libvips/arithmetic/hist_find.c:438 +msgid "Find histogram of band" +msgstr "" -#: libvips/arithmetic/arithmetic.c:168 libvips/histograms_lut/im_identity.c:80 -#: libvips/histograms_lut/im_identity.c:143 -msgid "bad bands" -msgstr "falsche Bänder" +#: libvips/arithmetic/hist_find_indexed.c:461 +msgid "find indexed image histogram" +msgstr "" -#: libvips/arithmetic/arithmetic.c:324 libvips/conversion/bandary.c:131 -msgid "too many input images" -msgstr "zu viele Eingabebilder" +#: libvips/arithmetic/hist_find_indexed.c:469 libvips/conversion/bandrank.c:261 +#: libvips/histogram/case.c:239 libvips/morphology/rank.c:584 +#: libvips/resample/mapim.c:555 +msgid "Index" +msgstr "" -#: libvips/arithmetic/arithmetic.c:378 -msgid "arithmetic operations" -msgstr "arithmetische Transaktionen" +#: libvips/arithmetic/hist_find_indexed.c:470 libvips/histogram/case.c:240 +#, fuzzy +msgid "Index image" +msgstr "Eingabebild" -#: libvips/arithmetic/arithmetic.c:383 libvips/conversion/conversion.c:90 -#: libvips/foreign/foreign.c:898 -msgid "Output image" -msgstr "Ausgabebild" +#: libvips/arithmetic/hist_find_indexed.c:481 libvips/convolution/compass.c:177 +msgid "Combine" +msgstr "" -#: libvips/arithmetic/stats.c:415 libvips/arithmetic/avg.c:210 -#: libvips/arithmetic/deviate.c:211 -msgid "find image average" -msgstr "Bildmittelwert finden" +#: libvips/arithmetic/hist_find_indexed.c:482 +msgid "Combine bins like this" +msgstr "" -#: libvips/arithmetic/stats.c:424 libvips/arithmetic/measure.c:203 -msgid "Output array of statistics" -msgstr "Ausgabefeld von Statistiken" +#: libvips/arithmetic/hist_find_ndim.c:150 +#, fuzzy +msgid "image is not 1 - 3 bands" +msgstr "Bild muss ein oder %d Bänder haben" -#: libvips/arithmetic/math2.c:196 -msgid "pow( left, right)" -msgstr "pow( links, rechts)" +#: libvips/arithmetic/hist_find_ndim.c:159 +#, fuzzy, c-format +msgid "bins out of range [1,%d]" +msgstr " »bins« außerhalb des Bereichs [1,%d]" -#: libvips/arithmetic/math2.c:205 libvips/arithmetic/math2.c:402 -#: libvips/arithmetic/math.c:206 -msgid "math to perform" -msgstr "durchzuführende Berechnung" +#: libvips/arithmetic/hist_find_ndim.c:304 +#, fuzzy +msgid "find n-dimensional image histogram" +msgstr "%d-dimensionale Bilder nicht unterstützt" -#: libvips/arithmetic/math2.c:393 -msgid "pow( @in, @c )" -msgstr "pow( @in, @c )" +#: libvips/arithmetic/hist_find_ndim.c:319 +msgid "Bins" +msgstr "" -#: libvips/arithmetic/round.c:160 -msgid "perform a round function on an image" -msgstr "eine Rundungsfunktion für ein Bild ausführen" +#: libvips/arithmetic/hist_find_ndim.c:320 +#, fuzzy +msgid "Number of bins in each dimension" +msgstr "Anzahl der Bänder in einem Bild" -#: libvips/arithmetic/round.c:168 -msgid "Round operation" -msgstr "Rundungstransakktion" +#: libvips/arithmetic/hough.c:170 +msgid "find hough transform" +msgstr "" -#: libvips/arithmetic/round.c:169 -msgid "rounding operation to perform" -msgstr "durchzuführende Rundungstransakktion" +#: libvips/arithmetic/hough_circle.c:115 +msgid "parameters out of range" +msgstr "Parameter außerhalb des Bereichs" -#: libvips/arithmetic/measure.c:163 -#, c-format -msgid "patch %d x %d, band %d: avg = %g, sdev = %g" -msgstr "Flicken %d x %d, Band %d: Durchschn. = %g, sdev = %g" +#: libvips/arithmetic/hough_circle.c:226 +msgid "find hough circle transform" +msgstr "" -#: libvips/arithmetic/measure.c:192 -msgid "measure a set of patches on a colour chart" -msgstr "messen eines Satzes von Patches auf ein Farbdiagramm" +#: libvips/arithmetic/hough_circle.c:233 libvips/foreign/pdfiumload.c:716 +#: libvips/foreign/popplerload.c:566 libvips/foreign/svgload.c:724 +#: libvips/foreign/webpload.c:192 libvips/mosaicing/mosaic.c:274 +#: libvips/resample/similarity.c:200 +msgid "Scale" +msgstr "" -#: libvips/arithmetic/measure.c:196 -msgid "in" -msgstr "in" +#: libvips/arithmetic/hough_circle.c:234 +msgid "Scale down dimensions by this factor" +msgstr "" -#: libvips/arithmetic/measure.c:197 -msgid "Image to measure" -msgstr "zu vermessendes Bild" +#: libvips/arithmetic/hough_circle.c:240 +msgid "Min radius" +msgstr "" -#: libvips/arithmetic/measure.c:208 libvips/conversion/replicate.c:202 -msgid "Across" -msgstr "über" +#: libvips/arithmetic/hough_circle.c:241 +msgid "Smallest radius to search for" +msgstr "" -#: libvips/arithmetic/measure.c:209 -msgid "Number of patches across chart" -msgstr "Anzahl der Patches über ein Diagramm" +#: libvips/arithmetic/hough_circle.c:247 +#, fuzzy +msgid "Max radius" +msgstr "Kacheln maximal" -#: libvips/arithmetic/measure.c:215 libvips/conversion/replicate.c:209 -msgid "Down" -msgstr "hinunter" +#: libvips/arithmetic/hough_circle.c:248 +msgid "Largest radius to search for" +msgstr "" -#: libvips/arithmetic/measure.c:216 -msgid "Number of patches down chart" -msgstr "Anzahl der Patches ein Diagramm hinunter" +#: libvips/arithmetic/hough_line.c:140 +msgid "find hough line transform" +msgstr "" -#: libvips/arithmetic/measure.c:222 libvips/arithmetic/binary.c:95 -#: libvips/conversion/extract.c:200 -msgid "Left" -msgstr "links" +#: libvips/arithmetic/hough_line.c:148 +msgid "Horizontal size of parameter space" +msgstr "" -#: libvips/arithmetic/measure.c:223 libvips/conversion/extract.c:201 -msgid "Left edge of extract area" -msgstr "linke Kante eines extrahierten Bereichs" +#: libvips/arithmetic/hough_line.c:155 +msgid "Vertical size of parameter space" +msgstr "" -#: libvips/arithmetic/measure.c:229 libvips/conversion/extract.c:207 -msgid "Top" -msgstr "oben" +#: libvips/arithmetic/invert.c:178 +msgid "invert an image" +msgstr "ein Bild invertieren" -#: libvips/arithmetic/measure.c:230 libvips/conversion/extract.c:208 -msgid "Top edge of extract area" -msgstr "obere Kante eines extrahierten Bereichs" +#: libvips/arithmetic/linear.c:446 +msgid "calculate (a * in + b)" +msgstr "(a * in + b) berechnen" -#: libvips/arithmetic/measure.c:236 libvips/conversion/extract.c:214 -#: libvips/conversion/embed.c:536 libvips/conversion/copy.c:331 -#: libvips/conversion/black.c:128 libvips/foreign/rawload.c:122 -#: libvips/iofuncs/image.c:845 -msgid "Width" -msgstr "Breite" +#: libvips/arithmetic/linear.c:454 libvips/create/sdf.c:332 +msgid "a" +msgstr "a" -#: libvips/arithmetic/measure.c:237 libvips/conversion/extract.c:215 -msgid "Width of extract area" -msgstr "Breite des extrahierten Bereichs" +#: libvips/arithmetic/linear.c:455 +msgid "Multiply by this" +msgstr "hiermit multiplizieren" -#: libvips/arithmetic/measure.c:243 libvips/conversion/extract.c:221 -#: libvips/conversion/embed.c:543 libvips/conversion/copy.c:338 -#: libvips/conversion/black.c:135 libvips/foreign/rawload.c:129 -#: libvips/iofuncs/image.c:852 -msgid "Height" -msgstr "Höhe" +#: libvips/arithmetic/linear.c:461 libvips/create/sdf.c:339 +msgid "b" +msgstr "b" -#: libvips/arithmetic/measure.c:244 libvips/conversion/extract.c:222 -msgid "Height of extract area" -msgstr "Höhe des extrahierten Bereichs" +#: libvips/arithmetic/linear.c:462 +msgid "Add this" +msgstr "dies hinzufügen" -#: libvips/arithmetic/math.c:197 -msgid "perform a math function on an image" -msgstr "eine mathematische Funktion für ein Bild ausführen" +#: libvips/arithmetic/linear.c:468 +msgid "uchar" +msgstr "" -#: libvips/arithmetic/relational.c:219 -msgid "a relational operation on a pair of images" -msgstr "eine relationale Transaktion für ein Bilderpaar" +#: libvips/arithmetic/linear.c:469 +msgid "Output should be uchar" +msgstr "" -#: libvips/arithmetic/relational.c:228 libvips/arithmetic/relational.c:561 -msgid "relational to perform" -msgstr "relational durchzuführen" +#: libvips/arithmetic/math2.c:233 +#, fuzzy +msgid "binary math operations" +msgstr "binäre Transaktionen" -#: libvips/arithmetic/relational.c:552 -msgid "relational operations against a constant" -msgstr "relationale Transaktion für eine Konstante" +#: libvips/arithmetic/math2.c:242 libvips/arithmetic/math2.c:472 +#: libvips/arithmetic/math.c:262 +#, fuzzy +msgid "Math to perform" +msgstr "durchzuführende Berechnung" -#: libvips/arithmetic/unaryconst.c:201 -msgid "unary operations with a constant" +#: libvips/arithmetic/math2.c:463 +#, fuzzy +msgid "binary math operations with a constant" msgstr "unäre Transaktionen mit einer Konstante" -#: libvips/arithmetic/unaryconst.c:205 -msgid "c" -msgstr "c" - -#: libvips/arithmetic/unaryconst.c:206 -msgid "Array of constants" -msgstr "Feld aus Konstanten" +#: libvips/arithmetic/math.c:253 +#, fuzzy +msgid "apply a math operation to an image" +msgstr "eine komplexe Transaktion mit einem Bild durchführen" -#: libvips/arithmetic/unary.c:80 -msgid "unary operations" -msgstr "unäre Transaktionen" +#: libvips/arithmetic/max.c:444 +msgid "find image maximum" +msgstr "Maximum des Bildes finden" -#: libvips/arithmetic/unary.c:88 libvips/conversion/bandmean.c:198 -#: libvips/conversion/recomb.c:201 -msgid "Input image argument" -msgstr "Eingabebildargument" - -#: libvips/arithmetic/invert.c:152 -msgid "invert an image" -msgstr "ein Bild invertieren" - -#: libvips/arithmetic/max.c:316 -msgid "find image maximum" -msgstr "Maximum des Bildes finden" - -#: libvips/arithmetic/max.c:332 +#: libvips/arithmetic/max.c:460 msgid "Horizontal position of maximum" msgstr "horizontale Position des Maximums" -#: libvips/arithmetic/max.c:339 +#: libvips/arithmetic/max.c:467 msgid "Vertical position of maximum" msgstr "vertikale Position des Maximums" -#: libvips/arithmetic/complex.c:215 -msgid "perform a complex operation on an image" -msgstr "eine komplexe Transaktion mit einem Bild durchführen" +#: libvips/arithmetic/max.c:473 libvips/arithmetic/min.c:473 +#: libvips/create/identity.c:157 libvips/create/invertlut.c:294 +#: libvips/resample/thumbnail.c:988 +msgid "Size" +msgstr "" -#: libvips/arithmetic/complex.c:223 libvips/arithmetic/complex.c:477 -msgid "complex to perform" -msgstr "komplex durchzuführen" +#: libvips/arithmetic/max.c:474 +#, fuzzy +msgid "Number of maximum values to find" +msgstr "Position des Maximalwerts des Bildes" -#: libvips/arithmetic/complex.c:468 -msgid "get a component from a complex image" -msgstr "einen Bestandteil eines komplexen Bildes holen" +#: libvips/arithmetic/max.c:487 libvips/arithmetic/min.c:487 +msgid "x array" +msgstr "" -#: libvips/arithmetic/complex.c:666 -msgid "form a complex image from two real images" -msgstr "ein komplexes Bild aus zwei echten Bildern erstellen" +#: libvips/arithmetic/max.c:488 libvips/arithmetic/min.c:488 +#, fuzzy +msgid "Array of horizontal positions" +msgstr "Feld aus Konstanten" -#: libvips/arithmetic/binary.c:88 -msgid "binary operations" -msgstr "binäre Transaktionen" +#: libvips/arithmetic/max.c:494 libvips/arithmetic/min.c:494 +msgid "y array" +msgstr "" -#: libvips/arithmetic/binary.c:96 -msgid "Left-hand image argument" -msgstr "linksseitiges Bildargument" +#: libvips/arithmetic/max.c:495 libvips/arithmetic/min.c:495 +#, fuzzy +msgid "Array of vertical positions" +msgstr "Feld aus Konstanten" -#: libvips/arithmetic/binary.c:101 -msgid "Right" -msgstr "rechts" +#: libvips/arithmetic/maxpair.c:151 +#, fuzzy +msgid "maximum of a pair of images" +msgstr "ein Bilderpaar zusammenführen" -#: libvips/arithmetic/binary.c:102 -msgid "Right-hand image argument" -msgstr "rechtsseitiges Bildargument" +#: libvips/arithmetic/measure.c:164 +#, fuzzy, c-format +msgid "%s: patch %d x %d, band %d: avg = %g, sdev = %g" +msgstr "Flicken %d x %d, Band %d: Durchschn. = %g, sdev = %g" -#: libvips/arithmetic/sign.c:151 -msgid "unit vector of pixel" -msgstr "Einheitsvektor von Bildpunkten" +#: libvips/arithmetic/measure.c:191 +#, fuzzy +msgid "measure a set of patches on a color chart" +msgstr "messen eines Satzes von Patches auf ein Farbdiagramm" -#: libvips/colour/im_rad2float.c:186 -msgid "not a RAD image" -msgstr "kein RAD-Bild" +#: libvips/arithmetic/measure.c:196 +msgid "Image to measure" +msgstr "zu vermessendes Bild" -#: libvips/colour/im_icc_transform.c:202 libvips/colour/im_icc_transform.c:212 -#: libvips/colour/im_icc_transform.c:1000 -#: libvips/colour/im_icc_transform.c:1010 -#, c-format -msgid "unable to open profile \"%s\"" -msgstr "Profil »%s« kann nicht geöffnet werden" +#: libvips/arithmetic/measure.c:202 libvips/arithmetic/stats.c:443 +msgid "Output array of statistics" +msgstr "Ausgabefeld von Statistiken" -#: libvips/colour/im_icc_transform.c:223 -#: libvips/colour/im_icc_transform.c:1022 -msgid "unable to create profiles" -msgstr "es können keine Profile erstellt werden" +#: libvips/arithmetic/measure.c:207 libvips/conversion/arrayjoin.c:401 +#: libvips/conversion/grid.c:212 libvips/conversion/replicate.c:202 +msgid "Across" +msgstr "über" -#: libvips/colour/im_icc_transform.c:242 -#: libvips/colour/im_icc_transform.c:1042 -msgid "unable to read profile" -msgstr "Profil kann nicht gelesen werden" +#: libvips/arithmetic/measure.c:208 +msgid "Number of patches across chart" +msgstr "Anzahl der Patches über ein Diagramm" -#: libvips/colour/im_icc_transform.c:363 libvips/colour/im_icc_transform.c:372 -#: libvips/colour/im_icc_transform.c:737 -#: libvips/colour/im_icc_transform.c:1170 -#: libvips/colour/im_icc_transform.c:1179 -#: libvips/colour/im_icc_transform.c:1522 -#, c-format -msgid "" -"intent %d (%s) not supported by profile \"%s\"; falling back to default " -"intent (usually PERCEPTUAL)" -msgstr "" -"Ziel-%d (%s) nicht von Profil »%s« unterstützt; Rückfall auf Standardabsicht " -"(normalerweise WAHRNEHMUNG)" +#: libvips/arithmetic/measure.c:214 libvips/conversion/grid.c:219 +#: libvips/conversion/replicate.c:209 +msgid "Down" +msgstr "hinunter" -#: libvips/colour/im_icc_transform.c:382 -#: libvips/colour/im_icc_transform.c:1189 -msgid "CMYK input profile needs a 4 band input image" -msgstr "CMYK-Eingabeprofil benötigt ein Eingabebild mit vier Bändern" +#: libvips/arithmetic/measure.c:215 +msgid "Number of patches down chart" +msgstr "Anzahl der Patches ein Diagramm hinunter" -#: libvips/colour/im_icc_transform.c:392 -#: libvips/colour/im_icc_transform.c:1199 -msgid "RGB input profile needs a 3 band input image" -msgstr "RGB-Eingabeprofil benötigt ein Eingabebild mit drei Bändern" +#: libvips/arithmetic/measure.c:222 libvips/conversion/extract.c:201 +msgid "Left edge of extract area" +msgstr "linke Kante eines extrahierten Bereichs" -#: libvips/colour/im_icc_transform.c:401 libvips/colour/im_icc_transform.c:551 -#: libvips/colour/im_icc_transform.c:1208 -#: libvips/colour/im_icc_transform.c:1340 -#, c-format -msgid "unimplemented input color space 0x%x" -msgstr "nicht implementierter Eingabefarbraum 0x%x" +#: libvips/arithmetic/min.c:444 +msgid "find image minimum" +msgstr "Minimum des Bildes finden" -#: libvips/colour/im_icc_transform.c:428 libvips/colour/im_icc_transform.c:767 -#: libvips/colour/im_icc_transform.c:1235 -#: libvips/colour/im_icc_transform.c:1552 -#, c-format -msgid "unimplemented output color space 0x%x" -msgstr "nicht implementierter Ausgabefarbraum 0x%x" +#: libvips/arithmetic/min.c:460 +msgid "Horizontal position of minimum" +msgstr "horizontale Position des Minimums" -#: libvips/colour/im_icc_transform.c:444 libvips/colour/im_icc_transform.c:567 -#: libvips/colour/im_icc_transform.c:1251 -#: libvips/colour/im_icc_transform.c:1356 -msgid "uchar or ushort input only" -msgstr "nur »uchar« oder »ushort«-Eingabe" +#: libvips/arithmetic/min.c:467 +msgid "Vertical position of minimum" +msgstr "vertikale Position des Minimums" -#: libvips/colour/im_icc_transform.c:516 -#: libvips/colour/im_icc_transform.c:1305 -#, c-format -msgid "" -"intent %d (%s) not supported by profile; falling back to default intent " -"(usually PERCEPTUAL)" -msgstr "" -"Ziel-%d (%s) nicht vom Profil unterstützt; Rückfall auf Standardabsicht " -"(normalerweise WAHRNEHMUNG)" +#: libvips/arithmetic/min.c:474 +#, fuzzy +msgid "Number of minimum values to find" +msgstr "Position des Minimalwerts des Bildes" -#: libvips/colour/im_icc_transform.c:533 -#: libvips/colour/im_icc_transform.c:1322 -msgid "CMYK profile needs a 4 band input image" -msgstr "CMYK-Profil benötigt ein Eingabebild mit vier Bändern" +#: libvips/arithmetic/minpair.c:151 +#, fuzzy +msgid "minimum of a pair of images" +msgstr "ein Bilderpaar zusammenführen" -#: libvips/colour/im_icc_transform.c:543 -#: libvips/colour/im_icc_transform.c:1332 -msgid "RGB profile needs a 3 band input image" -msgstr "RGB-Profil benötigt ein Eingabebild mit drei Bändern" +#: libvips/arithmetic/multiply.c:195 +msgid "multiply two images" +msgstr "zwei Bilder multiplizieren" -#: libvips/colour/im_icc_transform.c:634 -#: libvips/colour/im_icc_transform.c:1427 -msgid "no embedded profile" -msgstr "kein eingebettetes Profil" +#: libvips/arithmetic/nary.c:80 +#, fuzzy +msgid "nary operations" +msgstr "unäre Transaktionen" -#: libvips/colour/im_icc_transform.c:726 -#: libvips/colour/im_icc_transform.c:1511 -msgid "unsupported bit depth" -msgstr "nicht unterstützte Bit-Tiefe" +#: libvips/arithmetic/nary.c:88 libvips/conversion/arrayjoin.c:395 +#: libvips/conversion/bandjoin.c:202 libvips/conversion/bandrank.c:255 +#: libvips/conversion/composite.cpp:1581 libvips/iofuncs/system.c:278 +msgid "Array of input images" +msgstr "Feld von Eingabebildern" -#: libvips/colour/im_icc_transform.c:815 -#: libvips/colour/im_icc_transform.c:1605 -msgid "unable to get media white point" -msgstr "weißer Medienpunkt kann nicht abgefragt werden" +#: libvips/arithmetic/profile.c:293 +#, fuzzy +msgid "find image profiles" +msgstr "Bildmittelwert finden" -#: libvips/colour/im_icc_transform.c:1672 -msgid "lcms library not linked to this VIPS" -msgstr "gegen die »lcms«-Bibliothek wird in diesem VIPS nicht verlinkt" +#: libvips/arithmetic/profile.c:301 libvips/arithmetic/project.c:332 +msgid "Columns" +msgstr "" -#: libvips/colour/im_icc_transform.c:1682 -#: libvips/colour/im_icc_transform.c:1691 -#: libvips/colour/im_icc_transform.c:1701 -#: libvips/colour/im_icc_transform.c:1710 -msgid "lmcs library not linked to this VIPS" -msgstr "gegen die »lmcs«-Bibliothek wird in diesem VIPS nicht verlinkt" +#: libvips/arithmetic/profile.c:302 +msgid "First non-zero pixel in column" +msgstr "" -#: libvips/colour/disp.c:397 -msgid "out of range [0,255]" -msgstr "außerhalb des Bereichs [0,255]" +#: libvips/arithmetic/profile.c:307 libvips/arithmetic/project.c:338 +msgid "Rows" +msgstr "" -#: libvips/colour/disp.c:423 -msgid "bad display type" -msgstr "falsche Anzeigetyp" +#: libvips/arithmetic/profile.c:308 +msgid "First non-zero pixel in row" +msgstr "" -#: libvips/colour/disp.c:537 -msgid "display unknown" -msgstr "Anzeige unbekannt" +#: libvips/arithmetic/project.c:324 +#, fuzzy +msgid "find image projections" +msgstr "Minimum des Bildes finden" -#: libvips/colour/im_disp2XYZ.c:86 -msgid "input not 3-band uncoded char" -msgstr "Eingabe ist kein unkodiertes Zeichen mit drei Bändern" +#: libvips/arithmetic/project.c:333 +msgid "Sums of columns" +msgstr "" -#: libvips/colour/im_XYZ2disp.c:139 -msgid "3-band uncoded float only" -msgstr "nur unkodierte Fließkommazahlen mit drei Bändern" +#: libvips/arithmetic/project.c:339 +msgid "Sums of rows" +msgstr "" -#: libvips/colour/im_lab_morph.c:75 -msgid "bad greyscale mask size" -msgstr "falsche Grauskala-Maskengröße" +#: libvips/arithmetic/relational.c:238 +#, fuzzy +msgid "relational operation on two images" +msgstr "eine relationale Transaktion für ein Bilderpaar" -#: libvips/colour/im_lab_morph.c:86 -#, c-format -msgid "bad greyscale mask value, row %d" -msgstr "falscher Grauskala-Maskenwert, Reihe %d" +#: libvips/arithmetic/relational.c:247 libvips/arithmetic/relational.c:612 +#, fuzzy +msgid "Relational to perform" +msgstr "relational durchzuführen" -#: libvips/conversion/im_gaussnoise.c:124 -msgid "bad parameter" -msgstr "falscher Parameter" +#: libvips/arithmetic/relational.c:603 +msgid "relational operations against a constant" +msgstr "relationale Transaktion für eine Konstante" -#: libvips/conversion/bandmean.c:191 -msgid "band-wise average" -msgstr "bandweiser Durchschnitt" +#: libvips/arithmetic/remainder.c:192 +msgid "remainder after integer division of two images" +msgstr "Rest nach Ganzzahldivision zweier Bilder" -#: libvips/conversion/cast.c:123 -#, c-format -msgid "%d underflows and %d overflows detected" -msgstr "%d Unter- und %d Überläufe entdeckt" +#: libvips/arithmetic/remainder.c:353 +msgid "remainder after integer division of an image and a constant" +msgstr "Rest nach Ganzzahldivision eines Bildes und einer Konstante" -#: libvips/conversion/cast.c:470 -msgid "cast an image" -msgstr "ein Bild umwandeln" +#: libvips/arithmetic/round.c:173 +msgid "perform a round function on an image" +msgstr "eine Rundungsfunktion für ein Bild ausführen" -#: libvips/conversion/cast.c:480 libvips/conversion/copy.c:352 -#: libvips/iofuncs/image.c:866 -msgid "Format" -msgstr "Format" +#: libvips/arithmetic/round.c:181 +msgid "Round operation" +msgstr "Rundungstransakktion" -#: libvips/conversion/cast.c:481 -msgid "Format to cast to" -msgstr "Format, in das umgewandelt werden soll" +#: libvips/arithmetic/round.c:182 +#, fuzzy +msgid "Rounding operation to perform" +msgstr "durchzuführende Rundungstransakktion" -#: libvips/conversion/ifthenelse.c:395 -msgid "ifthenelse an image" -msgstr "fallsdannsonst eines Bildes" +#: libvips/arithmetic/sign.c:174 +msgid "unit vector of pixel" +msgstr "Einheitsvektor von Bildpunkten" -#: libvips/conversion/ifthenelse.c:399 -msgid "Condition" -msgstr "Bedingung" +#: libvips/arithmetic/statistic.c:161 +msgid "VIPS statistic operations" +msgstr "statistische VIPS-Transaktionen" -#: libvips/conversion/ifthenelse.c:400 -msgid "Condition input image" -msgstr "Bedingung des Eingabebilds" +#: libvips/arithmetic/stats.c:434 +#, fuzzy +msgid "find many image stats" +msgstr "ein Bild umdrehen" -#: libvips/conversion/ifthenelse.c:405 -msgid "Then image" -msgstr "dann Bild" +#: libvips/arithmetic/subtract.c:174 +msgid "subtract two images" +msgstr "zwei Bilder subtrahieren" -#: libvips/conversion/ifthenelse.c:406 -msgid "Source for TRUE pixels" -msgstr "Quelle für TRUE-Bildpunkte" +#: libvips/arithmetic/sum.c:149 +#, fuzzy +msgid "sum an array of images" +msgstr "ein Bilderpaar zusammenführen" -#: libvips/conversion/ifthenelse.c:411 -msgid "Else image" -msgstr "sonst Bild" +#: libvips/arithmetic/unary.c:81 +msgid "unary operations" +msgstr "unäre Transaktionen" -#: libvips/conversion/ifthenelse.c:412 -msgid "Source for FALSE pixels" -msgstr "Quelle für FALSE-Bildpunkte" +#: libvips/arithmetic/unaryconst.c:138 +msgid "unary operations with a constant" +msgstr "unäre Transaktionen mit einer Konstante" -#: libvips/conversion/ifthenelse.c:417 -msgid "blend" -msgstr "Mischung" +#: libvips/arithmetic/unaryconst.c:142 +msgid "c" +msgstr "c" -#: libvips/conversion/ifthenelse.c:418 -msgid "Blend smoothly between then and else parts" -msgstr "nahtlos zwischen »dann«- und »sonst«-Teilen mischen" +#: libvips/arithmetic/unaryconst.c:143 +msgid "Array of constants" +msgstr "Feld aus Konstanten" -#: libvips/conversion/insert.c:349 -msgid "insert an image" -msgstr "ein Bild einfügen" +#: libvips/colour/CMYK2XYZ.c:114 libvips/colour/CMYK2XYZ.c:182 +msgid "transform CMYK to XYZ" +msgstr "" -#: libvips/conversion/insert.c:353 -msgid "Main" -msgstr "primär" +#: libvips/colour/colour.c:288 +msgid "too many input images" +msgstr "zu viele Eingabebilder" -#: libvips/conversion/insert.c:354 -msgid "Main input image" -msgstr "Haupteingabebild" +#: libvips/colour/colour.c:409 +#, fuzzy +msgid "color operations" +msgstr "Transaktionen" -#: libvips/conversion/insert.c:359 -msgid "Sub-image" -msgstr "Teilbild" +#: libvips/colour/colour.c:476 +msgid "color space transformations" +msgstr "" -#: libvips/conversion/insert.c:360 -msgid "Sub-image to insert into main image" -msgstr "Teilbild, das in das Hauptbild eingefügt werden soll" +#: libvips/colour/colour.c:569 +msgid "change color coding" +msgstr "" -#: libvips/conversion/insert.c:365 -msgid "X" -msgstr "X" +#: libvips/colour/colour.c:680 +msgid "calculate color difference" +msgstr "" -#: libvips/conversion/insert.c:366 -msgid "Left edge of sub in main" -msgstr "linker Rand des Teilbilds im Hauptbild" +#: libvips/colour/colour.c:685 +#, fuzzy +msgid "Left-hand input image" +msgstr "zweites Eingabebild" -#: libvips/conversion/insert.c:372 -msgid "Y" -msgstr "Y" +#: libvips/colour/colour.c:691 +#, fuzzy +msgid "Right-hand input image" +msgstr "Haupteingabebild" -#: libvips/conversion/insert.c:373 -msgid "Top edge of sub in main" -msgstr "oberer Rand des Teilbilds im Hauptbild" +#: libvips/colour/colourspace.c:145 +#, fuzzy +msgid "too few bands for operation" +msgstr "Rundungstransakktion" -#: libvips/conversion/insert.c:379 libvips/conversion/join.c:233 -msgid "Expand" -msgstr "expandieren" +#: libvips/colour/colourspace.c:519 +#, fuzzy, c-format +msgid "no known route from '%s' to '%s'" +msgstr "unbekanntes Argument »%s«" -#: libvips/conversion/insert.c:380 libvips/conversion/join.c:234 -msgid "Expand output to hold all of both inputs" -msgstr "Ausgabe so expandieren, dass sie beide Eingaben vollständig enthält" +#: libvips/colour/colourspace.c:551 +msgid "convert to a new colorspace" +msgstr "" -#: libvips/conversion/insert.c:386 libvips/conversion/join.c:247 -msgid "Background" -msgstr "Hintergrund" +#: libvips/colour/colourspace.c:569 +msgid "Space" +msgstr "" -#: libvips/conversion/insert.c:387 libvips/conversion/join.c:248 -msgid "Colour for new pixels" -msgstr "Farbe für neue Bildpunkte" +#: libvips/colour/colourspace.c:570 +msgid "Destination color space" +msgstr "" -#: libvips/conversion/tilecache.c:418 libvips/conversion/cache.c:102 -msgid "cache an image" -msgstr "ein Bild zwischenspeichern" +#: libvips/colour/colourspace.c:576 +msgid "Source space" +msgstr "" -#: libvips/conversion/tilecache.c:428 libvips/conversion/cache.c:112 -#: libvips/foreign/tiffsave.c:213 -msgid "Tile width" -msgstr "Kachelbreite" +#: libvips/colour/colourspace.c:577 +#, fuzzy +msgid "Source color space" +msgstr "nicht unterstützter Farbraum %d" -#: libvips/conversion/tilecache.c:429 libvips/conversion/cache.c:113 -#: libvips/foreign/tiffsave.c:214 -msgid "Tile width in pixels" -msgstr "Kachelbreite in Bildpunkten" +#: libvips/colour/dE00.c:236 +msgid "calculate dE00" +msgstr "" -#: libvips/conversion/tilecache.c:435 libvips/conversion/cache.c:119 -#: libvips/foreign/tiffsave.c:220 -msgid "Tile height" -msgstr "Kachelhöhe" +#: libvips/colour/dE76.c:113 +msgid "calculate dE76" +msgstr "" -#: libvips/conversion/tilecache.c:436 libvips/conversion/cache.c:120 -#: libvips/foreign/tiffsave.c:221 -msgid "Tile height in pixels" -msgstr "Kachelhöhe in Bildpunkten" +#: libvips/colour/dECMC.c:61 +msgid "calculate dECMC" +msgstr "" -#: libvips/conversion/tilecache.c:442 libvips/conversion/cache.c:126 -msgid "Max tiles" -msgstr "Kacheln maximal" +#: libvips/colour/float2rad.c:206 +msgid "transform float RGB to Radiance coding" +msgstr "" -#: libvips/conversion/tilecache.c:443 libvips/conversion/cache.c:127 -msgid "Maximum number of tiles to cache" -msgstr "maximale Anzahl von Kacheln, die zwischengespeichert werden soll" +#: libvips/colour/HSV2sRGB.c:112 +msgid "transform HSV to sRGB" +msgstr "" -#: libvips/conversion/tilecache.c:449 -msgid "Strategy" -msgstr "Strategie" +#: libvips/colour/icc_transform.c:272 libvips/colour/scRGB2BW.c:190 +#: libvips/colour/scRGB2sRGB.c:224 +#, fuzzy +msgid "depth must be 8 or 16" +msgstr "»mwidth« muss -1 oder >= 0 sein" -#: libvips/conversion/tilecache.c:450 -msgid "Expected access pattern" -msgstr "erwartetes Zugriffsmuster" +#: libvips/colour/icc_transform.c:284 +#, c-format +msgid "unimplemented input color space 0x%x" +msgstr "nicht implementierter Eingabefarbraum 0x%x" -#: libvips/conversion/im_text.c:132 -msgid "no text to render" -msgstr "kein Text zu rendern" +#: libvips/colour/icc_transform.c:360 +#, c-format +msgid "unimplemented output color space 0x%x" +msgstr "nicht implementierter Ausgabefarbraum 0x%x" -#: libvips/conversion/im_text.c:219 -msgid "invalid markup in text" -msgstr "ungültige Auszeichnung im Text" +#: libvips/colour/icc_transform.c:437 +#, fuzzy +msgid "no device profile" +msgstr "kein eingebettetes Profil" -#: libvips/conversion/im_text.c:252 -msgid "pangoft2 support disabled" -msgstr "Pangoft2-Unterstützung deaktiviert" +#: libvips/colour/icc_transform.c:612 libvips/colour/icc_transform.c:635 +#: libvips/colour/icc_transform.c:658 libvips/iofuncs/operation.c:442 +msgid "input" +msgstr "Eingabe" -#: libvips/conversion/im_zoom.c:331 -msgid "zoom factors should be >= 0" -msgstr "Zoomfaktoren sollten >=0 sein" +#: libvips/colour/icc_transform.c:612 libvips/colour/icc_transform.c:635 +#: libvips/colour/icc_transform.c:658 libvips/iofuncs/operation.c:443 +msgid "output" +msgstr "Ausgabe" -#. Make sure we won't get integer overflow. -#. -#: libvips/conversion/im_zoom.c:338 -msgid "zoom factors too large" -msgstr "Zoomfaktoren zu groß" +#: libvips/colour/icc_transform.c:631 +#, c-format +msgid "" +"fallback to suggested %s intent, as profile does not support %s %s intent" +msgstr "" -#: libvips/conversion/conver_dispatch.c:918 -#: libvips/inplace/inplace_dispatch.c:171 -msgid "vectors not same length" -msgstr "Vektoren ungleicher Länge" +#: libvips/colour/icc_transform.c:656 +#, c-format +msgid "profile does not support %s %s intent" +msgstr "" -#: libvips/conversion/extract.c:147 -msgid "bad extract area" -msgstr "falscher extrahierter Bereich" +#: libvips/colour/icc_transform.c:757 +msgid "unable to load or find any compatible input profile" +msgstr "" -#: libvips/conversion/extract.c:190 -msgid "extract an area from an image" -msgstr "einen Bereich eines Bildes extrahieren" +#: libvips/colour/icc_transform.c:775 +msgid "transform using ICC profiles" +msgstr "" -#: libvips/conversion/extract.c:318 -msgid "bad extract band" -msgstr "schlecht extrahiertes Band" +#: libvips/colour/icc_transform.c:779 libvips/resample/thumbnail.c:1030 +msgid "Intent" +msgstr "" -#: libvips/conversion/extract.c:347 -msgid "extract band from an image" -msgstr "Band aus einem Bild extrahieren" +#: libvips/colour/icc_transform.c:780 libvips/resample/thumbnail.c:1031 +msgid "Rendering intent" +msgstr "" -#: libvips/conversion/extract.c:359 -msgid "Band" -msgstr "Band" +#: libvips/colour/icc_transform.c:786 +msgid "PCS" +msgstr "" -#: libvips/conversion/extract.c:360 -msgid "Band to extract" -msgstr "zu extrahierendes Band" +#: libvips/colour/icc_transform.c:787 +msgid "Set Profile Connection Space" +msgstr "" -#: libvips/conversion/extract.c:366 -msgid "n" -msgstr "n" +#: libvips/colour/icc_transform.c:793 +msgid "Black point compensation" +msgstr "" -#: libvips/conversion/extract.c:367 -msgid "Number of bands to extract" -msgstr "Anzahl zu extrahierender Bänder" +#: libvips/colour/icc_transform.c:794 +msgid "Enable black point compensation" +msgstr "" -#: libvips/conversion/embed.c:430 libvips/iofuncs/image.c:1777 -msgid "bad dimensions" -msgstr "falsche Abmessungen" +#: libvips/colour/icc_transform.c:969 +msgid "import from device with ICC profile" +msgstr "" -#: libvips/conversion/embed.c:512 -msgid "embed an image in a larger image" -msgstr "ein Bild in ein größeres Bild einbetten" +#: libvips/colour/icc_transform.c:975 libvips/colour/icc_transform.c:1258 +msgid "Embedded" +msgstr "" -#: libvips/conversion/embed.c:523 -msgid "Left edge of input in output" -msgstr "linker Rand der Eingabe in der Ausgabe" +#: libvips/colour/icc_transform.c:976 libvips/colour/icc_transform.c:1259 +msgid "Use embedded input profile, if available" +msgstr "" -#: libvips/conversion/embed.c:530 -msgid "Top edge of input in output" -msgstr "oberer Rand der Eingabe in der Ausgabe" +#: libvips/colour/icc_transform.c:982 libvips/colour/icc_transform.c:1265 +#, fuzzy +msgid "Input profile" +msgstr "Profil" -#: libvips/conversion/embed.c:537 libvips/conversion/copy.c:332 -#: libvips/conversion/black.c:129 libvips/foreign/rawload.c:123 -#: libvips/iofuncs/image.c:846 -msgid "Image width in pixels" -msgstr "Bildbreite in Bildpunkten" +#: libvips/colour/icc_transform.c:983 libvips/colour/icc_transform.c:1266 +#, fuzzy +msgid "Filename to load input profile from" +msgstr "Name der Datei, aus der geladen werden soll" -#: libvips/conversion/embed.c:544 libvips/conversion/copy.c:339 -#: libvips/conversion/black.c:136 libvips/foreign/rawload.c:130 -#: libvips/iofuncs/image.c:853 -msgid "Image height in pixels" -msgstr "Bildhöhe in Bildpunkten" +#: libvips/colour/icc_transform.c:1046 libvips/colour/icc_transform.c:1212 +#, fuzzy +msgid "no output profile" +msgstr "kein eingebettetes Profil" -#: libvips/conversion/embed.c:550 -msgid "Extend" -msgstr "vergrößern" +#: libvips/colour/icc_transform.c:1141 +msgid "output to device with ICC profile" +msgstr "" -#: libvips/conversion/embed.c:551 -msgid "How to generate the extra pixels" -msgstr "Wie werden die zusätzlichen Bildpunkte erzeugt?" +#: libvips/colour/icc_transform.c:1147 libvips/colour/icc_transform.c:1251 +#, fuzzy +msgid "Output profile" +msgstr "Ausgabewert" -#: libvips/conversion/im_grid.c:164 -#: libvips/convolution/im_contrast_surface.c:140 libvips/iofuncs/image.c:710 -#: libvips/iofuncs/sinkscreen.c:1082 libvips/morphology/im_rank.c:342 -msgid "bad parameters" -msgstr "falsche Parameter" +#: libvips/colour/icc_transform.c:1148 libvips/colour/icc_transform.c:1252 +#, fuzzy +msgid "Filename to load output profile from" +msgstr "Name der Datei, aus der geladen werden soll" -#: libvips/conversion/im_grid.c:169 -msgid "bad grid geometry" -msgstr "falsche Gittergeometrie" +#: libvips/colour/icc_transform.c:1154 libvips/colour/icc_transform.c:1272 +#: libvips/colour/scRGB2BW.c:249 libvips/colour/scRGB2sRGB.c:282 +#: libvips/foreign/dzsave.c:2364 libvips/foreign/tiffsave.c:378 +msgid "Depth" +msgstr "" -#: libvips/conversion/join.c:210 -msgid "join a pair of images" -msgstr "ein Bilderpaar zusammenführen" +#: libvips/colour/icc_transform.c:1155 libvips/colour/icc_transform.c:1273 +#: libvips/colour/scRGB2BW.c:250 libvips/colour/scRGB2sRGB.c:283 +msgid "Output device space depth in bits" +msgstr "" -#: libvips/conversion/join.c:214 -msgid "in1" -msgstr "in1" +#: libvips/colour/icc_transform.c:1245 +msgid "transform between devices with ICC profiles" +msgstr "" -#: libvips/conversion/join.c:215 -msgid "First input image" -msgstr "erstes Eingabebild" +#: libvips/colour/icc_transform.c:1321 +msgid "unable to get media white point" +msgstr "weißer Medienpunkt kann nicht abgefragt werden" -#: libvips/conversion/join.c:220 -msgid "in2" -msgstr "in2" +#: libvips/colour/icc_transform.c:1416 +#, fuzzy +msgid "libvips configured without lcms support" +msgstr "VIPS wurde ohne FFT-Unterstützung konfiguriert" -#: libvips/conversion/join.c:221 -msgid "Second input image" -msgstr "zweites Eingabebild" +#: libvips/colour/Lab2LabQ.c:137 +msgid "transform float Lab to LabQ coding" +msgstr "" -#: libvips/conversion/join.c:226 -msgid "direction" -msgstr "Richtung" +#: libvips/colour/Lab2LabS.c:82 +msgid "transform float Lab to signed short" +msgstr "" -#: libvips/conversion/join.c:227 -msgid "Join left-right or up-down" -msgstr "von links nach rechts oder von oben nach unten zusammenführen" +#: libvips/colour/Lab2LCh.c:132 +msgid "transform Lab to LCh" +msgstr "" -#: libvips/conversion/join.c:240 -msgid "Shim" -msgstr "Scheibe" +#: libvips/colour/Lab2XYZ.c:177 +msgid "transform CIELAB to XYZ" +msgstr "" -#: libvips/conversion/join.c:241 -msgid "Pixels between images" -msgstr "Bildpunkte zwischen Bildern" +#: libvips/colour/Lab2XYZ.c:183 libvips/colour/XYZ2Lab.c:236 +msgid "Temperature" +msgstr "" -#: libvips/conversion/join.c:254 -msgid "Align" -msgstr "ausrichten" +#: libvips/colour/Lab2XYZ.c:184 +msgid "Color temperature" +msgstr "" -#: libvips/conversion/join.c:255 -msgid "Align on the low, centre or high coordinate edge" -msgstr "am Rand der unteren, mittleren oder höchsten Koordinate ausrichten" +#: libvips/colour/LabQ2Lab.c:125 +msgid "unpack a LabQ image to float Lab" +msgstr "" -#: libvips/conversion/rot.c:351 -msgid "rotate an image" -msgstr "ein Bild drehen" +#: libvips/colour/LabQ2LabS.c:104 +msgid "unpack a LabQ image to short Lab" +msgstr "" -#: libvips/conversion/rot.c:361 -msgid "Angle" -msgstr "Winkel" +#: libvips/colour/LabQ2sRGB.c:549 +#, fuzzy +msgid "convert a LabQ image to sRGB" +msgstr "ein Bild invertieren" -#: libvips/conversion/rot.c:362 -msgid "Angle to rotate image" -msgstr "Winkel zum Drehen eines Bildes" +#: libvips/colour/LabS2Lab.c:78 +msgid "transform signed short Lab to float" +msgstr "" -#: libvips/conversion/flip.c:236 -msgid "flip an image" -msgstr "ein Bild umdrehen" +#: libvips/colour/LabS2LabQ.c:127 +msgid "transform short Lab to LabQ coding" +msgstr "" -#: libvips/conversion/flip.c:246 -msgid "Direction" -msgstr "Richtung" +#: libvips/colour/LCh2Lab.c:111 +msgid "transform LCh to Lab" +msgstr "" -#: libvips/conversion/flip.c:247 -msgid "Direction to flip image" -msgstr "Richtung, nach der das Bild umgedreht werden soll" +#: libvips/colour/LCh2UCS.c:206 libvips/colour/UCS2LCh.c:273 +msgid "transform LCh to CMC" +msgstr "" -#: libvips/conversion/copy.c:314 -msgid "copy an image" -msgstr "ein Bild kopieren" +#: libvips/colour/profile_load.c:123 +#, fuzzy, c-format +msgid "unable to load profile \"%s\"" +msgstr "Profil »%s« kann nicht geöffnet werden" -#: libvips/conversion/copy.c:324 -msgid "Swap" -msgstr "austauschen" +# Portable Pixmap +#: libvips/colour/profile_load.c:147 +#, fuzzy +msgid "load named ICC profile" +msgstr "PPM aus Datei laden" -#: libvips/conversion/copy.c:325 -msgid "Swap bytes in image between little and big-endian" -msgstr "Byte im Bild zwischen Little- und Big-Endian austauschen" +#: libvips/colour/profile_load.c:151 +msgid "Name" +msgstr "" -#: libvips/conversion/copy.c:345 libvips/conversion/black.c:142 -#: libvips/foreign/rawload.c:136 libvips/iofuncs/image.c:859 -msgid "Bands" -msgstr "Bänder" +#: libvips/colour/profile_load.c:152 +#, fuzzy +msgid "Profile name" +msgstr "Dateiname" -#: libvips/conversion/copy.c:346 libvips/conversion/black.c:143 -#: libvips/foreign/rawload.c:137 libvips/iofuncs/image.c:860 -msgid "Number of bands in image" -msgstr "Anzahl der Bänder in einem Bild" +#: libvips/colour/profile_load.c:158 libvips/foreign/foreign.c:1922 +#, fuzzy +msgid "Profile" +msgstr "Profil" -#: libvips/conversion/copy.c:353 libvips/iofuncs/image.c:867 -msgid "Pixel format in image" -msgstr "Bildpunktformat im Bild" +#: libvips/colour/profile_load.c:159 +#, fuzzy +msgid "Loaded profile" +msgstr "kein eingebettetes Profil" -#: libvips/conversion/copy.c:359 libvips/iofuncs/image.c:873 -msgid "Coding" -msgstr "Kodierung" +#: libvips/colour/rad2float.c:184 +#, fuzzy +msgid "unpack Radiance coding to float RGB" +msgstr "Nur Radiance-Kodierung" -#: libvips/conversion/copy.c:360 libvips/iofuncs/image.c:874 -msgid "Pixel coding" -msgstr "Bildpunktkodierung" +#: libvips/colour/scRGB2BW.c:231 +msgid "convert scRGB to BW" +msgstr "" -#: libvips/conversion/copy.c:366 libvips/iofuncs/image.c:880 -msgid "Interpretation" -msgstr "Interpretation" +#: libvips/colour/scRGB2sRGB.c:264 +#, fuzzy +msgid "convert an scRGB image to sRGB" +msgstr "ein Bild invertieren" -#: libvips/conversion/copy.c:367 libvips/iofuncs/image.c:881 -msgid "Pixel interpretation" -msgstr "Bildpunktinterpretation" +#: libvips/colour/scRGB2XYZ.c:185 +msgid "transform scRGB to XYZ" +msgstr "" -#: libvips/conversion/copy.c:373 libvips/foreign/tiffsave.c:249 -#: libvips/iofuncs/image.c:887 -msgid "Xres" -msgstr "Xres" +#: libvips/colour/sRGB2HSV.c:133 +msgid "transform sRGB to HSV" +msgstr "" -#: libvips/conversion/copy.c:374 libvips/foreign/tiffsave.c:250 -#: libvips/iofuncs/image.c:888 -msgid "Horizontal resolution in pixels/mm" -msgstr "horizontale Auflösung in Bildpunkten/mm" +#: libvips/colour/sRGB2scRGB.c:282 +#, fuzzy +msgid "convert an sRGB image to scRGB" +msgstr "ein Bild invertieren" -#: libvips/conversion/copy.c:380 libvips/foreign/tiffsave.c:256 -#: libvips/iofuncs/image.c:894 -msgid "Yres" -msgstr "Yres" +#: libvips/colour/XYZ2CMYK.c:113 libvips/colour/XYZ2CMYK.c:193 +msgid "transform XYZ to CMYK" +msgstr "" -#: libvips/conversion/copy.c:381 libvips/foreign/tiffsave.c:257 -#: libvips/iofuncs/image.c:895 -msgid "Vertical resolution in pixels/mm" -msgstr "vertikale Auflösung in Bildpunkten/mm" +#: libvips/colour/XYZ2Lab.c:230 +msgid "transform XYZ to Lab" +msgstr "" -#: libvips/conversion/copy.c:387 libvips/iofuncs/image.c:901 -msgid "Xoffset" -msgstr "Xoffset" +#: libvips/colour/XYZ2Lab.c:237 +msgid "Colour temperature" +msgstr "" -#: libvips/conversion/copy.c:388 libvips/iofuncs/image.c:902 -msgid "Horizontal offset of origin" -msgstr "horizontaler Versatz vom Ursprung" +#: libvips/colour/XYZ2scRGB.c:194 +msgid "transform XYZ to scRGB" +msgstr "" -#: libvips/conversion/copy.c:394 libvips/iofuncs/image.c:908 -msgid "Yoffset" -msgstr "Yoffset" +#: libvips/colour/XYZ2Yxy.c:98 +msgid "transform XYZ to Yxy" +msgstr "" -#: libvips/conversion/copy.c:395 libvips/iofuncs/image.c:909 -msgid "Vertical offset of origin" -msgstr "vertikaler Versatz vom Ursprung" +#: libvips/colour/Yxy2XYZ.c:103 +msgid "transform Yxy to XYZ" +msgstr "" -#: libvips/conversion/bandary.c:127 -msgid "no input images" -msgstr "keine Eingabebilder" +#: libvips/conversion/addalpha.c:84 +msgid "append an alpha channel" +msgstr "" -#: libvips/conversion/bandary.c:173 -msgid "operations on image bands" -msgstr "Transaktionen für Bänder von Bildern" +#: libvips/conversion/arrayjoin.c:388 +#, fuzzy +msgid "join an array of images" +msgstr "ein Bilderpaar zusammenführen" -#: libvips/conversion/conversion.c:85 -msgid "conversion operations" -msgstr "Umwandlungstransaktionen" +#: libvips/conversion/arrayjoin.c:402 +#, fuzzy +msgid "Number of images across grid" +msgstr "Anzahl der Patches über ein Diagramm" -#: libvips/conversion/recomb.c:160 -msgid "bands in must equal matrix width" -msgstr "»in«-Bänder müssen die gleiche Breite wie die Matrix haben" +#: libvips/conversion/arrayjoin.c:408 libvips/conversion/join.c:263 +msgid "Shim" +msgstr "Scheibe" -#: libvips/conversion/recomb.c:196 -msgid "linear recombination with matrix" -msgstr "lineare Neukombinierung mit der Matrix" +#: libvips/conversion/arrayjoin.c:409 libvips/conversion/join.c:264 +msgid "Pixels between images" +msgstr "Bildpunkte zwischen Bildern" -#: libvips/conversion/recomb.c:206 -msgid "M" -msgstr "M" +#: libvips/conversion/arrayjoin.c:416 libvips/conversion/join.c:271 +msgid "Colour for new pixels" +msgstr "Farbe für neue Bildpunkte" -#: libvips/conversion/recomb.c:207 -msgid "matrix of coefficients" -msgstr "Matrix der Koeffizienten" +#: libvips/conversion/arrayjoin.c:422 +#, fuzzy +msgid "Horizontal align" +msgstr "horizontaler Versatz vom Ursprung" -#: libvips/conversion/replicate.c:192 -msgid "replicate an image" -msgstr "ein Bild nachmachen" +#: libvips/conversion/arrayjoin.c:423 +#, fuzzy +msgid "Align on the left, centre or right" +msgstr "am Rand der unteren, mittleren oder höchsten Koordinate ausrichten" -#: libvips/conversion/replicate.c:203 -msgid "Repeat this many times horizontally" -msgstr "horizontal so oft wiederholen" +#: libvips/conversion/arrayjoin.c:429 +#, fuzzy +msgid "Vertical align" +msgstr "vertikaler Versatz vom Ursprung" -#: libvips/conversion/replicate.c:210 -msgid "Repeat this many times vertically" -msgstr "vertikal so oft wiederholen" +#: libvips/conversion/arrayjoin.c:430 +#, fuzzy +msgid "Align on the top, centre or bottom" +msgstr "am Rand der unteren, mittleren oder höchsten Koordinate ausrichten" -#: libvips/conversion/black.c:124 -msgid "make a black image" -msgstr "ein schwarzes Bild erstellen" +#: libvips/conversion/arrayjoin.c:436 +#, fuzzy +msgid "Horizontal spacing" +msgstr "horizontaler Versatz vom Ursprung" -#: libvips/conversion/im_msb.c:134 libvips/conversion/im_msb.c:213 -msgid "unknown coding" -msgstr "unbekannte Kodierung" +#: libvips/conversion/arrayjoin.c:437 +#, fuzzy +msgid "Horizontal spacing between images" +msgstr "Bildpunkte zwischen Bildern" -#: libvips/conversion/im_msb.c:169 libvips/resample/im_rightshift_size.c:116 -msgid "bad arguments" -msgstr "falsche Argumente" +#: libvips/conversion/arrayjoin.c:443 +msgid "Vertical spacing" +msgstr "" -#: libvips/conversion/im_msb.c:183 libvips/conversion/im_msb.c:200 -msgid "image does not have that many bands" -msgstr "Bild hat nicht so viele Bänder" +#: libvips/conversion/arrayjoin.c:444 +#, fuzzy +msgid "Vertical spacing between images" +msgstr "Bildpunkte zwischen Bildern" -#: libvips/conversion/im_system_image.c:76 -#, c-format -msgid "command failed: \"%s\"" -msgstr "Befehl fehlgeschlagen: »%s«" +#: libvips/conversion/autorot.c:203 +msgid "autorotate image by exif tag" +msgstr "" -#: libvips/conversion/im_subsample.c:202 -msgid "factors should both be >= 1" -msgstr "beide Faktoren sollten >=1 sein" +#: libvips/conversion/autorot.c:213 libvips/conversion/rot45.c:274 +#: libvips/conversion/rot.c:371 libvips/convolution/compass.c:170 +#: libvips/foreign/dzsave.c:2378 libvips/mosaicing/mosaic.c:281 +#: libvips/resample/similarity.c:207 libvips/resample/similarity.c:276 +msgid "Angle" +msgstr "Winkel" -#: libvips/conversion/im_subsample.c:221 libvips/resample/im_shrink.c:286 -msgid "image has shrunk to nothing" -msgstr "Bild ist zu nichts geschrumpft" +#: libvips/conversion/autorot.c:214 +msgid "Angle image was rotated by" +msgstr "" -#: libvips/conversion/bandjoin.c:165 -msgid "bandwise join a set of images" -msgstr "einen Satz Bilder bandweise zusammenführen" +#: libvips/conversion/autorot.c:220 +msgid "Flip" +msgstr "" -#: libvips/conversion/bandjoin.c:172 -msgid "Array of input images" -msgstr "Feld von Eingabebildern" +#: libvips/conversion/autorot.c:221 +msgid "Whether the image was flipped or not" +msgstr "" -#: libvips/convolution/im_contrast_surface.c:147 -msgid "parameters would result in zero size output image" -msgstr "Parameter würden zu einem Ausgabebild der Größe Null führen" +#: libvips/conversion/bandary.c:211 libvips/conversion/bandary.c:280 +#: libvips/conversion/composite.cpp:1299 +msgid "no input images" +msgstr "keine Eingabebilder" -#: libvips/convolution/im_aconvsep.c:130 libvips/convolution/im_aconv.c:223 -#: libvips/convolution/im_aconv.c:229 libvips/convolution/im_aconv.c:750 -msgid "mask too complex" -msgstr "Maske zu komplex" +#: libvips/conversion/bandary.c:257 +msgid "operations on image bands" +msgstr "Transaktionen für Bänder von Bildern" -#: libvips/convolution/im_aconvsep.c:798 libvips/convolution/im_conv.c:1038 -#: libvips/convolution/im_conv_f.c:340 libvips/convolution/im_aconv.c:980 -#: libvips/convolution/im_aconv.c:1201 libvips/morphology/morphology.c:721 -msgid "image too small for mask" -msgstr "Bild zu klein für Maske" +#: libvips/conversion/bandbool.c:75 +#, fuzzy, c-format +msgid "operator %s not supported across image bands" +msgstr "Transaktionen für Bänder von Bildern" -#: libvips/convolution/im_conv.c:215 -#, c-format -msgid "%d overflows and %d underflows detected" -msgstr "%d Über- und %d Unterläufe entdeckt" +#: libvips/conversion/bandbool.c:225 +#, fuzzy +msgid "boolean operation across image bands" +msgstr "Transaktionen für Bänder von Bildern" -#: libvips/convolution/im_conv.c:1125 libvips/convolution/im_conv_f.c:403 -msgid "expect 1xN or Nx1 input mask" -msgstr "1xN- oder Nx1-Eingabemaske wird erwartet" +#: libvips/conversion/bandbool.c:233 libvips/conversion/bandmean.c:213 +#: libvips/conversion/recomb.c:225 libvips/convolution/convolution.c:129 +#: libvips/convolution/correlation.c:151 libvips/morphology/morphology.c:122 +#: libvips/resample/resample.c:141 libvips/resample/thumbnail.c:1783 +msgid "Input image argument" +msgstr "Eingabebildargument" -# ref und in sind Objekte -#: libvips/convolution/im_fastcor.c:134 libvips/convolution/im_spcor.c:247 -msgid "ref not smaller than or equal to in" -msgstr "»ref« nicht kleiner oder gleich »in«" +#: libvips/conversion/bandfold.c:123 +msgid "@factor must be a factor of image width" +msgstr "" -#: libvips/convolution/im_sharpen.c:325 libvips/histograms_lut/im_stdif.c:196 -msgid "parameters out of range" -msgstr "Parameter außerhalb des Bereichs" +#: libvips/conversion/bandfold.c:155 +msgid "fold up x axis into bands" +msgstr "" -#: libvips/foreign/rawload.c:107 -msgid "load raw data from a file" -msgstr "Rohdaten aus einer Datei laden" +#: libvips/conversion/bandfold.c:167 libvips/conversion/bandunfold.c:170 +#: libvips/create/eye.c:108 +#, fuzzy +msgid "Factor" +msgstr "Q-Faktor" -#: libvips/foreign/rawload.c:115 libvips/foreign/fitssave.c:128 -#: libvips/foreign/ppmload.c:126 libvips/foreign/radload.c:126 -#: libvips/foreign/openslideload.c:176 libvips/foreign/tiffload.c:142 -#: libvips/foreign/fitsload.c:116 libvips/foreign/vipssave.c:125 -#: libvips/foreign/radsave.c:119 libvips/foreign/openexrload.c:137 -#: libvips/foreign/analyzeload.c:126 libvips/foreign/pngload.c:136 -#: libvips/foreign/tiffsave.c:169 libvips/foreign/vipsload.c:133 -#: libvips/foreign/magickload.c:146 libvips/foreign/matload.c:128 -#: libvips/foreign/jpegload.c:245 libvips/foreign/jpegsave.c:193 -#: libvips/foreign/rawsave.c:166 libvips/foreign/ppmsave.c:118 -#: libvips/foreign/csvsave.c:121 libvips/foreign/csvload.c:132 -#: libvips/foreign/pngsave.c:166 libvips/iofuncs/image.c:915 -msgid "Filename" -msgstr "Dateiname" +#: libvips/conversion/bandfold.c:168 +msgid "Fold by this factor" +msgstr "" -#: libvips/foreign/rawload.c:116 libvips/foreign/ppmload.c:127 -#: libvips/foreign/radload.c:127 libvips/foreign/openslideload.c:177 -#: libvips/foreign/tiffload.c:143 libvips/foreign/fitsload.c:117 -#: libvips/foreign/openexrload.c:138 libvips/foreign/analyzeload.c:127 -#: libvips/foreign/pngload.c:137 libvips/foreign/vipsload.c:134 -#: libvips/foreign/magickload.c:147 libvips/foreign/matload.c:129 -#: libvips/foreign/jpegload.c:246 libvips/foreign/csvload.c:133 -msgid "Filename to load from" -msgstr "Name der Datei, aus der geladen werden soll" +#: libvips/conversion/bandjoin.c:195 +msgid "bandwise join a set of images" +msgstr "einen Satz Bilder bandweise zusammenführen" -#: libvips/foreign/rawload.c:143 libvips/iofuncs/image.c:943 -msgid "Size of header" -msgstr "Größe der Kopfdaten" +#: libvips/conversion/bandjoin.c:430 +#, fuzzy +msgid "append a constant band to an image" +msgstr "Band aus einem Bild extrahieren" -#: libvips/foreign/rawload.c:144 libvips/iofuncs/image.c:944 -msgid "Offset in bytes from start of file" -msgstr "Versatz in Byte vom Anfang der Datei" +#: libvips/conversion/bandjoin.c:442 +msgid "Constants" +msgstr "" -#: libvips/foreign/fitssave.c:119 -# http://de.wikipedia.org/wiki/Flexible_Image_Transport_System -msgid "save image to fits file" -msgstr "Bild in FITS-Datei speichern" +#: libvips/conversion/bandjoin.c:443 +#, fuzzy +msgid "Array of constants to add" +msgstr "Feld aus Konstanten" -#: libvips/foreign/fitssave.c:129 libvips/foreign/vipssave.c:126 -#: libvips/foreign/radsave.c:120 libvips/foreign/tiffsave.c:170 -#: libvips/foreign/jpegsave.c:194 libvips/foreign/rawsave.c:167 -#: libvips/foreign/ppmsave.c:119 libvips/foreign/csvsave.c:122 -#: libvips/foreign/pngsave.c:167 -msgid "Filename to save to" -msgstr "Name der Datei in die gespeichert werden soll" +#: libvips/conversion/bandmean.c:206 +msgid "band-wise average" +msgstr "bandweiser Durchschnitt" -#: libvips/foreign/ppmload.c:114 -# Portable Pixmap -msgid "load ppm from file" -msgstr "PPM aus Datei laden" +#: libvips/conversion/bandrank.c:248 +#, fuzzy +msgid "band-wise rank of a set of images" +msgstr "einen Satz Bilder bandweise zusammenführen" -#: libvips/foreign/radload.c:114 -msgid "load a Radiance image from a file" -msgstr "ein Radiance-Bild aus einer Datei laden" +#: libvips/conversion/bandrank.c:262 +msgid "Select this band element from sorted list" +msgstr "" -#: libvips/foreign/openslideload.c:159 -msgid "load file with OpenSlide" -msgstr "Datei mit OpenSlide laden" +#: libvips/conversion/bandunfold.c:126 +msgid "@factor must be a factor of image bands" +msgstr "" -#: libvips/foreign/openslideload.c:183 -msgid "Level" -msgstr "Ebene" +#: libvips/conversion/bandunfold.c:158 +msgid "unfold image bands into x axis" +msgstr "" -#: libvips/foreign/openslideload.c:184 -msgid "Load this level from the file" -msgstr "diese Ebene aus der Datei laden" +#: libvips/conversion/bandunfold.c:171 +msgid "Unfold by this factor" +msgstr "" + +#: libvips/conversion/byteswap.c:232 +#, fuzzy +msgid "byteswap an image" +msgstr "ein Bild drehen" + +#: libvips/conversion/cache.c:98 libvips/conversion/tilecache.c:392 +msgid "cache an image" +msgstr "ein Bild zwischenspeichern" + +#: libvips/conversion/cache.c:114 libvips/conversion/tilecache.c:800 +#: libvips/foreign/dzsave.c:2451 libvips/foreign/jp2ksave.c:971 +#: libvips/foreign/tiffsave.c:287 +msgid "Tile width" +msgstr "Kachelbreite" + +#: libvips/conversion/cache.c:115 libvips/conversion/tilecache.c:801 +#: libvips/foreign/dzsave.c:2452 libvips/foreign/jp2ksave.c:972 +#: libvips/foreign/tiffsave.c:288 +msgid "Tile width in pixels" +msgstr "Kachelbreite in Bildpunkten" + +#: libvips/conversion/cache.c:121 libvips/conversion/grid.c:205 +#: libvips/conversion/sequential.c:249 libvips/conversion/tilecache.c:404 +#: libvips/foreign/dzsave.c:2458 libvips/foreign/jp2ksave.c:978 +#: libvips/foreign/tiffsave.c:294 +msgid "Tile height" +msgstr "Kachelhöhe" + +#: libvips/conversion/cache.c:122 libvips/conversion/sequential.c:250 +#: libvips/conversion/tilecache.c:405 libvips/foreign/dzsave.c:2459 +#: libvips/foreign/jp2ksave.c:979 libvips/foreign/tiffsave.c:295 +msgid "Tile height in pixels" +msgstr "Kachelhöhe in Bildpunkten" + +#: libvips/conversion/cache.c:128 libvips/conversion/tilecache.c:807 +msgid "Max tiles" +msgstr "Kacheln maximal" + +#: libvips/conversion/cache.c:129 libvips/conversion/tilecache.c:808 +msgid "Maximum number of tiles to cache" +msgstr "maximale Anzahl von Kacheln, die zwischengespeichert werden soll" + +#: libvips/conversion/cast.c:524 +msgid "cast an image" +msgstr "ein Bild umwandeln" + +#: libvips/conversion/cast.c:536 libvips/conversion/copy.c:305 +#: libvips/foreign/ppmsave.c:506 libvips/foreign/rawload.c:174 +#: libvips/foreign/vips2magick.c:482 libvips/iofuncs/image.c:1123 +msgid "Format" +msgstr "Format" + +#: libvips/conversion/cast.c:537 +msgid "Format to cast to" +msgstr "Format, in das umgewandelt werden soll" + +#: libvips/conversion/cast.c:543 +msgid "Shift" +msgstr "" + +#: libvips/conversion/cast.c:544 +msgid "Shift integer values up and down" +msgstr "" + +#: libvips/conversion/composite.cpp:1304 +#, fuzzy, c-format +msgid "must be 1 or %d blend modes" +msgstr "Bild muss ein oder %d Bänder haben" + +#: libvips/conversion/composite.cpp:1314 +#, c-format +msgid "blend mode index %d (%d) invalid" +msgstr "" + +#: libvips/conversion/composite.cpp:1413 +#, fuzzy +msgid "images do not have same numbers of bands" +msgstr "Bilder müssen die gleiche Anzahl Bänder haben" + +#: libvips/conversion/composite.cpp:1420 +#, fuzzy +msgid "too many input bands" +msgstr "zu viele Eingabebilder" + +#: libvips/conversion/composite.cpp:1430 +#, fuzzy +msgid "unsupported compositing space" +msgstr "nicht unterstützter Farbraum %d" + +#: libvips/conversion/composite.cpp:1478 +#, fuzzy +msgid "blend images together" +msgstr "falscher Bildtyp" + +#: libvips/conversion/composite.cpp:1484 +msgid "Compositing space" +msgstr "" + +#: libvips/conversion/composite.cpp:1485 +msgid "Composite images in this colour space" +msgstr "" + +#: libvips/conversion/composite.cpp:1491 libvips/conversion/smartcrop.c:474 +#: libvips/resample/affine.c:706 libvips/resample/mapim.c:581 +msgid "Premultiplied" +msgstr "" + +#: libvips/conversion/composite.cpp:1492 libvips/resample/affine.c:707 +#: libvips/resample/mapim.c:582 +msgid "Images have premultiplied alpha" +msgstr "" + +#: libvips/conversion/composite.cpp:1540 +#, c-format +msgid "must be %d x coordinates" +msgstr "" + +#: libvips/conversion/composite.cpp:1548 +#, c-format +msgid "must be %d y coordinates" +msgstr "" + +#: libvips/conversion/composite.cpp:1574 +msgid "blend an array of images with an array of blend modes" +msgstr "" + +#: libvips/conversion/composite.cpp:1580 +#, fuzzy +msgid "Inputs" +msgstr "Eingabe" + +#: libvips/conversion/composite.cpp:1587 +#, fuzzy +msgid "Blend modes" +msgstr "Öffnen-Modus" + +#: libvips/conversion/composite.cpp:1588 +msgid "Array of VipsBlendMode to join with" +msgstr "" + +#: libvips/conversion/composite.cpp:1594 +msgid "x coordinates" +msgstr "" + +#: libvips/conversion/composite.cpp:1595 +#, fuzzy +msgid "Array of x coordinates to join at" +msgstr "Feld aus Konstanten" + +#: libvips/conversion/composite.cpp:1601 +msgid "y coordinates" +msgstr "" + +#: libvips/conversion/composite.cpp:1602 +#, fuzzy +msgid "Array of y coordinates to join at" +msgstr "Feld aus Konstanten" + +#: libvips/conversion/composite.cpp:1708 +msgid "blend a pair of images with a blend mode" +msgstr "" + +#: libvips/conversion/composite.cpp:1714 +msgid "Base" +msgstr "" + +#: libvips/conversion/composite.cpp:1715 +#, fuzzy +msgid "Base image" +msgstr "sonst Bild" + +#: libvips/conversion/composite.cpp:1720 +msgid "Overlay" +msgstr "" + +#: libvips/conversion/composite.cpp:1721 +#, fuzzy +msgid "Overlay image" +msgstr "Zeilensprungbild" + +#: libvips/conversion/composite.cpp:1726 +#, fuzzy +msgid "Blend mode" +msgstr "Öffnen-Modus" + +#: libvips/conversion/composite.cpp:1727 +msgid "VipsBlendMode to join with" +msgstr "" + +#: libvips/conversion/composite.cpp:1734 +msgid "x position of overlay" +msgstr "" + +#: libvips/conversion/composite.cpp:1741 +msgid "y position of overlay" +msgstr "" + +#: libvips/conversion/conversion.c:342 +msgid "conversion operations" +msgstr "Umwandlungstransaktionen" + +#: libvips/conversion/copy.c:235 +#, fuzzy +msgid "must not change pel size" +msgstr "Bilder passen in der Bildpunktgröße nicht zusammen" + +#: libvips/conversion/copy.c:260 +msgid "copy an image" +msgstr "ein Bild kopieren" + +#: libvips/conversion/copy.c:277 +msgid "Swap" +msgstr "austauschen" + +#: libvips/conversion/copy.c:278 +msgid "Swap bytes in image between little and big-endian" +msgstr "Byte im Bild zwischen Little- und Big-Endian austauschen" + +#: libvips/conversion/copy.c:285 libvips/conversion/embed.c:575 +#: libvips/create/black.c:141 libvips/create/fractsurf.c:105 +#: libvips/create/gaussnoise.c:168 libvips/create/perlin.c:295 +#: libvips/create/point.c:142 libvips/create/sdf.c:305 +#: libvips/create/worley.c:308 libvips/create/xyz.c:192 +#: libvips/foreign/rawload.c:147 libvips/iofuncs/image.c:1103 +msgid "Image width in pixels" +msgstr "Bildbreite in Bildpunkten" + +#: libvips/conversion/copy.c:292 libvips/conversion/embed.c:582 +#: libvips/create/black.c:148 libvips/create/fractsurf.c:112 +#: libvips/create/gaussnoise.c:175 libvips/create/perlin.c:302 +#: libvips/create/point.c:149 libvips/create/sdf.c:312 +#: libvips/create/worley.c:315 libvips/create/xyz.c:199 +#: libvips/foreign/rawload.c:154 libvips/iofuncs/image.c:1110 +msgid "Image height in pixels" +msgstr "Bildhöhe in Bildpunkten" + +#: libvips/conversion/copy.c:298 libvips/create/black.c:154 +#: libvips/create/identity.c:143 libvips/foreign/rawload.c:160 +#: libvips/iofuncs/image.c:1116 +msgid "Bands" +msgstr "Bänder" + +#: libvips/conversion/copy.c:299 libvips/create/black.c:155 +#: libvips/foreign/rawload.c:161 libvips/iofuncs/image.c:1117 +msgid "Number of bands in image" +msgstr "Anzahl der Bänder in einem Bild" + +#: libvips/conversion/copy.c:306 libvips/foreign/rawload.c:175 +#: libvips/iofuncs/image.c:1124 +msgid "Pixel format in image" +msgstr "Bildpunktformat im Bild" + +#: libvips/conversion/copy.c:312 libvips/iofuncs/image.c:1130 +msgid "Coding" +msgstr "Kodierung" + +#: libvips/conversion/copy.c:313 libvips/iofuncs/image.c:1131 +msgid "Pixel coding" +msgstr "Bildpunktkodierung" + +#: libvips/conversion/copy.c:319 libvips/foreign/rawload.c:181 +#: libvips/iofuncs/image.c:1137 +msgid "Interpretation" +msgstr "Interpretation" + +#: libvips/conversion/copy.c:320 libvips/foreign/rawload.c:182 +#: libvips/iofuncs/image.c:1138 +msgid "Pixel interpretation" +msgstr "Bildpunktinterpretation" + +#: libvips/conversion/copy.c:326 libvips/foreign/tiffsave.c:329 +#: libvips/iofuncs/image.c:1144 +msgid "Xres" +msgstr "Xres" + +#: libvips/conversion/copy.c:327 libvips/foreign/tiffsave.c:330 +#: libvips/iofuncs/image.c:1145 +msgid "Horizontal resolution in pixels/mm" +msgstr "horizontale Auflösung in Bildpunkten/mm" + +#: libvips/conversion/copy.c:333 libvips/foreign/tiffsave.c:336 +#: libvips/iofuncs/image.c:1151 +msgid "Yres" +msgstr "Yres" + +#: libvips/conversion/copy.c:334 libvips/foreign/tiffsave.c:337 +#: libvips/iofuncs/image.c:1152 +msgid "Vertical resolution in pixels/mm" +msgstr "vertikale Auflösung in Bildpunkten/mm" + +#: libvips/conversion/copy.c:340 libvips/iofuncs/image.c:1158 +msgid "Xoffset" +msgstr "Xoffset" + +#: libvips/conversion/copy.c:341 libvips/iofuncs/image.c:1159 +msgid "Horizontal offset of origin" +msgstr "horizontaler Versatz vom Ursprung" + +#: libvips/conversion/copy.c:347 libvips/iofuncs/image.c:1165 +msgid "Yoffset" +msgstr "Yoffset" + +#: libvips/conversion/copy.c:348 libvips/iofuncs/image.c:1166 +msgid "Vertical offset of origin" +msgstr "vertikaler Versatz vom Ursprung" + +#: libvips/conversion/embed.c:479 libvips/foreign/heifload.c:571 +#: libvips/foreign/svgload.c:502 libvips/iofuncs/image.c:3143 +msgid "bad dimensions" +msgstr "falsche Abmessungen" + +#: libvips/conversion/embed.c:561 libvips/conversion/embed.c:652 +msgid "embed an image in a larger image" +msgstr "ein Bild in ein größeres Bild einbetten" + +#: libvips/conversion/embed.c:588 libvips/resample/affine.c:692 +#: libvips/resample/mapim.c:567 +msgid "Extend" +msgstr "vergrößern" + +#: libvips/conversion/embed.c:589 libvips/resample/affine.c:693 +#: libvips/resample/mapim.c:568 +msgid "How to generate the extra pixels" +msgstr "Wie werden die zusätzlichen Bildpunkte erzeugt?" + +#: libvips/conversion/embed.c:657 libvips/conversion/wrap.c:126 +msgid "Left edge of input in output" +msgstr "linker Rand der Eingabe in der Ausgabe" + +#: libvips/conversion/embed.c:664 libvips/conversion/wrap.c:133 +msgid "Top edge of input in output" +msgstr "oberer Rand der Eingabe in der Ausgabe" + +#: libvips/conversion/embed.c:806 +#, fuzzy +msgid "place an image within a larger image with a certain gravity" +msgstr "ein Bild in ein größeres Bild einbetten" + +#: libvips/conversion/embed.c:811 libvips/conversion/flip.c:246 +#: libvips/conversion/join.c:249 libvips/morphology/countlines.c:146 +#: libvips/mosaicing/merge.c:140 libvips/mosaicing/mosaic1.c:516 +#: libvips/mosaicing/mosaic.c:197 +msgid "Direction" +msgstr "Richtung" + +#: libvips/conversion/embed.c:812 +msgid "Direction to place image within width/height" +msgstr "" + +#: libvips/conversion/extract.c:150 libvips/conversion/smartcrop.c:341 +msgid "bad extract area" +msgstr "falscher extrahierter Bereich" + +#: libvips/conversion/extract.c:188 libvips/conversion/smartcrop.c:429 +msgid "extract an area from an image" +msgstr "einen Bereich eines Bildes extrahieren" + +#: libvips/conversion/extract.c:398 +msgid "bad extract band" +msgstr "schlecht extrahiertes Band" + +#: libvips/conversion/extract.c:426 +msgid "extract band from an image" +msgstr "Band aus einem Bild extrahieren" + +#: libvips/conversion/extract.c:439 +msgid "Band to extract" +msgstr "zu extrahierendes Band" + +#: libvips/conversion/extract.c:445 libvips/foreign/heifload.c:1090 +#: libvips/foreign/jxlload.c:1139 libvips/foreign/magick6load.c:148 +#: libvips/foreign/magick7load.c:389 libvips/foreign/nsgifload.c:627 +#: libvips/foreign/pdfiumload.c:702 libvips/foreign/popplerload.c:552 +#: libvips/foreign/tiffload.c:203 libvips/foreign/webpload.c:185 +msgid "n" +msgstr "n" + +#: libvips/conversion/extract.c:446 +msgid "Number of bands to extract" +msgstr "Anzahl zu extrahierender Bänder" + +#: libvips/conversion/falsecolour.c:374 +#, fuzzy +msgid "false-color an image" +msgstr "ein Bild einfügen" + +# http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650& +# db=man&fname=/usr/share/catman/p_man/cat3/il_c/ilAbsImg.z +#: libvips/conversion/flatten.c:413 +#, fuzzy +msgid "flatten alpha out of an image" +msgstr "absoluter Wert eines Bildes" + +#: libvips/conversion/flatten.c:426 libvips/foreign/foreign.c:1909 +#: libvips/resample/affine.c:700 libvips/resample/mapim.c:575 +#: libvips/resample/similarity.c:134 +#, fuzzy +msgid "Background value" +msgstr "Hintergrund" + +#: libvips/conversion/flatten.c:432 libvips/conversion/premultiply.c:267 +#: libvips/conversion/unpremultiply.c:329 +msgid "Maximum alpha" +msgstr "" + +#: libvips/conversion/flatten.c:433 libvips/conversion/premultiply.c:268 +#: libvips/conversion/unpremultiply.c:330 +#, fuzzy +msgid "Maximum value of alpha channel" +msgstr "Maximalwert des Bildes" + +#: libvips/conversion/flip.c:236 +msgid "flip an image" +msgstr "ein Bild umdrehen" + +#: libvips/conversion/flip.c:247 +msgid "Direction to flip image" +msgstr "Richtung, nach der das Bild umgedreht werden soll" + +#: libvips/conversion/gamma.c:136 +#, fuzzy +msgid "gamma an image" +msgstr "ein Bild umwandeln" + +#: libvips/conversion/gamma.c:148 libvips/conversion/scale.c:168 +msgid "Exponent" +msgstr "" + +#: libvips/conversion/gamma.c:149 +#, fuzzy +msgid "Gamma factor" +msgstr "Q-Faktor" + +#: libvips/conversion/grid.c:165 +msgid "bad grid geometry" +msgstr "falsche Gittergeometrie" + +#: libvips/conversion/grid.c:195 +#, fuzzy +msgid "grid an image" +msgstr "ein Bild umdrehen" + +#: libvips/conversion/grid.c:206 +msgid "Chop into tiles this high" +msgstr "" + +#: libvips/conversion/grid.c:213 +#, fuzzy +msgid "Number of tiles across" +msgstr "Anzahl der Patches über ein Diagramm" + +#: libvips/conversion/grid.c:220 +#, fuzzy +msgid "Number of tiles down" +msgstr "Anzahl der Patches ein Diagramm hinunter" + +#: libvips/conversion/ifthenelse.c:525 +msgid "ifthenelse an image" +msgstr "fallsdannsonst eines Bildes" + +#: libvips/conversion/ifthenelse.c:529 +msgid "Condition" +msgstr "Bedingung" + +#: libvips/conversion/ifthenelse.c:530 +msgid "Condition input image" +msgstr "Bedingung des Eingabebilds" + +#: libvips/conversion/ifthenelse.c:535 +msgid "Then image" +msgstr "dann Bild" + +#: libvips/conversion/ifthenelse.c:536 +msgid "Source for TRUE pixels" +msgstr "Quelle für TRUE-Bildpunkte" + +#: libvips/conversion/ifthenelse.c:541 +msgid "Else image" +msgstr "sonst Bild" + +#: libvips/conversion/ifthenelse.c:542 +msgid "Source for FALSE pixels" +msgstr "Quelle für FALSE-Bildpunkte" + +#: libvips/conversion/ifthenelse.c:547 +#, fuzzy +msgid "Blend" +msgstr "Mischung" + +#: libvips/conversion/ifthenelse.c:548 +msgid "Blend smoothly between then and else parts" +msgstr "nahtlos zwischen »dann«- und »sonst«-Teilen mischen" + +#: libvips/conversion/insert.c:460 +msgid "insert image @sub into @main at @x, @y" +msgstr "" + +#: libvips/conversion/insert.c:466 +msgid "Main" +msgstr "primär" + +#: libvips/conversion/insert.c:467 +msgid "Main input image" +msgstr "Haupteingabebild" + +#: libvips/conversion/insert.c:472 libvips/draw/draw_image.c:269 +msgid "Sub-image" +msgstr "Teilbild" + +#: libvips/conversion/insert.c:473 libvips/draw/draw_image.c:270 +msgid "Sub-image to insert into main image" +msgstr "Teilbild, das in das Hauptbild eingefügt werden soll" + +#: libvips/conversion/insert.c:478 +msgid "X" +msgstr "X" + +#: libvips/conversion/insert.c:479 +msgid "Left edge of sub in main" +msgstr "linker Rand des Teilbilds im Hauptbild" + +#: libvips/conversion/insert.c:485 +msgid "Y" +msgstr "Y" + +#: libvips/conversion/insert.c:486 +msgid "Top edge of sub in main" +msgstr "oberer Rand des Teilbilds im Hauptbild" + +#: libvips/conversion/insert.c:492 libvips/conversion/join.c:256 +msgid "Expand" +msgstr "expandieren" + +#: libvips/conversion/insert.c:493 libvips/conversion/join.c:257 +msgid "Expand output to hold all of both inputs" +msgstr "Ausgabe so expandieren, dass sie beide Eingaben vollständig enthält" + +#: libvips/conversion/insert.c:500 +#, fuzzy +msgid "Color for new pixels" +msgstr "Farbe für neue Bildpunkte" + +#: libvips/conversion/join.c:231 +msgid "join a pair of images" +msgstr "ein Bilderpaar zusammenführen" + +#: libvips/conversion/join.c:237 +msgid "in1" +msgstr "in1" + +#: libvips/conversion/join.c:238 +msgid "First input image" +msgstr "erstes Eingabebild" + +#: libvips/conversion/join.c:243 libvips/freqfilt/phasecor.c:111 +msgid "in2" +msgstr "in2" + +#: libvips/conversion/join.c:244 libvips/freqfilt/phasecor.c:112 +msgid "Second input image" +msgstr "zweites Eingabebild" + +#: libvips/conversion/join.c:250 +msgid "Join left-right or up-down" +msgstr "von links nach rechts oder von oben nach unten zusammenführen" + +#: libvips/conversion/join.c:277 libvips/create/text.c:581 +msgid "Align" +msgstr "ausrichten" + +#: libvips/conversion/join.c:278 +msgid "Align on the low, centre or high coordinate edge" +msgstr "am Rand der unteren, mittleren oder höchsten Koordinate ausrichten" + +#: libvips/conversion/msb.c:168 +#, fuzzy +msgid "bad band" +msgstr "falsche Bänder" + +#: libvips/conversion/msb.c:241 +msgid "pick most-significant byte from an image" +msgstr "" + +#: libvips/conversion/msb.c:254 +#, fuzzy +msgid "Band to msb" +msgstr "Bänder auf N setzen" + +#: libvips/conversion/premultiply.c:255 +#, fuzzy +msgid "premultiply image alpha" +msgstr "zwei Bilder multiplizieren" + +#: libvips/conversion/recomb.c:183 +msgid "bands in must equal matrix width" +msgstr "»in«-Bänder müssen die gleiche Breite wie die Matrix haben" + +#: libvips/conversion/recomb.c:218 +msgid "linear recombination with matrix" +msgstr "lineare Neukombinierung mit der Matrix" + +#: libvips/conversion/recomb.c:230 +msgid "M" +msgstr "M" + +#: libvips/conversion/recomb.c:231 +#, fuzzy +msgid "Matrix of coefficients" +msgstr "Matrix der Koeffizienten" + +#: libvips/conversion/replicate.c:192 +msgid "replicate an image" +msgstr "ein Bild nachmachen" + +#: libvips/conversion/replicate.c:203 +msgid "Repeat this many times horizontally" +msgstr "horizontal so oft wiederholen" + +#: libvips/conversion/replicate.c:210 +msgid "Repeat this many times vertically" +msgstr "vertikal so oft wiederholen" + +#: libvips/conversion/rot45.c:264 libvips/conversion/rot.c:361 +msgid "rotate an image" +msgstr "ein Bild drehen" + +#: libvips/conversion/rot45.c:275 libvips/conversion/rot.c:372 +msgid "Angle to rotate image" +msgstr "Winkel zum Drehen eines Bildes" + +#: libvips/conversion/scale.c:151 +#, fuzzy +msgid "scale an image to uchar" +msgstr "ein Bild zwischenspeichern" + +#: libvips/conversion/scale.c:161 libvips/iofuncs/system.c:311 +msgid "Log" +msgstr "" + +#: libvips/conversion/scale.c:162 +msgid "Log scale" +msgstr "" + +#: libvips/conversion/scale.c:169 +msgid "Exponent for log scale" +msgstr "" + +#: libvips/conversion/sequential.c:239 +msgid "check sequential access" +msgstr "" + +#: libvips/conversion/sequential.c:256 +msgid "Strategy" +msgstr "Strategie" + +#: libvips/conversion/sequential.c:257 libvips/conversion/tilecache.c:412 +msgid "Expected access pattern" +msgstr "erwartetes Zugriffsmuster" + +#: libvips/conversion/sequential.c:263 +msgid "Trace" +msgstr "" + +#: libvips/conversion/sequential.c:264 +msgid "Trace pixel requests" +msgstr "" + +#: libvips/conversion/smartcrop.c:453 +#, fuzzy +msgid "Interesting" +msgstr "Interpretation" + +#: libvips/conversion/smartcrop.c:454 +msgid "How to measure interestingness" +msgstr "" + +#: libvips/conversion/smartcrop.c:460 +msgid "Attention x" +msgstr "" + +#: libvips/conversion/smartcrop.c:461 +#, fuzzy +msgid "Horizontal position of attention centre" +msgstr "horizontale Position des Minimums" + +#: libvips/conversion/smartcrop.c:467 +msgid "Attention y" +msgstr "" + +#: libvips/conversion/smartcrop.c:468 +#, fuzzy +msgid "Vertical position of attention centre" +msgstr "vertikale Position des Minimums" + +#: libvips/conversion/smartcrop.c:475 +msgid "Input image already has premultiplied alpha" +msgstr "" + +#: libvips/conversion/subsample.c:228 libvips/resample/reduceh.cpp:546 +#: libvips/resample/reducev.cpp:1001 libvips/resample/shrinkh.c:316 +#: libvips/resample/shrinkv.c:364 +msgid "image has shrunk to nothing" +msgstr "Bild ist zu nichts geschrumpft" + +#: libvips/conversion/subsample.c:259 +#, fuzzy +msgid "subsample an image" +msgstr "ein Bild zwischenspeichern" + +#: libvips/conversion/subsample.c:273 libvips/conversion/zoom.c:379 +msgid "Xfac" +msgstr "" + +#: libvips/conversion/subsample.c:274 +#, fuzzy +msgid "Horizontal subsample factor" +msgstr "horizontaler Versatz vom Ursprung" + +#: libvips/conversion/subsample.c:280 libvips/conversion/zoom.c:386 +msgid "Yfac" +msgstr "" + +#: libvips/conversion/subsample.c:281 +#, fuzzy +msgid "Vertical subsample factor" +msgstr "vertikaler Versatz vom Ursprung" + +#: libvips/conversion/subsample.c:287 +msgid "Point" +msgstr "" + +#: libvips/conversion/subsample.c:288 +msgid "Point sample" +msgstr "" + +#: libvips/conversion/switch.c:129 +#, fuzzy +msgid "bad number of tests" +msgstr "falsche Achsenanzahl %d" + +#: libvips/conversion/switch.c:161 +#, fuzzy +msgid "test images not 1-band" +msgstr "Bild muss ein Band haben" + +#: libvips/conversion/switch.c:189 +msgid "find the index of the first non-zero pixel in tests" +msgstr "" + +#: libvips/conversion/switch.c:195 +msgid "Tests" +msgstr "" + +#: libvips/conversion/switch.c:196 +#, fuzzy +msgid "Table of images to test" +msgstr "Bild in TIFF-Datei speichern" + +#: libvips/conversion/tilecache.c:411 libvips/foreign/foreign.c:1235 +msgid "Access" +msgstr "" + +#: libvips/conversion/tilecache.c:418 +msgid "Threaded" +msgstr "" + +#: libvips/conversion/tilecache.c:419 +msgid "Allow threaded access" +msgstr "" + +#: libvips/conversion/tilecache.c:425 +msgid "Persistent" +msgstr "" + +#: libvips/conversion/tilecache.c:426 +msgid "Keep cache between evaluations" +msgstr "" + +#: libvips/conversion/tilecache.c:708 +#, c-format +msgid "error in tile %d x %d" +msgstr "" + +#: libvips/conversion/tilecache.c:796 +#, fuzzy +msgid "cache an image as a set of tiles" +msgstr "ein Bild zwischenspeichern" + +#: libvips/conversion/tilecache.c:983 +#, fuzzy +msgid "cache an image as a set of lines" +msgstr "ein Bild zwischenspeichern" + +#: libvips/conversion/transpose3d.c:135 +msgid "bad page_height" +msgstr "" + +#: libvips/conversion/transpose3d.c:163 +#, fuzzy +msgid "transpose3d an image" +msgstr "ein Bild einfügen" + +#: libvips/conversion/transpose3d.c:173 libvips/foreign/foreign.c:1915 +#, fuzzy +msgid "Page height" +msgstr "Kachelhöhe" + +#: libvips/conversion/transpose3d.c:174 +#, fuzzy +msgid "Height of each input page" +msgstr "Höhe des extrahierten Bereichs" + +#: libvips/conversion/unpremultiply.c:317 +#, fuzzy +msgid "unpremultiply image alpha" +msgstr "zwei Bilder multiplizieren" + +#: libvips/conversion/unpremultiply.c:336 +#, fuzzy +msgid "Alpha band" +msgstr "falsche Bänder" + +#: libvips/conversion/unpremultiply.c:337 +msgid "Unpremultiply with this alpha" +msgstr "" + +#: libvips/conversion/wrap.c:115 +msgid "wrap image origin" +msgstr "" + +#: libvips/conversion/zoom.c:328 +msgid "zoom factors too large" +msgstr "Zoomfaktoren zu groß" + +#: libvips/conversion/zoom.c:367 +#, fuzzy +msgid "zoom an image" +msgstr "ein Bild kopieren" + +#: libvips/conversion/zoom.c:380 +#, fuzzy +msgid "Horizontal zoom factor" +msgstr "horizontaler Versatz vom Ursprung" + +#: libvips/conversion/zoom.c:387 +#, fuzzy +msgid "Vertical zoom factor" +msgstr "vertikaler Versatz vom Ursprung" + +#: libvips/convolution/canny.c:436 +msgid "Canny edge detector" +msgstr "" + +#: libvips/convolution/canny.c:454 libvips/convolution/gaussblur.c:144 +#: libvips/convolution/sharpen.c:334 libvips/create/gaussmat.c:185 +#: libvips/create/gaussnoise.c:188 +msgid "Sigma" +msgstr "" + +#: libvips/convolution/canny.c:455 libvips/convolution/gaussblur.c:145 +#: libvips/convolution/sharpen.c:335 libvips/create/gaussmat.c:186 +msgid "Sigma of Gaussian" +msgstr "" + +#: libvips/convolution/canny.c:461 libvips/convolution/compass.c:184 +#: libvips/convolution/conv.c:134 libvips/convolution/convsep.c:130 +#: libvips/convolution/gaussblur.c:158 libvips/create/gaussmat.c:213 +#: libvips/create/logmat.c:229 +#, fuzzy +msgid "Precision" +msgstr "Komprimierung" + +#: libvips/convolution/canny.c:462 libvips/convolution/compass.c:185 +#: libvips/convolution/conv.c:135 libvips/convolution/convsep.c:131 +#: libvips/convolution/gaussblur.c:159 +msgid "Convolve with this precision" +msgstr "" + +#: libvips/convolution/compass.c:159 +msgid "convolve with rotating mask" +msgstr "" + +#: libvips/convolution/compass.c:163 +msgid "Times" +msgstr "" + +#: libvips/convolution/compass.c:164 +msgid "Rotate and convolve this many times" +msgstr "" + +#: libvips/convolution/compass.c:171 +msgid "Rotate mask by this much between convolutions" +msgstr "" + +#: libvips/convolution/compass.c:178 +msgid "Combine convolution results like this" +msgstr "" + +#: libvips/convolution/compass.c:191 libvips/convolution/conva.c:1323 +#: libvips/convolution/convasep.c:918 libvips/convolution/conv.c:141 +#: libvips/convolution/convsep.c:137 +msgid "Layers" +msgstr "" + +#: libvips/convolution/compass.c:192 libvips/convolution/conva.c:1324 +#: libvips/convolution/convasep.c:919 libvips/convolution/conv.c:142 +#: libvips/convolution/convsep.c:138 +msgid "Use this many layers in approximation" +msgstr "" + +#: libvips/convolution/compass.c:198 libvips/convolution/conva.c:1330 +#: libvips/convolution/conv.c:148 libvips/convolution/convsep.c:144 +msgid "Cluster" +msgstr "" + +#: libvips/convolution/compass.c:199 libvips/convolution/conva.c:1331 +#: libvips/convolution/conv.c:149 libvips/convolution/convsep.c:145 +msgid "Cluster lines closer than this in approximation" +msgstr "" + +#: libvips/convolution/conva.c:236 libvips/convolution/conva.c:242 +#: libvips/convolution/conva.c:760 libvips/convolution/convasep.c:151 +msgid "mask too complex" +msgstr "Maske zu komplex" + +#: libvips/convolution/conva.c:997 libvips/convolution/conva.c:1247 +#: libvips/convolution/convasep.c:840 +msgid "image too small for mask" +msgstr "Bild zu klein für Maske" + +#: libvips/convolution/conva.c:1319 +msgid "approximate integer convolution" +msgstr "" + +#: libvips/convolution/convasep.c:914 +msgid "approximate separable integer convolution" +msgstr "" + +#: libvips/convolution/conv.c:130 +#, fuzzy +msgid "convolution operation" +msgstr "Umwandlungstransaktionen" + +#: libvips/convolution/convf.c:374 +#, fuzzy +msgid "float convolution operation" +msgstr "Umwandlungstransaktionen" + +#: libvips/convolution/convi.c:1245 +#, fuzzy +msgid "int convolution operation" +msgstr "Umwandlungstransaktionen" + +#: libvips/convolution/convolution.c:119 +#, fuzzy +msgid "convolution operations" +msgstr "Umwandlungstransaktionen" + +#: libvips/convolution/convolution.c:140 libvips/convolution/correlation.c:156 +#: libvips/draw/draw_mask.c:332 libvips/freqfilt/freqmult.c:130 +#: libvips/morphology/labelregions.c:124 libvips/morphology/morph.c:965 +msgid "Mask" +msgstr "" + +#: libvips/convolution/convolution.c:141 libvips/morphology/morph.c:966 +#, fuzzy +msgid "Input matrix image" +msgstr "Eingabebild" + +#: libvips/convolution/convsep.c:126 +#, fuzzy +msgid "separable convolution operation" +msgstr "Umwandlungstransaktionen" + +#: libvips/convolution/correlation.c:144 +#, fuzzy +msgid "correlation operation" +msgstr "Umwandlungstransaktionen" + +#: libvips/convolution/correlation.c:157 +#, fuzzy +msgid "Input reference image" +msgstr "Zeilensprungbild" + +#: libvips/convolution/edge.c:213 +#, fuzzy +msgid "Edge detector" +msgstr "falscher Bild-Deskriptor" + +#: libvips/convolution/edge.c:258 +msgid "Sobel edge detector" +msgstr "" + +#: libvips/convolution/edge.c:291 +msgid "Scharr edge detector" +msgstr "" + +#: libvips/convolution/edge.c:324 +msgid "Prewitt edge detector" +msgstr "" + +#: libvips/convolution/fastcor.c:218 +#, fuzzy +msgid "fast correlation" +msgstr "Interpretation" + +#: libvips/convolution/gaussblur.c:126 +msgid "gaussian blur" +msgstr "" + +#: libvips/convolution/gaussblur.c:151 libvips/create/gaussmat.c:192 +msgid "Minimum amplitude" +msgstr "" + +#: libvips/convolution/gaussblur.c:152 libvips/create/gaussmat.c:193 +#: libvips/create/logmat.c:209 +#, fuzzy +msgid "Minimum amplitude of Gaussian" +msgstr "Minimalwert des Bildes" + +#: libvips/convolution/sharpen.c:316 +msgid "unsharp masking for print" +msgstr "" + +#: libvips/convolution/sharpen.c:341 libvips/draw/draw_line.c:284 +#, fuzzy +msgid "x1" +msgstr "x" + +#: libvips/convolution/sharpen.c:342 +msgid "Flat/jaggy threshold" +msgstr "" + +#: libvips/convolution/sharpen.c:348 libvips/draw/draw_line.c:305 +#, fuzzy +msgid "y2" +msgstr "y" + +#: libvips/convolution/sharpen.c:349 +msgid "Maximum brightening" +msgstr "" + +#: libvips/convolution/sharpen.c:355 +#, fuzzy +msgid "y3" +msgstr "y" + +#: libvips/convolution/sharpen.c:356 +msgid "Maximum darkening" +msgstr "" + +#: libvips/convolution/sharpen.c:362 +msgid "m1" +msgstr "" + +#: libvips/convolution/sharpen.c:363 +msgid "Slope for flat areas" +msgstr "" + +#: libvips/convolution/sharpen.c:369 +msgid "m2" +msgstr "" + +#: libvips/convolution/sharpen.c:370 +msgid "Slope for jaggy areas" +msgstr "" + +#: libvips/convolution/sharpen.c:378 libvips/create/logmat.c:201 +#: libvips/create/mask_butterworth_band.c:136 +#: libvips/create/mask_gaussian_band.c:121 libvips/create/mask_ideal_band.c:112 +#: libvips/create/sdf.c:326 libvips/draw/draw_circle.c:248 +msgid "Radius" +msgstr "" + +#: libvips/convolution/sharpen.c:379 libvips/create/logmat.c:202 +msgid "Radius of Gaussian" +msgstr "" + +#: libvips/convolution/spcor.c:317 +msgid "spatial correlation" +msgstr "" + +#: libvips/create/black.c:136 +msgid "make a black image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/buildlut.c:134 +#, fuzzy, c-format +msgid "x value row %d not an int" +msgstr "x-Wert keine Ganzzahl" + +#: libvips/create/buildlut.c:149 +msgid "x range too small" +msgstr "x-Bereich zu klein" + +#: libvips/create/buildlut.c:259 libvips/create/tonelut.c:221 +msgid "build a look-up table" +msgstr "" + +#: libvips/create/buildlut.c:264 libvips/create/invertlut.c:289 +#, fuzzy +msgid "Matrix of XY coordinates" +msgstr "Matrix der Koeffizienten" + +#: libvips/create/create.c:120 +#, fuzzy +msgid "create operations" +msgstr "Transaktionen" + +#: libvips/create/eye.c:103 +msgid "make an image showing the eye's spatial response" +msgstr "" + +#: libvips/create/eye.c:109 +msgid "Maximum spatial frequency" +msgstr "" + +#: libvips/create/fractsurf.c:100 +#, fuzzy +msgid "make a fractal surface" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/fractsurf.c:118 libvips/create/fractsurf.c:119 +#: libvips/create/mask_fractal.c:93 libvips/create/mask_fractal.c:94 +#, fuzzy +msgid "Fractal dimension" +msgstr "falsche Abmessungen" + +#: libvips/create/gaussmat.c:129 libvips/create/logmat.c:147 +#, fuzzy +msgid "mask too large" +msgstr "Maske zu komplex" + +#: libvips/create/gaussmat.c:181 +#, fuzzy +msgid "make a gaussian image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/gaussmat.c:199 libvips/create/logmat.c:215 +#, fuzzy +msgid "Separable" +msgstr "Trenner" + +#: libvips/create/gaussmat.c:200 libvips/create/logmat.c:216 +msgid "Generate separable Gaussian" +msgstr "" + +#: libvips/create/gaussmat.c:206 libvips/create/logmat.c:222 +#, fuzzy +msgid "Integer" +msgstr "Zeilensprung" + +#: libvips/create/gaussmat.c:207 libvips/create/logmat.c:223 +#, fuzzy +msgid "Generate integer Gaussian" +msgstr "Rest nach Ganzzahldivision" + +#: libvips/create/gaussmat.c:214 libvips/create/logmat.c:230 +msgid "Generate with this precision" +msgstr "" + +#: libvips/create/gaussnoise.c:159 +#, fuzzy +msgid "make a gaussnoise image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/gaussnoise.c:181 libvips/histogram/stdif.c:329 +msgid "Mean" +msgstr "" + +#: libvips/create/gaussnoise.c:182 +#, fuzzy +msgid "Mean of pixels in generated image" +msgstr "keine Bildpunktdaten in angehängtem Bild" + +#: libvips/create/gaussnoise.c:189 +#, fuzzy +msgid "Standard deviation of pixels in generated image" +msgstr "Standardabweichung des Bildes" + +#: libvips/create/gaussnoise.c:195 libvips/create/perlin.c:322 +#: libvips/create/worley.c:328 +msgid "Seed" +msgstr "" + +#: libvips/create/gaussnoise.c:196 libvips/create/perlin.c:323 +#: libvips/create/worley.c:329 +#, fuzzy +msgid "Random number seed" +msgstr "falsche Achsenanzahl %d" + +#: libvips/create/grey.c:89 +#, fuzzy +msgid "make a grey ramp image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/identity.c:139 +msgid "make a 1D image where pixel values are indexes" +msgstr "" + +#: libvips/create/identity.c:144 +#, fuzzy +msgid "Number of bands in LUT" +msgstr "Anzahl der Bänder in einem Bild" + +#: libvips/create/identity.c:150 +msgid "Ushort" +msgstr "" + +#: libvips/create/identity.c:151 +msgid "Create a 16-bit LUT" +msgstr "" + +#: libvips/create/identity.c:158 +msgid "Size of 16-bit LUT" +msgstr "" + +#: libvips/create/invertlut.c:124 +msgid "bad input matrix" +msgstr "falsche Eingabematrix" + +#: libvips/create/invertlut.c:129 +msgid "bad size" +msgstr "falsche Größe" + +#: libvips/create/invertlut.c:149 +#, fuzzy, c-format +msgid "element (%d, %d) is %g, outside range [0,1]" +msgstr "Element außerhalb des Bereichs [0,1]" + +#: libvips/create/invertlut.c:284 +msgid "build an inverted look-up table" +msgstr "" + +#: libvips/create/invertlut.c:295 +msgid "LUT size to generate" +msgstr "" + +#: libvips/create/logmat.c:197 +#, fuzzy +msgid "make a Laplacian of Gaussian image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/mask_butterworth_band.c:110 +msgid "make a butterworth_band filter" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:115 +#: libvips/create/mask_butterworth.c:91 +msgid "Order" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:116 +#: libvips/create/mask_butterworth.c:92 +msgid "Filter order" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:122 +#: libvips/create/mask_butterworth_band.c:123 +#: libvips/create/mask_gaussian_band.c:107 +#: libvips/create/mask_gaussian_band.c:108 libvips/create/mask_ideal_band.c:98 +#: libvips/create/mask_ideal_band.c:99 +msgid "Frequency cutoff x" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:129 +#: libvips/create/mask_butterworth_band.c:130 +#: libvips/create/mask_gaussian_band.c:114 +#: libvips/create/mask_gaussian_band.c:115 libvips/create/mask_ideal_band.c:105 +#: libvips/create/mask_ideal_band.c:106 +msgid "Frequency cutoff y" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:137 +#: libvips/create/mask_gaussian_band.c:122 libvips/create/mask_ideal_band.c:113 +msgid "Radius of circle" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:143 +#: libvips/create/mask_butterworth_band.c:144 +#: libvips/create/mask_butterworth.c:105 libvips/create/mask_butterworth.c:106 +#: libvips/create/mask_gaussian_band.c:128 +#: libvips/create/mask_gaussian_band.c:129 libvips/create/mask_gaussian.c:93 +#: libvips/create/mask_gaussian.c:94 +msgid "Amplitude cutoff" +msgstr "" + +#: libvips/create/mask_butterworth.c:86 +msgid "make a butterworth filter" +msgstr "" + +#: libvips/create/mask_butterworth.c:98 libvips/create/mask_butterworth.c:99 +#: libvips/create/mask_gaussian.c:86 libvips/create/mask_gaussian.c:87 +#: libvips/create/mask_ideal.c:84 libvips/create/mask_ideal.c:85 +msgid "Frequency cutoff" +msgstr "" + +#: libvips/create/mask_butterworth_ring.c:101 +msgid "make a butterworth ring filter" +msgstr "" + +#: libvips/create/mask_butterworth_ring.c:106 +#: libvips/create/mask_butterworth_ring.c:107 +#: libvips/create/mask_gaussian_ring.c:101 +#: libvips/create/mask_gaussian_ring.c:102 libvips/create/mask_ideal_ring.c:98 +#: libvips/create/mask_ideal_ring.c:99 +#, fuzzy +msgid "Ringwidth" +msgstr "Kachelbreite" + +#: libvips/create/mask.c:114 +msgid "base class for frequency filters" +msgstr "" + +#: libvips/create/mask.c:122 +msgid "Optical" +msgstr "" + +#: libvips/create/mask.c:123 +msgid "Rotate quadrants to optical space" +msgstr "" + +#: libvips/create/mask.c:129 +msgid "Reject" +msgstr "" + +#: libvips/create/mask.c:130 +msgid "Invert the sense of the filter" +msgstr "" + +#: libvips/create/mask.c:136 +msgid "Nodc" +msgstr "" + +#: libvips/create/mask.c:137 +msgid "Remove DC component" +msgstr "" + +#: libvips/create/mask_fractal.c:88 +msgid "make fractal filter" +msgstr "" + +#: libvips/create/mask_gaussian_band.c:102 libvips/create/mask_gaussian.c:81 +msgid "make a gaussian filter" +msgstr "" + +#: libvips/create/mask_gaussian_ring.c:96 +msgid "make a gaussian ring filter" +msgstr "" + +#: libvips/create/mask_ideal_band.c:93 +msgid "make an ideal band filter" +msgstr "" + +#: libvips/create/mask_ideal.c:79 +msgid "make an ideal filter" +msgstr "" + +#: libvips/create/mask_ideal_ring.c:93 +msgid "make an ideal ring filter" +msgstr "" + +#: libvips/create/perlin.c:290 +#, fuzzy +msgid "make a perlin noise image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/perlin.c:308 libvips/create/worley.c:321 +msgid "Cell size" +msgstr "" + +#: libvips/create/perlin.c:309 +msgid "Size of Perlin cells" +msgstr "" + +#: libvips/create/perlin.c:315 libvips/create/point.c:155 +msgid "Uchar" +msgstr "" + +#: libvips/create/perlin.c:316 libvips/create/point.c:156 +#, fuzzy +msgid "Output an unsigned char image" +msgstr "kein »uchar«-Bild mit einem Band" + +#: libvips/create/point.c:132 +#, fuzzy +msgid "make a point image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/sdf.c:178 +msgid "circle needs a, r to be set" +msgstr "" + +#: libvips/create/sdf.c:183 +msgid "rounded-box needs 2 values for a" +msgstr "" + +#: libvips/create/sdf.c:196 +msgid "box needs a, b to be set" +msgstr "" + +#: libvips/create/sdf.c:202 +msgid "box needs 2 values for a, b" +msgstr "" + +#: libvips/create/sdf.c:216 +msgid "rounded-box needs a, b to be set" +msgstr "" + +#: libvips/create/sdf.c:222 +msgid "rounded-box needs 2 values for a, b" +msgstr "" + +#: libvips/create/sdf.c:227 +msgid "rounded-box needs 4 values for corners" +msgstr "" + +#: libvips/create/sdf.c:242 +msgid "line needs sx, sy to be set" +msgstr "" + +#: libvips/create/sdf.c:248 +msgid "line needs 2 values for a, b" +msgstr "" + +#: libvips/create/sdf.c:259 +#, fuzzy, c-format +msgid "unknown SDF %d" +msgstr "unbekannte Kodierung" + +#: libvips/create/sdf.c:300 +#, fuzzy +msgid "create an SDF image" +msgstr "ein Bild drehen" + +#: libvips/create/sdf.c:318 +msgid "Shape" +msgstr "" + +#: libvips/create/sdf.c:319 +msgid "SDF shape to create" +msgstr "" + +#: libvips/create/sdf.c:325 +msgid "r" +msgstr "" + +#: libvips/create/sdf.c:333 +msgid "Point a" +msgstr "" + +#: libvips/create/sdf.c:340 +msgid "Point b" +msgstr "" + +#: libvips/create/sdf.c:346 +msgid "corners" +msgstr "" + +#: libvips/create/sdf.c:347 +msgid "Corner radii" +msgstr "" + +#: libvips/create/sines.c:122 +msgid "make a 2D sine wave" +msgstr "" + +#: libvips/create/sines.c:128 +msgid "hfreq" +msgstr "" + +#: libvips/create/sines.c:129 +#, fuzzy +msgid "Horizontal spatial frequency" +msgstr "horizontaler Versatz vom Ursprung" + +#: libvips/create/sines.c:135 +msgid "vfreq" +msgstr "" + +#: libvips/create/sines.c:136 +msgid "Vertical spatial frequency" +msgstr "" + +#: libvips/create/text.c:406 +msgid "invalid markup in text" +msgstr "ungültige Auszeichnung im Text" + +#: libvips/create/text.c:428 +#, fuzzy, c-format +msgid "unable to load fontfile \"%s\"" +msgstr "Profil »%s« kann nicht geöffnet werden" + +#: libvips/create/text.c:467 +msgid "no text to render" +msgstr "kein Text zu rendern" + +#: libvips/create/text.c:549 +#, fuzzy +msgid "make a text image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/text.c:553 +msgid "Text" +msgstr "" + +#: libvips/create/text.c:554 +#, fuzzy +msgid "Text to render" +msgstr "kein Text zu rendern" + +#: libvips/create/text.c:560 +msgid "Font" +msgstr "" + +#: libvips/create/text.c:561 +#, fuzzy +msgid "Font to render with" +msgstr "kein Text zu rendern" + +#: libvips/create/text.c:568 +#, fuzzy +msgid "Maximum image width in pixels" +msgstr "Bildbreite in Bildpunkten" + +#: libvips/create/text.c:575 +#, fuzzy +msgid "Maximum image height in pixels" +msgstr "Bildhöhe in Bildpunkten" + +#: libvips/create/text.c:582 +#, fuzzy +msgid "Align on the low, centre or high edge" +msgstr "am Rand der unteren, mittleren oder höchsten Koordinate ausrichten" + +#: libvips/create/text.c:588 +msgid "Justify" +msgstr "" + +#: libvips/create/text.c:589 +#, fuzzy +msgid "Justify lines" +msgstr "leere Zeile" + +#: libvips/create/text.c:595 libvips/foreign/pdfiumload.c:709 +#: libvips/foreign/popplerload.c:559 libvips/foreign/svgload.c:717 +msgid "DPI" +msgstr "" + +#: libvips/create/text.c:596 libvips/foreign/pdfiumload.c:710 +#: libvips/foreign/popplerload.c:560 +#, fuzzy +msgid "DPI to render at" +msgstr "kein Text zu rendern" + +#: libvips/create/text.c:602 +msgid "Autofit DPI" +msgstr "" + +#: libvips/create/text.c:603 +msgid "DPI selected by autofit" +msgstr "" + +#: libvips/create/text.c:609 +msgid "Spacing" +msgstr "" + +#: libvips/create/text.c:610 +msgid "Line spacing" +msgstr "" + +#: libvips/create/text.c:616 +#, fuzzy +msgid "Font file" +msgstr "Profil" + +#: libvips/create/text.c:617 +#, fuzzy +msgid "Load this font file" +msgstr "diese Seite aus der Datei laden" + +#: libvips/create/text.c:623 +msgid "RGBA" +msgstr "" + +#: libvips/create/text.c:624 +msgid "Enable RGBA output" +msgstr "" + +#: libvips/create/text.c:630 +msgid "Wrap" +msgstr "" + +#: libvips/create/text.c:631 +msgid "Wrap lines on word or character boundaries" +msgstr "" + +#: libvips/create/tonelut.c:225 +msgid "In-max" +msgstr "" + +#: libvips/create/tonelut.c:226 +msgid "Size of LUT to build" +msgstr "" + +#: libvips/create/tonelut.c:232 +msgid "Out-max" +msgstr "" + +#: libvips/create/tonelut.c:233 +#, fuzzy +msgid "Maximum value in output LUT" +msgstr "Maximalwert des Bildes" + +#: libvips/create/tonelut.c:239 +msgid "Black point" +msgstr "" + +#: libvips/create/tonelut.c:240 +#, fuzzy +msgid "Lowest value in output" +msgstr "linker Rand der Eingabe in der Ausgabe" + +#: libvips/create/tonelut.c:246 +msgid "White point" +msgstr "" + +#: libvips/create/tonelut.c:247 +msgid "Highest value in output" +msgstr "" + +#: libvips/create/tonelut.c:253 +msgid "Shadow point" +msgstr "" + +#: libvips/create/tonelut.c:254 +msgid "Position of shadow" +msgstr "" + +#: libvips/create/tonelut.c:260 +msgid "Mid-tone point" +msgstr "" + +#: libvips/create/tonelut.c:261 +msgid "Position of mid-tones" +msgstr "" + +#: libvips/create/tonelut.c:267 +msgid "Highlight point" +msgstr "" + +#: libvips/create/tonelut.c:268 +msgid "Position of highlights" +msgstr "" + +#: libvips/create/tonelut.c:274 +msgid "Shadow adjust" +msgstr "" + +#: libvips/create/tonelut.c:275 +msgid "Adjust shadows by this much" +msgstr "" + +#: libvips/create/tonelut.c:281 +msgid "Mid-tone adjust" +msgstr "" + +#: libvips/create/tonelut.c:282 +msgid "Adjust mid-tones by this much" +msgstr "" + +#: libvips/create/tonelut.c:288 +msgid "Highlight adjust" +msgstr "" + +#: libvips/create/tonelut.c:289 +msgid "Adjust highlights by this much" +msgstr "" + +#: libvips/create/worley.c:303 +#, fuzzy +msgid "make a worley noise image" +msgstr "ein schwarzes Bild erstellen" + +#: libvips/create/worley.c:322 +msgid "Size of Worley cells" +msgstr "" + +#: libvips/create/xyz.c:139 +#, fuzzy +msgid "lower dimensions not set" +msgstr "Abfragen der Abmessungen: %s" + +#: libvips/create/xyz.c:156 libvips/foreign/heifsave.c:682 +#: libvips/foreign/webpsave.c:734 +#, fuzzy +msgid "image too large" +msgstr "Bild zu schmal" + +#: libvips/create/xyz.c:187 +msgid "make an image where pixel values are coordinates" +msgstr "" + +#: libvips/create/xyz.c:205 +#, fuzzy +msgid "csize" +msgstr "falsche Größe" + +#: libvips/create/xyz.c:206 +msgid "Size of third dimension" +msgstr "" + +#: libvips/create/xyz.c:212 +#, fuzzy +msgid "dsize" +msgstr "falsche Größe" + +#: libvips/create/xyz.c:213 +msgid "Size of fourth dimension" +msgstr "" + +#: libvips/create/xyz.c:219 +#, fuzzy +msgid "esize" +msgstr "falsche Größe" + +#: libvips/create/xyz.c:220 +msgid "Size of fifth dimension" +msgstr "" + +#: libvips/create/zone.c:90 +msgid "make a zone plate" +msgstr "" + +#: libvips/draw/draw.c:131 +#, fuzzy +msgid "draw operations" +msgstr "Transaktionen" + +#: libvips/draw/draw.c:138 +#, fuzzy +msgid "Image" +msgstr "Eingabebild" + +#: libvips/draw/draw.c:139 +#, fuzzy +msgid "Image to draw on" +msgstr "zu speicherndes Bild" + +#: libvips/draw/draw_circle.c:230 +#, fuzzy +msgid "draw a circle on an image" +msgstr "einen Bereich eines Bildes extrahieren" + +#: libvips/draw/draw_circle.c:234 +#, fuzzy +msgid "cx" +msgstr "x" + +#: libvips/draw/draw_circle.c:235 libvips/draw/draw_circle.c:242 +msgid "Centre of draw_circle" +msgstr "" + +#: libvips/draw/draw_circle.c:241 +#, fuzzy +msgid "cy" +msgstr "y" + +#: libvips/draw/draw_circle.c:249 +#, fuzzy +msgid "Radius in pixels" +msgstr "Bildbreite in Bildpunkten" + +#: libvips/draw/draw_circle.c:255 libvips/draw/draw_rect.c:201 +msgid "Fill" +msgstr "" + +#: libvips/draw/draw_circle.c:256 libvips/draw/draw_rect.c:202 +msgid "Draw a solid object" +msgstr "" + +#: libvips/draw/draw_flood.c:562 +msgid "flood-fill an area" +msgstr "" + +#: libvips/draw/draw_flood.c:567 libvips/draw/draw_flood.c:574 +msgid "DrawFlood start point" +msgstr "" + +#: libvips/draw/draw_flood.c:580 +msgid "Test" +msgstr "" + +#: libvips/draw/draw_flood.c:581 +#, fuzzy +msgid "Test pixels in this image" +msgstr "keine Bildpunktdaten in angehängtem Bild" + +#: libvips/draw/draw_flood.c:586 +msgid "Equal" +msgstr "" + +#: libvips/draw/draw_flood.c:587 +msgid "DrawFlood while equal to edge" +msgstr "" + +#: libvips/draw/draw_flood.c:594 +#, fuzzy +msgid "Left edge of modified area" +msgstr "linke Kante eines extrahierten Bereichs" + +#: libvips/draw/draw_flood.c:601 +#, fuzzy +msgid "Top edge of modified area" +msgstr "obere Kante eines extrahierten Bereichs" + +#: libvips/draw/draw_flood.c:608 +#, fuzzy +msgid "Width of modified area" +msgstr "Breite des extrahierten Bereichs" + +#: libvips/draw/draw_flood.c:615 +#, fuzzy +msgid "Height of modified area" +msgstr "Höhe des extrahierten Bereichs" + +#: libvips/draw/draw_image.c:265 +#, fuzzy +msgid "paint an image into another image" +msgstr "ein Bild in ein größeres Bild einbetten" + +#: libvips/draw/draw_image.c:276 libvips/draw/draw_image.c:283 +#, fuzzy +msgid "Draw image here" +msgstr "- Bild-Kopfzeilen ausgeben" + +#: libvips/draw/draw_image.c:289 libvips/iofuncs/image.c:1179 +msgid "Mode" +msgstr "Modus" + +#: libvips/draw/draw_image.c:290 +msgid "Combining mode" +msgstr "" + +#: libvips/draw/drawink.c:86 +#, fuzzy +msgid "draw with ink operations" +msgstr "arithmetische Transaktionen" + +#: libvips/draw/drawink.c:90 +msgid "Ink" +msgstr "" + +#: libvips/draw/drawink.c:91 +#, fuzzy +msgid "Color for pixels" +msgstr "Farbe für neue Bildpunkte" + +#: libvips/draw/draw_line.c:280 +#, fuzzy +msgid "draw a line on an image" +msgstr "eine mathematische Funktion für ein Bild ausführen" + +#: libvips/draw/draw_line.c:285 libvips/draw/draw_line.c:292 +msgid "Start of draw_line" +msgstr "" + +#: libvips/draw/draw_line.c:291 +#, fuzzy +msgid "y1" +msgstr "y" + +#: libvips/draw/draw_line.c:298 +#, fuzzy +msgid "x2" +msgstr "x" + +#: libvips/draw/draw_line.c:299 libvips/draw/draw_line.c:306 +msgid "End of draw_line" +msgstr "" + +#: libvips/draw/draw_mask.c:328 +#, fuzzy +msgid "draw a mask on an image" +msgstr "einen Bereich eines Bildes extrahieren" + +#: libvips/draw/draw_mask.c:333 +msgid "Mask of pixels to draw" +msgstr "" + +#: libvips/draw/draw_mask.c:339 libvips/draw/draw_mask.c:346 +msgid "Draw mask here" +msgstr "" + +#: libvips/draw/draw_rect.c:169 +#, fuzzy +msgid "paint a rectangle on an image" +msgstr "einen Bereich eines Bildes extrahieren" + +#: libvips/draw/draw_rect.c:174 libvips/draw/draw_rect.c:181 +#: libvips/draw/draw_rect.c:188 libvips/draw/draw_rect.c:195 +#: libvips/draw/draw_smudge.c:216 libvips/draw/draw_smudge.c:223 +#: libvips/draw/draw_smudge.c:230 libvips/draw/draw_smudge.c:237 +#, fuzzy +msgid "Rect to fill" +msgstr "Ziel zu klein" + +# http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650& +# db=man&fname=/usr/share/catman/p_man/cat3/il_c/ilAbsImg.z +#: libvips/draw/draw_smudge.c:211 +#, fuzzy +msgid "blur a rectangle on an image" +msgstr "absoluter Wert eines Bildes" + +#: libvips/foreign/analyze2vips.c:308 +msgid "header file size incorrect" +msgstr "Kopfdatendateigröße nicht korrekt" + +#: libvips/foreign/analyze2vips.c:352 +msgid "header size incorrect" +msgstr "Kopfdatengröße nicht korrekt" + +#: libvips/foreign/analyze2vips.c:370 libvips/foreign/niftiload.c:399 +#, c-format +msgid "%d-dimensional images not supported" +msgstr "%d-dimensionale Bilder nicht unterstützt" + +#: libvips/foreign/analyze2vips.c:423 libvips/foreign/niftiload.c:442 +#, c-format +msgid "datatype %d not supported" +msgstr "Datentyp %d nicht unterstützt" + +#: libvips/foreign/analyzeload.c:120 +msgid "load an Analyze6 image" +msgstr "ein Analyze6-Bild laden" + +#: libvips/foreign/analyzeload.c:141 libvips/foreign/cgifsave.c:1058 +#: libvips/foreign/csvload.c:590 libvips/foreign/csvsave.c:274 +#: libvips/foreign/dzsave.c:2597 libvips/foreign/fitsload.c:259 +#: libvips/foreign/fitssave.c:143 libvips/foreign/heifload.c:1271 +#: libvips/foreign/heifsave.c:897 libvips/foreign/jp2kload.c:1309 +#: libvips/foreign/jp2ksave.c:1063 libvips/foreign/jpegload.c:354 +#: libvips/foreign/jpegsave.c:361 libvips/foreign/jxlload.c:1218 +#: libvips/foreign/jxlsave.c:897 libvips/foreign/magick6load.c:238 +#: libvips/foreign/magick7load.c:851 libvips/foreign/matload.c:138 +#: libvips/foreign/matrixload.c:374 libvips/foreign/matrixsave.c:228 +#: libvips/foreign/niftiload.c:713 libvips/foreign/niftisave.c:441 +#: libvips/foreign/nsgifload.c:765 libvips/foreign/openexrload.c:149 +#: libvips/foreign/openslideload.c:1152 libvips/foreign/pdfiumload.c:812 +#: libvips/foreign/pngload.c:318 libvips/foreign/pngsave.c:378 +#: libvips/foreign/popplerload.c:689 libvips/foreign/ppmload.c:829 +#: libvips/foreign/ppmsave.c:592 libvips/foreign/radload.c:281 +#: libvips/foreign/radsave.c:154 libvips/foreign/rawload.c:139 +#: libvips/foreign/rawsave.c:196 libvips/foreign/spngload.c:835 +#: libvips/foreign/spngsave.c:858 libvips/foreign/svgload.c:929 +#: libvips/foreign/tiffload.c:382 libvips/foreign/tiffsave.c:527 +#: libvips/foreign/vips2magick.c:578 libvips/foreign/vipsload.c:236 +#: libvips/foreign/vipssave.c:197 libvips/foreign/webpload.c:346 +#: libvips/foreign/webpsave.c:1038 libvips/iofuncs/connection.c:133 +#: libvips/iofuncs/image.c:1172 libvips/resample/thumbnail.c:1198 +msgid "Filename" +msgstr "Dateiname" + +#: libvips/foreign/analyzeload.c:142 libvips/foreign/csvload.c:591 +#: libvips/foreign/fitsload.c:260 libvips/foreign/heifload.c:1272 +#: libvips/foreign/jp2kload.c:1310 libvips/foreign/jpegload.c:355 +#: libvips/foreign/jxlload.c:1219 libvips/foreign/magick6load.c:239 +#: libvips/foreign/magick7load.c:852 libvips/foreign/matload.c:139 +#: libvips/foreign/matrixload.c:375 libvips/foreign/niftiload.c:714 +#: libvips/foreign/nsgifload.c:766 libvips/foreign/openexrload.c:150 +#: libvips/foreign/openslideload.c:1153 libvips/foreign/pdfiumload.c:813 +#: libvips/foreign/pngload.c:319 libvips/foreign/popplerload.c:690 +#: libvips/foreign/ppmload.c:830 libvips/foreign/radload.c:282 +#: libvips/foreign/rawload.c:140 libvips/foreign/spngload.c:836 +#: libvips/foreign/svgload.c:930 libvips/foreign/tiffload.c:383 +#: libvips/foreign/vipsload.c:237 libvips/foreign/webpload.c:347 +msgid "Filename to load from" +msgstr "Name der Datei, aus der geladen werden soll" + +#: libvips/foreign/archive.c:138 +#, fuzzy +msgid "unable to create archive" +msgstr "es können keine Profile erstellt werden" + +#: libvips/foreign/archive.c:146 +#, fuzzy +msgid "unable to set zip format" +msgstr "Dateistatus kann nicht abgefragt werden" + +#: libvips/foreign/archive.c:163 +#, fuzzy +msgid "unable to set compression" +msgstr "»%s« kann nicht gesetzt werden" + +#: libvips/foreign/archive.c:175 +#, fuzzy +msgid "unable to set padding" +msgstr "»%s« kann nicht gesetzt werden" + +#: libvips/foreign/archive.c:184 libvips/iofuncs/target.c:129 +#, fuzzy +msgid "unable to open for write" +msgstr "»%s« kann nicht zur Eingabe geöffnet werden" + +#: libvips/foreign/archive.c:205 libvips/iofuncs/util.c:1097 +#, fuzzy, c-format +msgid "unable to create directory \"%s\", %s" +msgstr "Daten für »%s« können nicht gelesen werden, %s" + +#: libvips/foreign/archive.c:240 +#, fuzzy +msgid "unable to create entry" +msgstr "Thread kann nicht erstellt werden" + +#: libvips/foreign/archive.c:256 +#, fuzzy +msgid "unable to write header" +msgstr "Thread kann nicht erstellt werden" + +#: libvips/foreign/archive.c:265 +#, fuzzy +msgid "unable to write data" +msgstr "Daten können nicht gelesen werden" + +#: libvips/foreign/cgifsave.c:407 libvips/foreign/cgifsave.c:833 +#: libvips/foreign/quantise.c:403 libvips/foreign/quantise.c:423 +msgid "quantisation failed" +msgstr "" + +#: libvips/foreign/cgifsave.c:587 +#, fuzzy +msgid "dither failed" +msgstr "Schreiben fehlgeschlagen" + +#: libvips/foreign/cgifsave.c:772 +#, fuzzy +msgid "frame too large" +msgstr "Zoomfaktoren zu groß" + +#: libvips/foreign/cgifsave.c:811 +#, fuzzy +msgid "gif-palette too large" +msgstr "Zoomfaktoren zu groß" + +#: libvips/foreign/cgifsave.c:884 +#, fuzzy +msgid "save as gif" +msgstr "Bild als ASCII speichern" + +#: libvips/foreign/cgifsave.c:893 libvips/foreign/pngsave.c:247 +#: libvips/foreign/spngsave.c:725 +msgid "Dithering" +msgstr "" + +#: libvips/foreign/cgifsave.c:894 libvips/foreign/pngsave.c:248 +#: libvips/foreign/spngsave.c:726 +msgid "Amount of dithering" +msgstr "" + +#: libvips/foreign/cgifsave.c:900 libvips/foreign/heifsave.c:803 +#: libvips/foreign/jxlsave.c:824 libvips/foreign/pngsave.c:261 +#: libvips/foreign/spngsave.c:739 libvips/foreign/webpsave.c:890 +msgid "Effort" +msgstr "" + +#: libvips/foreign/cgifsave.c:901 +msgid "Quantisation effort" +msgstr "" + +#: libvips/foreign/cgifsave.c:907 libvips/foreign/heifsave.c:781 +#: libvips/foreign/pngsave.c:254 libvips/foreign/ppmsave.c:521 +#: libvips/foreign/spngsave.c:732 libvips/foreign/tiffsave.c:315 +#: libvips/foreign/vips2magick.c:510 +msgid "Bit depth" +msgstr "" + +#: libvips/foreign/cgifsave.c:908 libvips/foreign/heifsave.c:782 +#: libvips/foreign/vips2magick.c:511 +#, fuzzy +msgid "Number of bits per pixel" +msgstr "Anzahl der Bänder in einem Bild" + +#: libvips/foreign/cgifsave.c:914 +#, fuzzy +msgid "Maximum inter-frame error" +msgstr "interner Fehler" + +#: libvips/foreign/cgifsave.c:915 +msgid "Maximum inter-frame error for transparency" +msgstr "" + +#: libvips/foreign/cgifsave.c:921 +msgid "Reuse palette" +msgstr "" + +#: libvips/foreign/cgifsave.c:922 +msgid "Reuse palette from input" +msgstr "" + +#: libvips/foreign/cgifsave.c:928 +#, fuzzy +msgid "Maximum inter-palette error" +msgstr "interner Fehler" + +#: libvips/foreign/cgifsave.c:929 +msgid "Maximum inter-palette error for palette reusage" +msgstr "" + +#: libvips/foreign/cgifsave.c:935 +#, fuzzy +msgid "Interlaced" +msgstr "Zeilensprung" + +#: libvips/foreign/cgifsave.c:936 +msgid "Generate an interlaced (progressive) GIF" +msgstr "" + +#: libvips/foreign/cgifsave.c:945 +msgid "Reoptimise palettes" +msgstr "" + +#: libvips/foreign/cgifsave.c:946 +msgid "Reoptimise colour palettes" +msgstr "" + +#: libvips/foreign/cgifsave.c:952 +#, fuzzy +msgid "Keep duplicate frames" +msgstr "ein Bild nachmachen" + +#: libvips/foreign/cgifsave.c:953 +msgid "Keep duplicate frames in the output instead of combining them" +msgstr "" + +#: libvips/foreign/cgifsave.c:1010 libvips/foreign/csvsave.c:325 +#: libvips/foreign/dzsave.c:2537 libvips/foreign/heifsave.c:1020 +#: libvips/foreign/jp2ksave.c:1182 libvips/foreign/jpegsave.c:292 +#: libvips/foreign/jxlsave.c:1016 libvips/foreign/matrixsave.c:281 +#: libvips/foreign/pngsave.c:326 libvips/foreign/ppmsave.c:648 +#: libvips/foreign/radsave.c:207 libvips/foreign/rawsave.c:252 +#: libvips/foreign/spngsave.c:805 libvips/foreign/tiffsave.c:474 +#: libvips/foreign/vipssave.c:253 libvips/foreign/webpsave.c:987 +#: libvips/iofuncs/target.c:283 +msgid "Target" +msgstr "" + +#: libvips/foreign/cgifsave.c:1011 libvips/foreign/csvsave.c:326 +#: libvips/foreign/dzsave.c:2538 libvips/foreign/heifsave.c:1021 +#: libvips/foreign/jp2ksave.c:1183 libvips/foreign/jpegsave.c:293 +#: libvips/foreign/jxlsave.c:1017 libvips/foreign/matrixsave.c:282 +#: libvips/foreign/pngsave.c:327 libvips/foreign/ppmsave.c:649 +#: libvips/foreign/radsave.c:208 libvips/foreign/rawsave.c:253 +#: libvips/foreign/spngsave.c:806 libvips/foreign/tiffsave.c:475 +#: libvips/foreign/vipssave.c:254 libvips/foreign/webpsave.c:988 +#, fuzzy +msgid "Target to save to" +msgstr "zu speicherndes Bild" + +#: libvips/foreign/cgifsave.c:1059 libvips/foreign/csvsave.c:275 +#: libvips/foreign/dzsave.c:2598 libvips/foreign/fitssave.c:144 +#: libvips/foreign/heifsave.c:898 libvips/foreign/jp2ksave.c:1064 +#: libvips/foreign/jpegsave.c:362 libvips/foreign/jxlsave.c:898 +#: libvips/foreign/matrixsave.c:229 libvips/foreign/niftisave.c:442 +#: libvips/foreign/pngsave.c:379 libvips/foreign/ppmsave.c:593 +#: libvips/foreign/radsave.c:155 libvips/foreign/rawsave.c:197 +#: libvips/foreign/spngsave.c:859 libvips/foreign/tiffsave.c:528 +#: libvips/foreign/vips2magick.c:579 libvips/foreign/vipssave.c:198 +#: libvips/foreign/webpsave.c:1039 +msgid "Filename to save to" +msgstr "Name der Datei in die gespeichert werden soll" + +#: libvips/foreign/cgifsave.c:1117 libvips/foreign/dzsave.c:2656 +#: libvips/foreign/heifload.c:1340 libvips/foreign/heifsave.c:962 +#: libvips/foreign/jp2kload.c:1385 libvips/foreign/jp2ksave.c:1126 +#: libvips/foreign/jpegload.c:430 libvips/foreign/jpegsave.c:439 +#: libvips/foreign/jxlload.c:1293 libvips/foreign/jxlsave.c:960 +#: libvips/foreign/magick6load.c:313 libvips/foreign/magick7load.c:932 +#: libvips/foreign/nsgifload.c:843 libvips/foreign/pdfiumload.c:872 +#: libvips/foreign/pngload.c:394 libvips/foreign/pngsave.c:437 +#: libvips/foreign/popplerload.c:749 libvips/foreign/radload.c:356 +#: libvips/foreign/radsave.c:273 libvips/foreign/rawsave.c:314 +#: libvips/foreign/spngload.c:911 libvips/foreign/spngsave.c:918 +#: libvips/foreign/svgload.c:997 libvips/foreign/tiffload.c:460 +#: libvips/foreign/tiffsave.c:588 libvips/foreign/vips2magick.c:650 +#: libvips/foreign/webpload.c:424 libvips/foreign/webpsave.c:1096 +#: libvips/resample/thumbnail.c:1445 +msgid "Buffer" +msgstr "Puffer" + +#: libvips/foreign/cgifsave.c:1118 libvips/foreign/dzsave.c:2657 +#: libvips/foreign/heifsave.c:963 libvips/foreign/jp2ksave.c:1127 +#: libvips/foreign/jpegsave.c:440 libvips/foreign/jxlsave.c:961 +#: libvips/foreign/pngsave.c:438 libvips/foreign/radsave.c:274 +#: libvips/foreign/rawsave.c:315 libvips/foreign/spngsave.c:919 +#: libvips/foreign/tiffsave.c:589 libvips/foreign/vips2magick.c:651 +#: libvips/foreign/webpsave.c:1097 +msgid "Buffer to save to" +msgstr "Puffer, in den gespeichert werden soll" + +#: libvips/foreign/csvload.c:301 +#, fuzzy, c-format +msgid "bad number, line %d, column %d" +msgstr "Fehler beim Auswerten von Nummer, Zeile %d, Spalte %d" + +#: libvips/foreign/csvload.c:341 libvips/foreign/csvload.c:402 +#: libvips/foreign/csvload.c:434 +#, fuzzy +msgid "unexpected end of file" +msgstr "Unerwartetes Ende der Zeichenkette" + +#: libvips/foreign/csvload.c:440 +#, c-format +msgid "line %d has only %d columns" +msgstr "" + +#: libvips/foreign/csvload.c:479 +#, fuzzy +msgid "load csv" +msgstr "CSV aus Datei laden" + +#: libvips/foreign/csvload.c:492 +msgid "Skip" +msgstr "überspringen" + +#: libvips/foreign/csvload.c:493 +msgid "Skip this many lines at the start of the file" +msgstr "so viele Zeilen ab dem Dateianfang überspringen" + +#: libvips/foreign/csvload.c:499 +msgid "Lines" +msgstr "Zeilen" + +#: libvips/foreign/csvload.c:500 +msgid "Read this many lines from the file" +msgstr "so viele Zeilen aus der Datei lesen" + +#: libvips/foreign/csvload.c:506 +msgid "Whitespace" +msgstr "Leerraum" + +#: libvips/foreign/csvload.c:507 +msgid "Set of whitespace characters" +msgstr "Satz von Leerraumzeichen" + +#: libvips/foreign/csvload.c:513 libvips/foreign/csvsave.c:223 +msgid "Separator" +msgstr "Trenner" + +#: libvips/foreign/csvload.c:514 +msgid "Set of separator characters" +msgstr "Satz von Trennzeichen" + +#: libvips/foreign/csvload.c:661 libvips/foreign/fitsload.c:338 +#: libvips/foreign/heifload.c:1414 libvips/foreign/jp2kload.c:1448 +#: libvips/foreign/jpegload.c:278 libvips/foreign/jxlload.c:1357 +#: libvips/foreign/matrixload.c:462 libvips/foreign/niftiload.c:792 +#: libvips/foreign/nsgifload.c:909 libvips/foreign/openslideload.c:1230 +#: libvips/foreign/pdfiumload.c:932 libvips/foreign/pngload.c:242 +#: libvips/foreign/popplerload.c:809 libvips/foreign/ppmload.c:890 +#: libvips/foreign/radload.c:205 libvips/foreign/spngload.c:757 +#: libvips/foreign/svgload.c:836 libvips/foreign/tiffload.c:302 +#: libvips/foreign/vipsload.c:312 libvips/foreign/webpload.c:266 +#: libvips/resample/thumbnail.c:1658 +msgid "Source" +msgstr "" + +#: libvips/foreign/csvload.c:662 libvips/foreign/fitsload.c:339 +#: libvips/foreign/heifload.c:1415 libvips/foreign/jp2kload.c:1449 +#: libvips/foreign/jpegload.c:279 libvips/foreign/jxlload.c:1358 +#: libvips/foreign/matrixload.c:463 libvips/foreign/niftiload.c:793 +#: libvips/foreign/nsgifload.c:910 libvips/foreign/openslideload.c:1231 +#: libvips/foreign/pdfiumload.c:933 libvips/foreign/pngload.c:243 +#: libvips/foreign/popplerload.c:810 libvips/foreign/ppmload.c:891 +#: libvips/foreign/radload.c:206 libvips/foreign/spngload.c:758 +#: libvips/foreign/svgload.c:837 libvips/foreign/tiffload.c:303 +#: libvips/foreign/vipsload.c:313 libvips/foreign/webpload.c:267 +#: libvips/iofuncs/sbuf.c:89 libvips/resample/thumbnail.c:1659 +#, fuzzy +msgid "Source to load from" +msgstr "Puffer, aus dem geladen werden soll" + +#: libvips/foreign/csvsave.c:215 +#, fuzzy +msgid "save image to csv" +msgstr "Bild in CSV-Datei speichern" + +#: libvips/foreign/csvsave.c:224 +msgid "Separator characters" +msgstr "Trennzeichen" + +#: libvips/foreign/dzsave.c:2008 +#, fuzzy +msgid "overlap too large" +msgstr "Überlappen zu schmal" + +# http://de.wikipedia.org/wiki/Portable_Pixmap +#: libvips/foreign/dzsave.c:2319 +#, fuzzy +msgid "save image to deep zoom format" +msgstr "Bild in PPM-Datei speichern" + +#: libvips/foreign/dzsave.c:2329 libvips/foreign/dzsave.c:2330 +#, fuzzy +msgid "Image name" +msgstr "Bilddateiname" + +#: libvips/foreign/dzsave.c:2336 +msgid "Layout" +msgstr "" + +#: libvips/foreign/dzsave.c:2337 +msgid "Directory layout" +msgstr "" + +#: libvips/foreign/dzsave.c:2343 +msgid "Suffix" +msgstr "" + +#: libvips/foreign/dzsave.c:2344 +msgid "Filename suffix for tiles" +msgstr "" + +#: libvips/foreign/dzsave.c:2350 +#, fuzzy +msgid "Overlap" +msgstr "kein Überlappen" + +#: libvips/foreign/dzsave.c:2351 +#, fuzzy +msgid "Tile overlap in pixels" +msgstr "Kachelhöhe in Bildpunkten" + +#: libvips/foreign/dzsave.c:2357 +#, fuzzy +msgid "Tile size" +msgstr "Kachelbreite" + +#: libvips/foreign/dzsave.c:2358 +#, fuzzy +msgid "Tile size in pixels" +msgstr "Kachelbreite in Bildpunkten" + +#: libvips/foreign/dzsave.c:2365 libvips/foreign/tiffsave.c:379 +#, fuzzy +msgid "Pyramid depth" +msgstr "Pyramide" + +#: libvips/foreign/dzsave.c:2371 +msgid "Center" +msgstr "" + +#: libvips/foreign/dzsave.c:2372 +#, fuzzy +msgid "Center image in tile" +msgstr "Bild in PNG-Datei speichern" + +#: libvips/foreign/dzsave.c:2379 +msgid "Rotate image during save" +msgstr "" + +#: libvips/foreign/dzsave.c:2385 +msgid "Container" +msgstr "" + +#: libvips/foreign/dzsave.c:2386 +msgid "Pyramid container type" +msgstr "" + +#: libvips/foreign/dzsave.c:2392 libvips/foreign/heifsave.c:795 +#: libvips/foreign/pngsave.c:211 libvips/foreign/spngsave.c:689 +#: libvips/foreign/tiffsave.c:257 +msgid "Compression" +msgstr "Komprimierung" + +#: libvips/foreign/dzsave.c:2393 +msgid "ZIP deflate compression level" +msgstr "" + +#: libvips/foreign/dzsave.c:2399 libvips/foreign/tiffsave.c:357 +msgid "Region shrink" +msgstr "" + +#: libvips/foreign/dzsave.c:2400 libvips/foreign/tiffsave.c:358 +msgid "Method to shrink regions" +msgstr "" + +#: libvips/foreign/dzsave.c:2406 +msgid "Skip blanks" +msgstr "" + +#: libvips/foreign/dzsave.c:2407 +msgid "Skip tiles which are nearly equal to the background" +msgstr "" + +#: libvips/foreign/dzsave.c:2413 +msgid "id" +msgstr "" + +#: libvips/foreign/dzsave.c:2414 +msgid "Resource ID" +msgstr "" + +#: libvips/foreign/dzsave.c:2420 libvips/foreign/heifsave.c:774 +#: libvips/foreign/jp2ksave.c:1000 libvips/foreign/jpegsave.c:164 +#: libvips/foreign/jxlsave.c:838 libvips/foreign/tiffsave.c:265 +#: libvips/foreign/webpsave.c:826 +msgid "Q" +msgstr "Q" + +#: libvips/foreign/dzsave.c:2421 libvips/foreign/heifsave.c:775 +#: libvips/foreign/jp2ksave.c:1001 libvips/foreign/jpegsave.c:165 +#: libvips/foreign/tiffsave.c:266 libvips/foreign/webpsave.c:827 +msgid "Q factor" +msgstr "Q-Faktor" + +#: libvips/foreign/dzsave.c:2430 +msgid "No strip" +msgstr "" + +#: libvips/foreign/dzsave.c:2431 +msgid "Don't strip tile metadata" +msgstr "" + +#: libvips/foreign/dzsave.c:2437 +#, fuzzy +msgid "Base name" +msgstr "Bilddateiname" + +#: libvips/foreign/dzsave.c:2438 +#, fuzzy +msgid "Base name to save to" +msgstr "Name der Datei in die gespeichert werden soll" + +#: libvips/foreign/dzsave.c:2444 +#, fuzzy +msgid "Directory name" +msgstr "Richtung" + +#: libvips/foreign/dzsave.c:2445 +#, fuzzy +msgid "Directory name to save to" +msgstr "Name der Datei in die gespeichert werden soll" + +#: libvips/foreign/dzsave.c:2465 libvips/foreign/tiffsave.c:350 +#, fuzzy +msgid "Properties" +msgstr "Transaktionen" + +#: libvips/foreign/dzsave.c:2466 +msgid "Write a properties file to the output directory" +msgstr "" + +# http://de.wikipedia.org/wiki/Portable_Pixmap +#: libvips/foreign/dzsave.c:2533 +#, fuzzy +msgid "save image to deepzoom target" +msgstr "Bild in PPM-Datei speichern" + +# http://de.wikipedia.org/wiki/Portable_Pixmap +#: libvips/foreign/dzsave.c:2593 +#, fuzzy +msgid "save image to deepzoom file" +msgstr "Bild in PPM-Datei speichern" + +#: libvips/foreign/dzsave.c:2652 +#, fuzzy +msgid "save image to dz buffer" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/exif.c:199 +#, fuzzy +msgid "exif too small" +msgstr "Ziel zu klein" + +#: libvips/foreign/exif.c:203 +#, fuzzy +msgid "exif too large" +msgstr "Fenster zu groß" + +#: libvips/foreign/exif.c:208 +#, fuzzy +msgid "unable to init exif" +msgstr "kann nicht gekürzt werden" + +#: libvips/foreign/exif.c:1260 libvips/foreign/exif.c:1270 +#: libvips/foreign/exif.c:1279 libvips/foreign/exif.c:1319 +#, fuzzy, c-format +msgid "bad exif meta \"%s\"" +msgstr "falscher Modus »%s«" + +#: libvips/foreign/exif.c:1496 +msgid "error saving EXIF" +msgstr "Fehler beim Speichern von EXIF" + +#: libvips/foreign/fits.c:184 libvips/foreign/matlab.c:113 +#: libvips/iofuncs/vips.c:159 libvips/mosaicing/global_balance.c:1240 +#: libvips/mosaicing/global_balance.c:1690 +#, c-format +msgid "unable to open \"%s\"" +msgstr "»%s« kann nicht geöffnet werden" + +#: libvips/foreign/fits.c:237 +msgid "no HDU found with naxes > 0" +msgstr "" + +#: libvips/foreign/fits.c:275 +msgid "dimensions above 3 must be size 1" +msgstr "Dimensionen größer drei müssen die Größe eins haben" + +#: libvips/foreign/fits.c:290 +#, c-format +msgid "bad number of axis %d" +msgstr "falsche Achsenanzahl %d" + +#: libvips/foreign/fits.c:301 +#, c-format +msgid "unsupported bitpix %d\n" +msgstr "nicht unterstützte »bitpix« %d\n" + +#: libvips/foreign/fits.c:586 libvips/iofuncs/vips.c:222 +#, c-format +msgid "unable to write to \"%s\"" +msgstr "auf »%s« kann nicht geschrieben werden" + +#: libvips/foreign/fits.c:729 +#, c-format +msgid "unsupported BandFmt %d\n" +msgstr "nicht unterstütztes BandFmt %d\n" + +#: libvips/foreign/fitsload.c:101 libvips/foreign/niftiload.c:130 +#: libvips/foreign/openslideload.c:916 +msgid "no filename available" +msgstr "" + +#: libvips/foreign/fitsload.c:183 +#, fuzzy +msgid "FITS loader base class" +msgstr "Basisklasse" + +#: libvips/foreign/fitsload.c:251 +msgid "load a FITS image" +msgstr "ein FITS-Bild laden" + +#: libvips/foreign/fitsload.c:329 +#, fuzzy +msgid "load FITS from a source" +msgstr "ein FITS-Bild laden" + +# http://de.wikipedia.org/wiki/Flexible_Image_Transport_System +#: libvips/foreign/fitssave.c:129 +msgid "save image to fits file" +msgstr "Bild in FITS-Datei speichern" + +#: libvips/foreign/foreign.c:408 +msgid "load and save image files" +msgstr "Bilddateien laden und speichern" + +#: libvips/foreign/foreign.c:607 +#, fuzzy, c-format +msgid "file \"%s\" does not exist" +msgstr "Datei »%s« nicht gefunden" + +#: libvips/foreign/foreign.c:612 +#, c-format +msgid "\"%s\" is a directory" +msgstr "" + +#: libvips/foreign/foreign.c:621 libvips/foreign/foreign.c:2003 +#, c-format +msgid "\"%s\" is not a known file format" +msgstr "»%s« ist kein bekanntes Dateiformat" + +#: libvips/foreign/foreign.c:708 +#, fuzzy +msgid "buffer is not in a known format" +msgstr "»%s« ist kein bekanntes Dateiformat" + +#: libvips/foreign/foreign.c:769 +#, fuzzy +msgid "source is not in a known format" +msgstr "»%s« ist kein bekanntes Dateiformat" + +#: libvips/foreign/foreign.c:979 +#, fuzzy +msgid "images do not match between header and load" +msgstr "Bilder passen in der Bildpunktgröße nicht zusammen" + +#: libvips/foreign/foreign.c:1210 +#, fuzzy +msgid "loaders" +msgstr "Dateilader" + +#: libvips/foreign/foreign.c:1221 +msgid "Flags" +msgstr "Schalter" + +#: libvips/foreign/foreign.c:1222 +msgid "Flags for this file" +msgstr "Schalter für diese Datei" + +#: libvips/foreign/foreign.c:1228 libvips/iofuncs/target.c:294 +msgid "Memory" +msgstr "" + +#: libvips/foreign/foreign.c:1229 +msgid "Force open via memory" +msgstr "" + +#: libvips/foreign/foreign.c:1236 +#, fuzzy +msgid "Required access pattern for this file" +msgstr "Komprimierung für diese Datei" + +#: libvips/foreign/foreign.c:1242 libvips/resample/thumbnail.c:1037 +#, fuzzy +msgid "Fail on" +msgstr "scheitern" + +#: libvips/foreign/foreign.c:1243 libvips/resample/thumbnail.c:1038 +msgid "Error level to fail on" +msgstr "" + +#: libvips/foreign/foreign.c:1249 +msgid "Revalidate" +msgstr "" + +#: libvips/foreign/foreign.c:1250 +msgid "Don't use a cached result for this operation" +msgstr "" + +#: libvips/foreign/foreign.c:1256 +msgid "Sequential" +msgstr "sequenziell" + +#: libvips/foreign/foreign.c:1257 +msgid "Sequential read only" +msgstr "sequenziell nur mit Lesezugriff" + +#: libvips/foreign/foreign.c:1263 +msgid "Fail" +msgstr "scheitern" + +#: libvips/foreign/foreign.c:1264 +msgid "Fail on first warning" +msgstr "scheitert bei erster Warnung" + +#: libvips/foreign/foreign.c:1270 +msgid "Disc" +msgstr "Platte" + +#: libvips/foreign/foreign.c:1271 +msgid "Open to disc" +msgstr "offen zur Platte" + +#: libvips/foreign/foreign.c:1871 +#, fuzzy +msgid "savers" +msgstr "Dateispeicherer" + +#: libvips/foreign/foreign.c:1895 +msgid "Image to save" +msgstr "zu speicherndes Bild" + +#: libvips/foreign/foreign.c:1900 +msgid "Keep" +msgstr "" + +#: libvips/foreign/foreign.c:1901 +msgid "Which metadata to retain" +msgstr "" + +#: libvips/foreign/foreign.c:1916 +msgid "Set page height for multipage save" +msgstr "" + +#: libvips/foreign/foreign.c:1923 +#, fuzzy +msgid "Filename of ICC profile to embed" +msgstr "einzubettendes ICC-Profil" + +#: libvips/foreign/foreign.c:1929 +msgid "Strip" +msgstr "" + +#: libvips/foreign/foreign.c:1930 +#, fuzzy +msgid "Strip all metadata from image" +msgstr "einen Bereich eines Bildes extrahieren" + +#: libvips/foreign/foreign.c:2158 +#, fuzzy, c-format +msgid "\"%s\" is not a known target format" +msgstr "»%s« ist kein bekanntes Dateiformat" + +#: libvips/foreign/foreign.c:2216 +#, fuzzy, c-format +msgid "\"%s\" is not a known buffer format" +msgstr "»%s« ist kein bekanntes Dateiformat" + +#: libvips/foreign/heifload.c:820 libvips/foreign/jxlload.c:753 +#: libvips/foreign/nsgifload.c:448 libvips/foreign/webp2vips.c:501 +#, fuzzy +msgid "bad page number" +msgstr "falsche Seitennummer %d" + +#: libvips/foreign/heifload.c:872 +msgid "undefined bits per pixel" +msgstr "" + +#: libvips/foreign/heifload.c:884 +msgid "not all pages are the same size" +msgstr "" + +#: libvips/foreign/heifload.c:983 +#, fuzzy +msgid "bad image dimensions on decode" +msgstr "Überlaufganzzahl der Bildabmessungen" + +#: libvips/foreign/heifload.c:990 +#, fuzzy +msgid "unable to get image data" +msgstr "Dateistatus kann nicht abgefragt werden" + +#: libvips/foreign/heifload.c:1075 +#, fuzzy +msgid "load a HEIF image" +msgstr "ein FITS-Bild laden" + +#: libvips/foreign/heifload.c:1083 libvips/foreign/jp2kload.c:1229 +#: libvips/foreign/jxlload.c:1132 libvips/foreign/magick6load.c:141 +#: libvips/foreign/magick7load.c:382 libvips/foreign/nsgifload.c:620 +#: libvips/foreign/pdfiumload.c:695 libvips/foreign/popplerload.c:545 +#: libvips/foreign/tiffload.c:196 libvips/foreign/webpload.c:178 +msgid "Page" +msgstr "Seite" + +#: libvips/foreign/heifload.c:1084 libvips/foreign/jxlload.c:1133 +#: libvips/foreign/magick6load.c:142 libvips/foreign/magick7load.c:383 +#: libvips/foreign/nsgifload.c:621 libvips/foreign/pdfiumload.c:696 +#: libvips/foreign/popplerload.c:546 libvips/foreign/tiffload.c:197 +#: libvips/foreign/webpload.c:179 +#, fuzzy +msgid "First page to load" +msgstr "Name der Datei, aus der geladen werden soll" + +#: libvips/foreign/heifload.c:1091 libvips/foreign/jxlload.c:1140 +#: libvips/foreign/magick6load.c:149 libvips/foreign/magick7load.c:390 +#: libvips/foreign/nsgifload.c:628 libvips/foreign/pdfiumload.c:703 +#: libvips/foreign/popplerload.c:553 libvips/foreign/tiffload.c:204 +#: libvips/foreign/webpload.c:186 +#, fuzzy +msgid "Number of pages to load, -1 for all" +msgstr "Anzahl der Patches ein Diagramm hinunter" + +#: libvips/foreign/heifload.c:1097 +msgid "Thumbnail" +msgstr "" + +#: libvips/foreign/heifload.c:1098 +#, fuzzy +msgid "Fetch thumbnail image" +msgstr "Miniaturansicht auf GRÖẞE setzen" + +#: libvips/foreign/heifload.c:1104 libvips/foreign/jpegload.c:198 +#: libvips/foreign/tiffload.c:210 +msgid "Autorotate" +msgstr "" + +#: libvips/foreign/heifload.c:1105 libvips/foreign/jpegload.c:199 +msgid "Rotate image using exif orientation" +msgstr "" + +#: libvips/foreign/heifload.c:1112 libvips/foreign/jpegload.c:206 +#: libvips/foreign/pngload.c:171 libvips/foreign/spngload.c:678 +#: libvips/foreign/svgload.c:732 libvips/foreign/tiffload.c:225 +msgid "Unlimited" +msgstr "" + +#: libvips/foreign/heifload.c:1113 libvips/foreign/jpegload.c:207 +#: libvips/foreign/pngload.c:172 libvips/foreign/spngload.c:679 +#: libvips/foreign/tiffload.c:226 +msgid "Remove all denial of service limits" +msgstr "" + +#: libvips/foreign/heifload.c:1341 libvips/foreign/jp2kload.c:1386 +#: libvips/foreign/jpegload.c:431 libvips/foreign/jxlload.c:1294 +#: libvips/foreign/magick6load.c:314 libvips/foreign/magick7load.c:933 +#: libvips/foreign/nsgifload.c:844 libvips/foreign/pdfiumload.c:873 +#: libvips/foreign/pngload.c:395 libvips/foreign/popplerload.c:750 +#: libvips/foreign/radload.c:357 libvips/foreign/spngload.c:912 +#: libvips/foreign/svgload.c:998 libvips/foreign/tiffload.c:461 +#: libvips/foreign/webpload.c:425 libvips/resample/thumbnail.c:1446 +msgid "Buffer to load from" +msgstr "Puffer, aus dem geladen werden soll" + +#: libvips/foreign/heifsave.c:441 +#, fuzzy +msgid "unimplemented format conversion" +msgstr "nicht implementierte Maske" + +#: libvips/foreign/heifsave.c:550 +#, fuzzy, c-format +msgid "%d-bit colour depth not supported" +msgstr "%d-dimensionale Bilder nicht unterstützt" + +#: libvips/foreign/heifsave.c:583 +#, fuzzy +msgid "Unsupported compression" +msgstr "nicht unterstützter Farbtyp" + +#: libvips/foreign/heifsave.c:767 +#, fuzzy +msgid "save image in HEIF format" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/heifsave.c:788 libvips/foreign/jp2ksave.c:985 +#: libvips/foreign/jxlsave.c:831 libvips/foreign/tiffsave.c:371 +#: libvips/foreign/webpsave.c:833 +msgid "Lossless" +msgstr "" + +#: libvips/foreign/heifsave.c:789 libvips/foreign/jp2ksave.c:986 +#: libvips/foreign/jxlsave.c:832 libvips/foreign/webpsave.c:834 +msgid "Enable lossless compression" +msgstr "" + +#: libvips/foreign/heifsave.c:796 +#, fuzzy +msgid "Compression format" +msgstr "Komprimierungsfaktor" + +#: libvips/foreign/heifsave.c:804 libvips/foreign/heifsave.c:819 +msgid "CPU effort" +msgstr "" + +#: libvips/foreign/heifsave.c:810 libvips/foreign/jp2ksave.c:992 +#: libvips/foreign/jpegsave.c:220 +#, fuzzy +msgid "Subsample mode" +msgstr "Öffnen-Modus" + +#: libvips/foreign/heifsave.c:811 libvips/foreign/jp2ksave.c:993 +#: libvips/foreign/jpegsave.c:221 +msgid "Select chroma subsample operation mode" +msgstr "" + +#: libvips/foreign/heifsave.c:818 +msgid "Speed" +msgstr "" + +#: libvips/foreign/heifsave.c:825 +msgid "Encoder" +msgstr "" + +#: libvips/foreign/heifsave.c:826 +msgid "Select encoder to use" +msgstr "" + +#: libvips/foreign/heifsave.c:1047 +#, fuzzy +msgid "save image in AVIF format" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/jp2kload.c:235 +#, fuzzy +msgid "unable to create jp2k stream" +msgstr "Thread kann nicht erstellt werden" + +#: libvips/foreign/jp2kload.c:548 +#, fuzzy, c-format +msgid "unsupported colourspace %d" +msgstr "nicht unterstützter Farbraum %d" + +#: libvips/foreign/jp2kload.c:597 +#, fuzzy +msgid "too many image bands" +msgstr "zu viele Argumente" + +#: libvips/foreign/jp2kload.c:601 +#, fuzzy +msgid "no image components" +msgstr "keine Bilddaten" + +#: libvips/foreign/jp2kload.c:618 +msgid "components differ in geometry" +msgstr "" + +#: libvips/foreign/jp2kload.c:625 +msgid "components differ in precision" +msgstr "" + +#: libvips/foreign/jp2kload.c:996 libvips/foreign/jp2kload.c:1093 +#, fuzzy +msgid "decoded image does not match container" +msgstr "»ink«-Bild passt nicht in das Bild" + +#: libvips/foreign/jp2kload.c:1217 +#, fuzzy +msgid "load JPEG2000 image" +msgstr "ein FITS-Bild laden" + +#: libvips/foreign/jp2kload.c:1230 +#, fuzzy +msgid "Load this page from the image" +msgstr "diese Seite aus der Datei laden" + +#: libvips/foreign/jp2kload.c:1600 libvips/foreign/jp2ksave.c:1434 +#, fuzzy +msgid "libvips built without JPEG2000 support" +msgstr "VIPS wurde ohne FFT-Unterstützung konfiguriert" + +#: libvips/foreign/jp2ksave.c:818 +#, fuzzy +msgid "not an integer format" +msgstr "»%s« ist kein bekanntes Dateiformat" + +#: libvips/foreign/jp2ksave.c:963 +msgid "save image in JPEG2000 format" +msgstr "" + +#: libvips/foreign/jpeg2vips.c:415 +#, c-format +msgid "read gave %ld warnings" +msgstr "Lesen ergab %ld Warnungen" + +#: libvips/foreign/jpeg2vips.c:886 libvips/foreign/spngload.c:529 +#: libvips/foreign/vipspng.c:723 +#, c-format +msgid "out of order read at line %d" +msgstr "" + +#: libvips/foreign/jpegload.c:116 +#, c-format +msgid "bad shrink factor %d" +msgstr "falscher Schrumpffaktor %d" + +#: libvips/foreign/jpegload.c:177 +msgid "load jpeg" +msgstr "JPEG laden" + +#: libvips/foreign/jpegload.c:191 libvips/foreign/webpload.c:199 +msgid "Shrink" +msgstr "verkleinern" + +#: libvips/foreign/jpegload.c:192 libvips/foreign/webpload.c:200 +msgid "Shrink factor on load" +msgstr "falscher Verkleinerungsfaktor %d" + +#: libvips/foreign/jpegload.c:270 +#, fuzzy +msgid "load image from jpeg source" +msgstr "Bild in den JPEG-Puffer speichern" + +#: libvips/foreign/jpegload.c:346 +msgid "load jpeg from file" +msgstr "JPEG aus Datei laden" + +#: libvips/foreign/jpegload.c:424 +msgid "load jpeg from buffer" +msgstr "JPEG aus Puffer laden" + +#: libvips/foreign/jpegsave.c:153 +msgid "save jpeg" +msgstr "JPEG speichern" + +#: libvips/foreign/jpegsave.c:171 +#, fuzzy +msgid "Optimize coding" +msgstr "Bildpunktkodierung" + +#: libvips/foreign/jpegsave.c:172 +msgid "Compute optimal Huffman coding tables" +msgstr "" + +#: libvips/foreign/jpegsave.c:178 libvips/foreign/pngsave.c:218 +#: libvips/foreign/spngsave.c:696 +msgid "Interlace" +msgstr "Zeilensprung" + +#: libvips/foreign/jpegsave.c:179 +msgid "Generate an interlaced (progressive) jpeg" +msgstr "" + +#: libvips/foreign/jpegsave.c:185 +msgid "No subsample" +msgstr "" + +#: libvips/foreign/jpegsave.c:186 +msgid "Disable chroma subsample" +msgstr "" + +#: libvips/foreign/jpegsave.c:192 +msgid "Trellis quantisation" +msgstr "" + +#: libvips/foreign/jpegsave.c:193 +msgid "Apply trellis quantisation to each 8x8 block" +msgstr "" + +#: libvips/foreign/jpegsave.c:199 +msgid "Overshoot de-ringing" +msgstr "" + +#: libvips/foreign/jpegsave.c:200 +msgid "Apply overshooting to samples with extreme values" +msgstr "" + +#: libvips/foreign/jpegsave.c:206 +msgid "Optimize scans" +msgstr "" + +#: libvips/foreign/jpegsave.c:207 +msgid "Split spectrum of DCT coefficients into separate scans" +msgstr "" + +#: libvips/foreign/jpegsave.c:213 +msgid "Quantization table" +msgstr "" + +#: libvips/foreign/jpegsave.c:214 +msgid "Use predefined quantization table with given index" +msgstr "" + +#: libvips/foreign/jpegsave.c:228 +msgid "Restart interval" +msgstr "" + +#: libvips/foreign/jpegsave.c:229 +msgid "Add restart markers every specified number of mcu" +msgstr "" + +#: libvips/foreign/jpegsave.c:288 +#, fuzzy +msgid "save image to jpeg target" +msgstr "Bild in JPEG-Datei speichern" + +#: libvips/foreign/jpegsave.c:357 +msgid "save image to jpeg file" +msgstr "Bild in JPEG-Datei speichern" + +#: libvips/foreign/jpegsave.c:435 +msgid "save image to jpeg buffer" +msgstr "Bild in den JPEG-Puffer speichern" + +# http://de.wikipedia.org/wiki/MIME#image +#: libvips/foreign/jpegsave.c:511 +msgid "save image to jpeg mime" +msgstr "Bild in JPEG-MIME speichern" + +#: libvips/foreign/jxlload.c:251 libvips/foreign/jxlsave.c:433 +#: libvips/iofuncs/dbuf.c:81 libvips/iofuncs/util.c:684 +msgid "out of memory" +msgstr "Hauptspeicher reicht nicht aus" + +#: libvips/foreign/jxlload.c:576 +#, fuzzy +msgid "bad buffer size" +msgstr "falsche Größe" + +#: libvips/foreign/jxlload.c:602 libvips/foreign/webp2vips.c:724 +msgid "not enough frames" +msgstr "" + +#: libvips/foreign/jxlload.c:683 libvips/foreign/radiance.c:704 +#, fuzzy +msgid "image size out of bounds" +msgstr "Bild muss ein Band haben" + +#: libvips/foreign/jxlload.c:1119 +#, fuzzy +msgid "load JPEG-XL image" +msgstr "ein OpenEXR-Bild laden" + +#: libvips/foreign/jxlsave.c:748 libvips/foreign/webpsave.c:744 +#, c-format +msgid "failed to allocate %zu bytes" +msgstr "" + +#: libvips/foreign/jxlsave.c:796 +msgid "save image in JPEG-XL format" +msgstr "" + +#: libvips/foreign/jxlsave.c:810 +msgid "Tier" +msgstr "" + +#: libvips/foreign/jxlsave.c:811 +msgid "Decode speed tier" +msgstr "" + +#: libvips/foreign/jxlsave.c:817 libvips/morphology/nearest.c:315 +msgid "Distance" +msgstr "" + +#: libvips/foreign/jxlsave.c:818 +msgid "Target butteraugli distance" +msgstr "" + +#: libvips/foreign/jxlsave.c:825 +msgid "Encoding effort" +msgstr "" + +#: libvips/foreign/jxlsave.c:839 +#, fuzzy +msgid "Quality factor" +msgstr "Q-Faktor" + +#: libvips/foreign/magick2vips.c:305 +#, c-format +msgid "unsupported image type %d" +msgstr "nicht unterstützter Bildtyp %d" + +#: libvips/foreign/magick2vips.c:354 libvips/foreign/magick7load.c:471 +#, c-format +msgid "bad image dimensions %d x %d pixels, %d bands" +msgstr "" + +#: libvips/foreign/magick2vips.c:384 +#, c-format +msgid "unsupported bit depth %d" +msgstr "nicht unterstützte Bit-Tiefe %d" + +#: libvips/foreign/magick2vips.c:791 libvips/foreign/webp2vips.c:638 +msgid "unable to read pixels" +msgstr "Bildpunkte können nicht gelesen werden" + +#: libvips/foreign/magick2vips.c:823 libvips/foreign/magick2vips.c:861 +#, fuzzy, c-format +msgid "unable to read file \"%s\"" +msgstr "Profil kann nicht gelesen werden" + +#: libvips/foreign/magick2vips.c:870 libvips/foreign/magick2vips.c:949 +msgid "bad image size" +msgstr "falsche Bildgröße" + +#: libvips/foreign/magick2vips.c:902 +#, fuzzy +msgid "unable to read buffer" +msgstr "In den Puffer kann nicht geschrieben werden." + +#: libvips/foreign/magick2vips.c:940 +#, fuzzy +msgid "unable to ping blob" +msgstr "»%s« kann nicht geöffnet werden" + +#: libvips/foreign/magick6load.c:113 +#, fuzzy +msgid "load with ImageMagick" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/magick6load.c:134 libvips/foreign/magick7load.c:375 +msgid "Density" +msgstr "" + +#: libvips/foreign/magick6load.c:135 libvips/foreign/magick7load.c:376 +msgid "Canvas resolution for rendering vector formats like SVG" +msgstr "" + +#: libvips/foreign/magick6load.c:155 libvips/foreign/magick7load.c:396 +msgid "All frames" +msgstr "" + +#: libvips/foreign/magick6load.c:156 libvips/foreign/magick7load.c:397 +#, fuzzy +msgid "Read all frames from an image" +msgstr "einen Bereich eines Bildes extrahieren" + +#: libvips/foreign/magick6load.c:231 +msgid "load file with ImageMagick" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/magick6load.c:306 +#, fuzzy +msgid "load buffer with ImageMagick" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/magick7load.c:353 +#, fuzzy +msgid "load with ImageMagick7" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/magick7load.c:414 +#, c-format +msgid "Magick: %s %s" +msgstr "" + +#: libvips/foreign/magick7load.c:491 +#, fuzzy, c-format +msgid "unsupported bit depth %zd" +msgstr "nicht unterstützte Bit-Tiefe %d" + +#: libvips/foreign/magick7load.c:845 +#, fuzzy +msgid "load file with ImageMagick7" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/magick7load.c:926 +#, fuzzy +msgid "load buffer with ImageMagick7" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/magick.c:804 +#, fuzzy, c-format +msgid "libMagick error: %s %s" +msgstr "" +"Datei »%s« kann nicht gelesen werden\n" +"libMagick-Fehler: %s %s" + +#: libvips/foreign/magick.c:807 +#, fuzzy, c-format +msgid "libMagick error: %s" +msgstr "EXR-Fehler: %s" + +#: libvips/foreign/magick.c:810 +msgid "libMagick error:" +msgstr "" + +#: libvips/foreign/matlab.c:121 +#, c-format +msgid "no matrix variables in \"%s\"" +msgstr "keine Matrixvariablen in »%s«" + +#: libvips/foreign/matlab.c:203 +#, c-format +msgid "unsupported rank %d\n" +msgstr "nicht unterstützte Rangstufe %d\n" + +#: libvips/foreign/matlab.c:211 +#, c-format +msgid "unsupported class type %d\n" +msgstr "nicht unterstützter Klassentyp %d\n" + +#: libvips/foreign/matlab.c:265 +msgid "Mat_VarReadDataAll failed" +msgstr "»Mat_VarReadDataAll« fehlgeschlagen" + +# http://www.dateiendung.com/format/mat +#: libvips/foreign/matload.c:122 +msgid "load mat from file" +msgstr "Mat aus Datei laden" + +#: libvips/foreign/matrixload.c:128 libvips/foreign/matrixload.c:242 +#, fuzzy, c-format +msgid "bad number \"%s\"" +msgstr "falscher Modus »%s«" + +#: libvips/foreign/matrixload.c:137 +msgid "no width / height" +msgstr "" + +#: libvips/foreign/matrixload.c:143 +msgid "width / height not int" +msgstr "" + +#: libvips/foreign/matrixload.c:156 +#, fuzzy +msgid "width / height out of range" +msgstr "Parameter außerhalb des Bereichs" + +#: libvips/foreign/matrixload.c:160 +msgid "zero scale" +msgstr "" + +#: libvips/foreign/matrixload.c:251 +#, c-format +msgid "line %d too short" +msgstr "" + +# http://www.dateiendung.com/format/mat +#: libvips/foreign/matrixload.c:273 +#, fuzzy +msgid "load matrix" +msgstr "Mat aus Datei laden" + +# http://de.wikipedia.org/wiki/Rohdatenformat_(Fotografie) +#: libvips/foreign/matrixsave.c:175 +#, fuzzy +msgid "save image to matrix" +msgstr "Bild in Rohdatenformatdatei speichern" + +#: libvips/foreign/matrixsave.c:323 +#, fuzzy +msgid "print matrix" +msgstr "falsche Eingabematrix" + +#: libvips/foreign/niftiload.c:406 +#, fuzzy +msgid "invalid dimension" +msgstr "falsche Abmessungen" + +#: libvips/foreign/niftiload.c:417 +#, fuzzy +msgid "invalid resolution" +msgstr "ungültiges Argument" + +#: libvips/foreign/niftiload.c:431 libvips/foreign/niftiload.c:435 +#: libvips/foreign/niftisave.c:309 +#, fuzzy +msgid "dimension overflow" +msgstr "Überlaufganzzahl der Bildabmessungen" + +#: libvips/foreign/niftiload.c:536 +#, fuzzy +msgid "unable to read NIFTI header" +msgstr "Kopfdaten für »%s« können nicht gelesen werden" + +#: libvips/foreign/niftiload.c:564 +#, fuzzy +msgid "unable to load NIFTI file" +msgstr "Profil kann nicht gelesen werden" + +#: libvips/foreign/niftiload.c:594 +#, fuzzy +msgid "load a NIFTI image" +msgstr "ein FITS-Bild laden" + +#: libvips/foreign/niftiload.c:705 +msgid "load NIfTI volume" +msgstr "" + +#: libvips/foreign/niftiload.c:783 +msgid "load NIfTI volumes" +msgstr "" + +#: libvips/foreign/niftisave.c:115 libvips/foreign/niftisave.c:322 +#, fuzzy +msgid "unsupported libvips image type" +msgstr "nicht unterstützter Bildtyp %d" + +#: libvips/foreign/niftisave.c:122 +#, fuzzy +msgid "8-bit colour images only" +msgstr "nur skalare Bilder" + +#: libvips/foreign/niftisave.c:132 +#, fuzzy +msgid "3 or 4 band colour images only" +msgstr "nur RGB-TIFF mit drei oder vier Bändern" + +#: libvips/foreign/niftisave.c:251 +msgid "bad nifti-ext- field name" +msgstr "" + +#: libvips/foreign/niftisave.c:260 +#, fuzzy +msgid "unable to attach nifti ext" +msgstr "Dateistatus kann nicht abgefragt werden" + +#: libvips/foreign/niftisave.c:315 libvips/foreign/nsgifload.c:644 +#: libvips/foreign/webp2vips.c:550 +#, fuzzy +msgid "bad image dimensions" +msgstr "falsche Abmessungen" + +#: libvips/foreign/niftisave.c:375 +#, fuzzy +msgid "unable to set nifti filename" +msgstr "Dateistatus kann nicht abgefragt werden" + +# http://de.wikipedia.org/wiki/Flexible_Image_Transport_System +#: libvips/foreign/niftisave.c:427 +#, fuzzy +msgid "save image to nifti file" +msgstr "Bild in FITS-Datei speichern" + +#: libvips/foreign/nsgifload.c:420 +msgid "no frames in GIF" +msgstr "" + +#: libvips/foreign/nsgifload.c:463 +#, fuzzy +msgid "bad frame" +msgstr "falscher Parameter" + +#: libvips/foreign/nsgifload.c:607 libvips/foreign/nsgifload.c:757 +#: libvips/foreign/nsgifload.c:837 +msgid "load GIF with libnsgif" +msgstr "" + +#: libvips/foreign/nsgifload.c:901 +#, fuzzy +msgid "load gif from source" +msgstr "TIFF aus Datei laden" + +#: libvips/foreign/openexr2vips.c:123 +#, c-format +msgid "EXR error: %s" +msgstr "EXR-Fehler: %s" + +#: libvips/foreign/openexrload.c:129 +msgid "load an OpenEXR image" +msgstr "ein OpenEXR-Bild laden" + +#: libvips/foreign/openslideload.c:207 +msgid "invalid associated image name" +msgstr "ungültiger zugehöriger Bildname" + +#: libvips/foreign/openslideload.c:252 +msgid "specify only one of level and associated image" +msgstr "" + +#: libvips/foreign/openslideload.c:259 +msgid "specify only one of attach_assicated and associated image" +msgstr "" + +#: libvips/foreign/openslideload.c:376 libvips/foreign/openslideload.c:491 +#: libvips/foreign/openslideload.c:652 +#, fuzzy, c-format +msgid "opening slide: %s" +msgstr "Fehler beim Öffnen des Dias" + +#: libvips/foreign/openslideload.c:398 +#, c-format +msgid "reading associated image: %s" +msgstr "zugehöriges Bild wird gelesen: %s" + +#: libvips/foreign/openslideload.c:485 +#, fuzzy +msgid "unsupported slide format" +msgstr "nicht unterstützte Bit-Tiefe" + +#: libvips/foreign/openslideload.c:498 +msgid "invalid slide level" +msgstr "ungültige Diastufe" + +#: libvips/foreign/openslideload.c:590 +#, c-format +msgid "getting dimensions: %s" +msgstr "Abfragen der Abmessungen: %s" + +#: libvips/foreign/openslideload.c:597 +msgid "image dimensions overflow int" +msgstr "Überlaufganzzahl der Bildabmessungen" + +#: libvips/foreign/openslideload.c:753 +#, c-format +msgid "reading region: %s" +msgstr "Region wird gelesen: %s" + +#: libvips/foreign/openslideload.c:1017 +msgid "load OpenSlide base class" +msgstr "" + +#: libvips/foreign/openslideload.c:1046 libvips/foreign/tiffsave.c:364 +msgid "Level" +msgstr "Ebene" + +#: libvips/foreign/openslideload.c:1047 +msgid "Load this level from the file" +msgstr "diese Ebene aus der Datei laden" + +#: libvips/foreign/openslideload.c:1053 +msgid "Autocrop" +msgstr "" + +#: libvips/foreign/openslideload.c:1054 +#, fuzzy +msgid "Crop to image bounds" +msgstr "Transaktionen für Bänder von Bildern" + +#: libvips/foreign/openslideload.c:1060 +msgid "Associated" +msgstr "dazugehörig" + +#: libvips/foreign/openslideload.c:1061 +msgid "Load this associated image" +msgstr "dieses zugehörige Bild laden" + +#: libvips/foreign/openslideload.c:1067 +#, fuzzy +msgid "Attach associated" +msgstr "dazugehörig" + +#: libvips/foreign/openslideload.c:1068 +#, fuzzy +msgid "Attach all associated images" +msgstr "dieses zugehörige Bild laden" + +#: libvips/foreign/openslideload.c:1074 +#, fuzzy +msgid "RGB" +msgstr "GB" + +#: libvips/foreign/openslideload.c:1075 +msgid "Output RGB (not RGBA)" +msgstr "" + +#: libvips/foreign/openslideload.c:1144 +msgid "load file with OpenSlide" +msgstr "Datei mit OpenSlide laden" + +#: libvips/foreign/openslideload.c:1223 +#, fuzzy +msgid "load source with OpenSlide" +msgstr "Datei mit OpenSlide laden" + +#: libvips/foreign/pdfiumload.c:196 +#, fuzzy +msgid "unknown error" +msgstr "Unix-Fehler" + +#: libvips/foreign/pdfiumload.c:291 +#, c-format +msgid "%s: too large for pdfium" +msgstr "" + +#: libvips/foreign/pdfiumload.c:307 +#, fuzzy, c-format +msgid "%s: unable to load" +msgstr "»fd« kann nicht geschlossen werden" + +#: libvips/foreign/pdfiumload.c:318 +#, c-format +msgid "%s: unable to initialize form fill environment" +msgstr "" + +#: libvips/foreign/pdfiumload.c:366 libvips/foreign/popplerload.c:239 +#, fuzzy, c-format +msgid "unable to load page %d" +msgstr "»fd« kann nicht geschlossen werden" + +#: libvips/foreign/pdfiumload.c:478 libvips/foreign/popplerload.c:333 +#, fuzzy +msgid "pages out of range" +msgstr "Parameter außerhalb des Bereichs" + +#: libvips/foreign/pdfiumload.c:513 +#, fuzzy +msgid "page size out of range" +msgstr "Parameter außerhalb des Bereichs" + +#: libvips/foreign/pdfiumload.c:685 +msgid "load PDF with PDFium" +msgstr "" + +#: libvips/foreign/pdfiumload.c:717 libvips/foreign/popplerload.c:567 +#: libvips/foreign/webpload.c:193 +msgid "Factor to scale by" +msgstr "" + +#: libvips/foreign/pdfiumload.c:724 libvips/foreign/popplerload.c:574 +#, fuzzy +msgid "Background colour" +msgstr "Hintergrund" + +#: libvips/foreign/pdfiumload.c:730 libvips/foreign/popplerload.c:580 +msgid "Password" +msgstr "" + +#: libvips/foreign/pdfiumload.c:731 libvips/foreign/popplerload.c:581 +msgid "Password to decrypt with" +msgstr "" + +# Portable Pixmap +#: libvips/foreign/pdfiumload.c:803 libvips/foreign/popplerload.c:680 +#, fuzzy +msgid "load PDF from file" +msgstr "PPM aus Datei laden" + +#: libvips/foreign/pdfiumload.c:866 libvips/foreign/popplerload.c:743 +#, fuzzy +msgid "load PDF from buffer" +msgstr "JPEG aus Puffer laden" + +#: libvips/foreign/pdfiumload.c:924 libvips/foreign/popplerload.c:801 +#, fuzzy +msgid "load PDF from source" +msgstr "JPEG aus Puffer laden" + +#: libvips/foreign/pngload.c:157 libvips/foreign/spngload.c:664 +#, fuzzy +msgid "load png base class" +msgstr "Basisklasse" + +#: libvips/foreign/pngload.c:234 libvips/foreign/spngload.c:749 +#, fuzzy +msgid "load png from source" +msgstr "PNG-Datei aus Datei laden" + +#: libvips/foreign/pngload.c:310 libvips/foreign/spngload.c:827 +msgid "load png from file" +msgstr "PNG-Datei aus Datei laden" + +#: libvips/foreign/pngload.c:388 libvips/foreign/spngload.c:905 +#, fuzzy +msgid "load png from buffer" +msgstr "JPEG aus Puffer laden" + +#: libvips/foreign/pngsave.c:202 +msgid "save png" +msgstr "PNG speichern" + +#: libvips/foreign/pngsave.c:212 libvips/foreign/spngsave.c:690 +msgid "Compression factor" +msgstr "Komprimierungsfaktor" + +#: libvips/foreign/pngsave.c:219 libvips/foreign/spngsave.c:697 +msgid "Interlace image" +msgstr "Zeilensprungbild" + +#: libvips/foreign/pngsave.c:225 libvips/foreign/spngsave.c:703 +msgid "Filter" +msgstr "" + +#: libvips/foreign/pngsave.c:226 +msgid "libpng row filter flag(s)" +msgstr "" + +#: libvips/foreign/pngsave.c:233 libvips/foreign/spngsave.c:711 +msgid "Palette" +msgstr "" + +#: libvips/foreign/pngsave.c:234 libvips/foreign/spngsave.c:712 +msgid "Quantise to 8bpp palette" +msgstr "" + +#: libvips/foreign/pngsave.c:240 libvips/foreign/spngsave.c:718 +#: libvips/foreign/vips2magick.c:489 +msgid "Quality" +msgstr "" + +#: libvips/foreign/pngsave.c:241 libvips/foreign/spngsave.c:719 +msgid "Quantisation quality" +msgstr "" + +#: libvips/foreign/pngsave.c:255 libvips/foreign/spngsave.c:733 +msgid "Write as a 1, 2, 4, 8 or 16 bit image" +msgstr "" + +#: libvips/foreign/pngsave.c:262 libvips/foreign/spngsave.c:740 +msgid "Quantisation CPU effort" +msgstr "" + +#: libvips/foreign/pngsave.c:268 libvips/foreign/spngsave.c:746 +msgid "Colours" +msgstr "" + +#: libvips/foreign/pngsave.c:269 libvips/foreign/spngsave.c:747 +#, fuzzy +msgid "Max number of palette colours" +msgstr "maximale Anzahl von Kacheln, die zwischengespeichert werden soll" + +# http://de.wikipedia.org/wiki/Rohdatenformat_(Fotografie) +#: libvips/foreign/pngsave.c:322 libvips/foreign/spngsave.c:801 +#, fuzzy +msgid "save image to target as PNG" +msgstr "Bild in Rohdatenformatdatei speichern" + +#: libvips/foreign/pngsave.c:374 +msgid "save image to png file" +msgstr "Bild in PNG-Datei speichern" + +#: libvips/foreign/pngsave.c:433 +msgid "save image to png buffer" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/popplerload.c:531 +msgid "load PDF with libpoppler" +msgstr "" + +#: libvips/foreign/ppmload.c:264 +msgid "bad magic number" +msgstr "falsche magische Zahl" + +#: libvips/foreign/ppmload.c:521 +#, fuzzy +msgid "file truncated" +msgstr "Datei wurde gekürzt" + +#: libvips/foreign/ppmload.c:746 +#, fuzzy +msgid "load ppm base class" +msgstr "Basisklasse" + +# Portable Pixmap +#: libvips/foreign/ppmload.c:823 +msgid "load ppm from file" +msgstr "PPM aus Datei laden" + +#: libvips/foreign/ppmsave.c:321 +#, fuzzy +msgid "too few bands for format" +msgstr "unbekanntes Bandformat %d" + +# http://de.wikipedia.org/wiki/Portable_Pixmap +#: libvips/foreign/ppmsave.c:499 +#, fuzzy +msgid "save to ppm" +msgstr "Bild in PPM-Datei speichern" + +#: libvips/foreign/ppmsave.c:507 libvips/foreign/vips2magick.c:483 +#, fuzzy +msgid "Format to save in" +msgstr "Format, in das umgewandelt werden soll" + +#: libvips/foreign/ppmsave.c:514 +msgid "ASCII" +msgstr "ASCII" + +#: libvips/foreign/ppmsave.c:515 +#, fuzzy +msgid "Save as ascii" +msgstr "Bild als ASCII speichern" + +#: libvips/foreign/ppmsave.c:522 +msgid "Set to 1 to write as a 1 bit image" +msgstr "" + +#: libvips/foreign/ppmsave.c:528 libvips/foreign/tiffsave.c:406 +msgid "Squash" +msgstr "quetschen" + +#: libvips/foreign/ppmsave.c:529 +msgid "Save as one bit" +msgstr "" + +# http://de.wikipedia.org/wiki/Portable_Pixmap +#: libvips/foreign/ppmsave.c:586 +msgid "save image to ppm file" +msgstr "Bild in PPM-Datei speichern" + +# http://de.wikipedia.org/wiki/Portable_Pixmap +#: libvips/foreign/ppmsave.c:675 +#, fuzzy +msgid "save image in pbm format" +msgstr "Bild in PPM-Datei speichern" + +#: libvips/foreign/ppmsave.c:707 +#, fuzzy +msgid "save image in pgm format" +msgstr "Bild in den PNG-Puffer speichern" + +# http://de.wikipedia.org/wiki/Portable_Pixmap +#: libvips/foreign/ppmsave.c:739 +#, fuzzy +msgid "save image in pfm format" +msgstr "Bild in PPM-Datei speichern" + +#: libvips/foreign/ppmsave.c:771 +#, fuzzy +msgid "save image in pnm format" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/quantise.c:469 +msgid "libvips not built with quantisation support" +msgstr "" + +#: libvips/foreign/radiance.c:438 +msgid "scanline length mismatch" +msgstr "" + +#: libvips/foreign/radiance.c:455 +msgid "overrun" +msgstr "" + +# http://radsite.lbl.gov/radiance/refer/Notes/picture_format.html +#: libvips/foreign/radiance.c:687 +msgid "error reading radiance header" +msgstr "Fehler beim Lesen der Radiance-Kopfzeilen" + +#: libvips/foreign/radiance.c:774 +#, fuzzy, c-format +msgid "read error line %d" +msgstr "Lesefehler" + +#: libvips/foreign/radload.c:125 +#, fuzzy +msgid "load rad base class" +msgstr "Basisklasse" + +# http://www.dateiendung.com/format/mat +#: libvips/foreign/radload.c:197 +#, fuzzy +msgid "load rad from source" +msgstr "Mat aus Datei laden" + +#: libvips/foreign/radload.c:273 +msgid "load a Radiance image from a file" +msgstr "ein Radiance-Bild aus einer Datei laden" + +#: libvips/foreign/radload.c:350 +#, fuzzy +msgid "load rad from buffer" +msgstr "JPEG aus Puffer laden" + +#: libvips/foreign/radsave.c:92 +#, fuzzy +msgid "save Radiance" +msgstr "Bild in Radiance-Datei speichern" + +#: libvips/foreign/radsave.c:150 +msgid "save image to Radiance file" +msgstr "Bild in Radiance-Datei speichern" + +#: libvips/foreign/radsave.c:203 +#, fuzzy +msgid "save image to Radiance target" +msgstr "Bild in Radiance-Datei speichern" + +#: libvips/foreign/radsave.c:269 +#, fuzzy +msgid "save image to Radiance buffer" +msgstr "Bild in Radiance-Datei speichern" + +#: libvips/foreign/rawload.c:131 +msgid "load raw data from a file" +msgstr "Rohdaten aus einer Datei laden" + +#: libvips/foreign/rawload.c:167 libvips/iofuncs/image.c:1200 +msgid "Size of header" +msgstr "Größe der Kopfdaten" + +#: libvips/foreign/rawload.c:168 libvips/iofuncs/image.c:1201 +msgid "Offset in bytes from start of file" +msgstr "Versatz in Byte vom Anfang der Datei" + +# http://de.wikipedia.org/wiki/Rohdatenformat_(Fotografie) +#: libvips/foreign/rawsave.c:138 +#, fuzzy +msgid "save image to raw" +msgstr "Bild in Rohdatenformatdatei speichern" + +# http://de.wikipedia.org/wiki/Rohdatenformat_(Fotografie) +#: libvips/foreign/rawsave.c:190 +msgid "save image to raw file" +msgstr "Bild in Rohdatenformatdatei speichern" + +#: libvips/foreign/rawsave.c:246 +#, fuzzy +msgid "write raw image to target" +msgstr "Rohdatenbild in Datei-Deskriptor schreiben" + +#: libvips/foreign/rawsave.c:308 +#, fuzzy +msgid "write raw image to buffer" +msgstr "Rohdatenbild in Datei-Deskriptor schreiben" + +#: libvips/foreign/spngload.c:252 libvips/foreign/vipspng.c:582 +#, c-format +msgid "%d text chunks, only %d text chunks will be loaded" +msgstr "" + +#: libvips/foreign/spngload.c:403 +#, fuzzy +msgid "unknown color type" +msgstr "unbekannter Kodierungstyp" + +#: libvips/foreign/spngload.c:562 +#, fuzzy +msgid "libspng read error" +msgstr "Lesefehler" + +#: libvips/foreign/spngsave.c:164 libvips/foreign/vipspng.c:1013 +#, fuzzy +msgid "bad png comment key" +msgstr "falsche Gittergeometrie" + +#: libvips/foreign/spngsave.c:680 +#, fuzzy +msgid "save spng" +msgstr "PNG speichern" + +#: libvips/foreign/spngsave.c:704 +msgid "libspng row filter flag(s)" +msgstr "" + +# http://de.wikipedia.org/wiki/Rohdatenformat_(Fotografie) +#: libvips/foreign/spngsave.c:854 +#, fuzzy +msgid "save image to file as PNG" +msgstr "Bild in Rohdatenformatdatei speichern" + +#: libvips/foreign/spngsave.c:914 +#, fuzzy +msgid "save image to buffer as PNG" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/svgload.c:626 libvips/foreign/svgload.c:644 +msgid "SVG rendering failed" +msgstr "" + +#: libvips/foreign/svgload.c:700 +msgid "load SVG with rsvg" +msgstr "" + +#: libvips/foreign/svgload.c:718 +msgid "Render at this DPI" +msgstr "" + +#: libvips/foreign/svgload.c:725 +msgid "Scale output by this factor" +msgstr "" + +#: libvips/foreign/svgload.c:733 +msgid "Allow SVG of any size" +msgstr "" + +#: libvips/foreign/svgload.c:827 +#, fuzzy +msgid "load svg from source" +msgstr "CSV aus Datei laden" + +#: libvips/foreign/tiff2vips.c:480 libvips/foreign/tiff2vips.c:498 +#, c-format +msgid "required field %d missing" +msgstr "benötigtes Feld %d fehlt" + +#: libvips/foreign/tiff2vips.c:540 +msgid "unknown resolution unit" +msgstr "unbekannte Auflösungseinheit" + +#: libvips/foreign/tiff2vips.c:680 +#, c-format +msgid "bad page number %d" +msgstr "falsche Seitennummer %d" + +#: libvips/foreign/tiff2vips.c:690 +#, fuzzy, c-format +msgid "bad number of pages %d" +msgstr "falsche Achsenanzahl %d" + +#: libvips/foreign/tiff2vips.c:718 libvips/foreign/tiff2vips.c:760 +#: libvips/iofuncs/source.c:812 +msgid "read error" +msgstr "Lesefehler" + +#: libvips/foreign/tiff2vips.c:802 +#, fuzzy, c-format +msgid "TIFF does not contain page %d" +msgstr "TIFF-Datei enthält nicht Seite %d" + +#: libvips/foreign/tiff2vips.c:812 +msgid "no SUBIFD tag" +msgstr "" + +#: libvips/foreign/tiff2vips.c:818 +#, c-format +msgid "subifd %d out of range, only 0-%d available" +msgstr "" + +#: libvips/foreign/tiff2vips.c:826 +msgid "subdirectory unreadable" +msgstr "" + +#: libvips/foreign/tiff2vips.c:867 +#, fuzzy, c-format +msgid "not %d bands" +msgstr "nicht ein Band oder %d Bänder" + +#: libvips/foreign/tiff2vips.c:880 +#, c-format +msgid "not at least %d samples per pixel" +msgstr "" + +#: libvips/foreign/tiff2vips.c:895 +msgid "samples_per_pixel not a whole number of bytes" +msgstr "" + +#: libvips/foreign/tiff2vips.c:908 +#, fuzzy, c-format +msgid "not photometric interpretation %d" +msgstr "unbekannte fotometrische Deutung %d" + +#: libvips/foreign/tiff2vips.c:920 +#, c-format +msgid "not %d bits per sample" +msgstr "" + +#: libvips/foreign/tiff2vips.c:936 +#, c-format +msgid "%d bits per sample palette image not supported" +msgstr "%d Bit pro Musterfarbpalettenbild nicht unterstützt" + +#: libvips/foreign/tiff2vips.c:995 +#, fuzzy +msgid "unsupported tiff image type\n" +msgstr "nicht unterstützter Bildtyp %d" + +#: libvips/foreign/tiff2vips.c:1603 +msgid "bad colormap" +msgstr "falsche Farbzusammenstellung" + +#: libvips/foreign/tiff2vips.c:2330 +#, c-format +msgid "decompress error tile %d x %d" +msgstr "" + +#: libvips/foreign/tiff2vips.c:2608 +#, fuzzy +msgid "tiled separate planes not supported" +msgstr "Datentyp %d nicht unterstützt" + +#: libvips/foreign/tiff2vips.c:2627 libvips/foreign/tiff2vips.c:2910 +#: libvips/foreign/tiff2vips.c:3034 +#, fuzzy +msgid "unsupported tiff image type" +msgstr "nicht unterstützter Bildtyp %d" + +#: libvips/foreign/tiff2vips.c:2761 +#, c-format +msgid "out of order read -- at line %d, but line %d requested" +msgstr "" + +#: libvips/foreign/tiff2vips.c:3070 +#, fuzzy +msgid "subsampled images not supported" +msgstr "%d-dimensionale Bilder nicht unterstützt" + +#: libvips/foreign/tiff2vips.c:3082 +msgid "not SGI-compressed LOGLUV" +msgstr "" + +#: libvips/foreign/tiff2vips.c:3099 +#, fuzzy +msgid "width/height out of range" +msgstr "Parameter außerhalb des Bereichs" + +#: libvips/foreign/tiff2vips.c:3108 +#, fuzzy +msgid "samples out of range" +msgstr "Parameter außerhalb des Bereichs" + +#: libvips/foreign/tiff2vips.c:3194 libvips/foreign/tiff2vips.c:3222 +#, fuzzy +msgid "tile size out of range" +msgstr "Parameter außerhalb des Bereichs" + +#: libvips/foreign/tiff2vips.c:3414 +#, c-format +msgid "page %d differs from page %d" +msgstr "" + +#: libvips/foreign/tiff.c:207 libvips/foreign/tiff.c:222 +#, fuzzy +msgid "unable to open source for input" +msgstr "»%s« kann nicht zur Eingabe geöffnet werden" + +#: libvips/foreign/tiff.c:330 libvips/foreign/tiff.c:345 +#, fuzzy +msgid "unable to open target for output" +msgstr "»%s« kann nicht zur Ausgabe geöffnet werden" + +#: libvips/foreign/tiffload.c:183 +#, fuzzy +msgid "load tiff" +msgstr "TIFF aus Datei laden" + +#: libvips/foreign/tiffload.c:211 +msgid "Rotate image using orientation tag" +msgstr "" + +#: libvips/foreign/tiffload.c:217 +msgid "subifd" +msgstr "" + +#: libvips/foreign/tiffload.c:218 +msgid "Subifd index" +msgstr "" + +#: libvips/foreign/tiffload.c:294 +#, fuzzy +msgid "load tiff from source" +msgstr "TIFF aus Datei laden" + +#: libvips/foreign/tiffload.c:374 +msgid "load tiff from file" +msgstr "TIFF aus Datei laden" + +#: libvips/foreign/tiffload.c:454 +#, fuzzy +msgid "load tiff from buffer" +msgstr "TIFF aus Datei laden" + +#: libvips/foreign/tiffsave.c:248 +#, fuzzy +msgid "save image as tiff" +msgstr "Bild in TIFF-Datei speichern" + +#: libvips/foreign/tiffsave.c:258 +msgid "Compression for this file" +msgstr "Komprimierung für diese Datei" + +# http://de.wikipedia.org/wiki/Abhängige_und_unabhängige_Variable +#: libvips/foreign/tiffsave.c:272 +#, fuzzy +msgid "Predictor" +msgstr "Prädiktor" + +#: libvips/foreign/tiffsave.c:273 +msgid "Compression prediction" +msgstr "Prognose der Komprimierung" + +#: libvips/foreign/tiffsave.c:280 +msgid "Tile" +msgstr "Kachel" + +#: libvips/foreign/tiffsave.c:281 +msgid "Write a tiled tiff" +msgstr "ein gekacheltes TIFF schreiben" + +#: libvips/foreign/tiffsave.c:301 +msgid "Pyramid" +msgstr "Pyramide" + +#: libvips/foreign/tiffsave.c:302 +msgid "Write a pyramidal tiff" +msgstr "ein pyramidenförmiges TIFF schreiben" + +#: libvips/foreign/tiffsave.c:308 +msgid "Miniswhite" +msgstr "" + +#: libvips/foreign/tiffsave.c:309 +msgid "Use 0 for white in 1-bit images" +msgstr "" + +#: libvips/foreign/tiffsave.c:316 +#, fuzzy +msgid "Write as a 1, 2, 4 or 8 bit image" +msgstr "ein BigTIFF-Bild schreiben" + +#: libvips/foreign/tiffsave.c:322 libvips/foreign/tiffsave.c:323 +msgid "Resolution unit" +msgstr "Einheit der Auflösung" + +# http://de.wikipedia.org/wiki/Liste_von_Dateinamenserweiterungen/T +#: libvips/foreign/tiffsave.c:343 +msgid "Bigtiff" +msgstr "BigTIFF" + +#: libvips/foreign/tiffsave.c:344 +msgid "Write a bigtiff image" +msgstr "ein BigTIFF-Bild schreiben" + +#: libvips/foreign/tiffsave.c:351 +msgid "Write a properties document to IMAGEDESCRIPTION" +msgstr "" + +#: libvips/foreign/tiffsave.c:365 +msgid "Deflate (1-9, default 6) or ZSTD (1-22, default 9) compression level" +msgstr "" + +#: libvips/foreign/tiffsave.c:372 +#, fuzzy +msgid "Enable WEBP lossless mode" +msgstr "»fd« kann nicht geschlossen werden" + +#: libvips/foreign/tiffsave.c:385 +msgid "Sub-IFD" +msgstr "" + +#: libvips/foreign/tiffsave.c:386 +msgid "Save pyr layers as sub-IFDs" +msgstr "" + +#: libvips/foreign/tiffsave.c:392 +msgid "Premultiply" +msgstr "" + +#: libvips/foreign/tiffsave.c:393 +msgid "Save with premultiplied alpha" +msgstr "" + +#: libvips/foreign/tiffsave.c:399 +msgid "RGB JPEG" +msgstr "" + +#: libvips/foreign/tiffsave.c:400 +msgid "Output RGB JPEG rather than YCbCr" +msgstr "" + +#: libvips/foreign/tiffsave.c:407 +msgid "Squash images down to 1 bit" +msgstr "Bilder auf ein Bit zusammenquetschen" + +#: libvips/foreign/tiffsave.c:470 +#, fuzzy +msgid "save image to tiff target" +msgstr "Bild in TIFF-Datei speichern" + +#: libvips/foreign/tiffsave.c:523 +msgid "save image to tiff file" +msgstr "Bild in TIFF-Datei speichern" + +#: libvips/foreign/tiffsave.c:584 +#, fuzzy +msgid "save image to tiff buffer" +msgstr "Bild in TIFF-Datei speichern" + +#: libvips/foreign/vips2jpeg.c:176 +#, c-format +msgid "%s" +msgstr "%s" + +#: libvips/foreign/vips2jpeg.c:273 +#, c-format +msgid "field \"%s\" is too large for a single JPEG marker, ignoring" +msgstr "" + +#: libvips/foreign/vips2jpeg.c:1059 +#, fuzzy +msgid "libvips built without JPEG support" +msgstr "VIPS wurde ohne FFT-Unterstützung konfiguriert" + +#: libvips/foreign/vips2magick.c:319 +#, fuzzy +msgid "unsupported image format" +msgstr "nicht unterstützter Bildtyp %d" + +#: libvips/foreign/vips2magick.c:349 +#, fuzzy +msgid "unsupported number of image bands" +msgstr "nicht unterstützter Bildtyp %d" + +#: libvips/foreign/vips2magick.c:464 +#, fuzzy +msgid "save with ImageMagick" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/vips2magick.c:490 +#, fuzzy +msgid "Quality to use" +msgstr "kann nicht gesucht werden" + +#: libvips/foreign/vips2magick.c:496 +msgid "Optimize_gif_frames" +msgstr "" + +#: libvips/foreign/vips2magick.c:497 +msgid "Apply GIF frames optimization" +msgstr "" + +#: libvips/foreign/vips2magick.c:503 +msgid "Optimize_gif_transparency" +msgstr "" + +#: libvips/foreign/vips2magick.c:504 +msgid "Apply GIF transparency optimization" +msgstr "" + +#: libvips/foreign/vips2magick.c:574 +#, fuzzy +msgid "save file with ImageMagick" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/vips2magick.c:646 +#, fuzzy +msgid "save image to magick buffer" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/vips2magick.c:677 +#, fuzzy +msgid "save bmp image with ImageMagick" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/vips2magick.c:710 +#, fuzzy +msgid "save bmp image to magick buffer" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/vips2magick.c:743 +#, fuzzy +msgid "save gif image with ImageMagick" +msgstr "Datei mit ImageMagick laden" + +#: libvips/foreign/vips2magick.c:776 +#, fuzzy +msgid "save gif image to magick buffer" +msgstr "Bild in den PNG-Puffer speichern" + +#: libvips/foreign/vips2tiff.c:1449 +msgid "can only pyramid LABQ and non-complex images" +msgstr "" +"nur LABQ und nicht-komplexe Bilder können pyramidenartig verwendet werden" + +#: libvips/foreign/vips2tiff.c:1472 +msgid "tile size not a multiple of 16" +msgstr "Bildgröße kein Vielfaches von 16" + +#: libvips/foreign/vips2tiff.c:1830 libvips/foreign/vips2tiff.c:2019 +msgid "TIFF write tile failed" +msgstr "Schreiben des TIFF-Bildes fehlgeschlagen" + +#: libvips/foreign/vipsload.c:126 +msgid "no filename associated with source" +msgstr "" + +#: libvips/foreign/vipsload.c:157 +#, fuzzy +msgid "load vips base class" +msgstr "Basisklasse" + +#: libvips/foreign/vipsload.c:228 +msgid "load vips from file" +msgstr "Vips aus einer Datei laden" + +#: libvips/foreign/vipsload.c:303 +#, fuzzy +msgid "load vips from source" +msgstr "Vips aus einer Datei laden" + +#: libvips/foreign/vipspng.c:450 +msgid "unsupported color type" +msgstr "nicht unterstützter Farbtyp" + +#: libvips/foreign/vipspng.c:564 +#, fuzzy +msgid "unable to read PNG header" +msgstr "Kopfdaten für »%s« können nicht gelesen werden" + +#: libvips/foreign/vipspng.c:756 +#, fuzzy +msgid "libpng read error" +msgstr "Lesefehler" + +#: libvips/foreign/vipspng.c:1113 +msgid "compress should be in [0,9]" +msgstr "Komprimierung sollte in [0,9] liegen" + +#: libvips/foreign/vipspng.c:1141 +#, c-format +msgid "can't save %d band image as png" +msgstr "" + +#: libvips/foreign/vipspng.c:1349 +#, fuzzy, c-format +msgid "unable to write to target %s" +msgstr "auf »%s« kann nicht geschrieben werden" + +#: libvips/foreign/vipssave.c:114 +#, fuzzy +msgid "no filename associated with target" +msgstr "dieses zugehörige Bild laden" + +#: libvips/foreign/vipssave.c:141 +#, fuzzy +msgid "save vips base class" +msgstr "Basisklasse" + +#: libvips/foreign/vipssave.c:193 +#, fuzzy +msgid "save image to file in vips format" +msgstr "Bild in Vips-Datei speichern" + +#: libvips/foreign/vipssave.c:249 +#, fuzzy +msgid "save image to target in vips format" +msgstr "Bild in Vips-Datei speichern" + +#: libvips/foreign/webp2vips.c:407 +#, fuzzy +msgid "unable to parse image" +msgstr "es kann nicht zu einem %s-Bild ausgegeben werden" + +#: libvips/foreign/webp2vips.c:595 +#, fuzzy +msgid "unable to loop through frames" +msgstr "es kann nicht zu einem %s-Bild ausgegeben werden" + +#: libvips/foreign/webpload.c:164 +#, fuzzy +msgid "load webp" +msgstr "JPEG laden" + +# Portable Pixmap +#: libvips/foreign/webpload.c:258 +#, fuzzy +msgid "load webp from source" +msgstr "PPM aus Datei laden" + +# Portable Pixmap +#: libvips/foreign/webpload.c:338 +#, fuzzy +msgid "load webp from file" +msgstr "PPM aus Datei laden" + +#: libvips/foreign/webpload.c:418 +#, fuzzy +msgid "load webp from buffer" +msgstr "JPEG aus Puffer laden" + +#: libvips/foreign/webpsave.c:248 +#, fuzzy +msgid "picture version error" +msgstr "Version ausgeben" + +#: libvips/foreign/webpsave.c:290 +msgid "picture memory error" +msgstr "" + +#: libvips/foreign/webpsave.c:315 +#, fuzzy +msgid "anim add error" +msgstr "Lesefehler" + +#: libvips/foreign/webpsave.c:332 +#, fuzzy +msgid "unable to encode" +msgstr "kann nicht gesucht werden" + +#: libvips/foreign/webpsave.c:428 +#, fuzzy +msgid "chunk add error" +msgstr "Lesefehler" + +#: libvips/foreign/webpsave.c:534 libvips/foreign/webpsave.c:575 +#, fuzzy +msgid "mux error" +msgstr "Unix-Fehler" + +#: libvips/foreign/webpsave.c:595 libvips/foreign/webpsave.c:605 +#: libvips/foreign/webpsave.c:644 +#, fuzzy +msgid "config version error" +msgstr "Umwandlungstransaktionen" + +#: libvips/foreign/webpsave.c:625 +msgid "invalid configuration" +msgstr "" + +#: libvips/foreign/webpsave.c:655 +#, fuzzy +msgid "unable to init animation" +msgstr "kann nicht gekürzt werden" + +#: libvips/foreign/webpsave.c:698 +#, fuzzy +msgid "anim close error" +msgstr "XML-Fehler beim Speichern" + +#: libvips/foreign/webpsave.c:703 +#, fuzzy +msgid "anim build error" +msgstr "Lesefehler" + +#: libvips/foreign/webpsave.c:711 libvips/mosaicing/lrmerge.c:309 +#: libvips/mosaicing/tbmerge.c:187 libvips/mosaicing/tbmerge.c:262 +#: libvips/mosaicing/tbmerge.c:594 +msgid "internal error" +msgstr "interner Fehler" + +#: libvips/foreign/webpsave.c:817 +#, fuzzy +msgid "save as WebP" +msgstr "Bild als ASCII speichern" + +#: libvips/foreign/webpsave.c:840 +msgid "Preset" +msgstr "" + +#: libvips/foreign/webpsave.c:841 +msgid "Preset for lossy compression" +msgstr "" + +#: libvips/foreign/webpsave.c:848 +msgid "Smart subsampling" +msgstr "" + +#: libvips/foreign/webpsave.c:849 +msgid "Enable high quality chroma subsampling" +msgstr "" + +#: libvips/foreign/webpsave.c:855 +msgid "Near lossless" +msgstr "" + +#: libvips/foreign/webpsave.c:856 +msgid "Enable preprocessing in lossless mode (uses Q)" +msgstr "" + +#: libvips/foreign/webpsave.c:862 +msgid "Alpha quality" +msgstr "" + +#: libvips/foreign/webpsave.c:863 +msgid "Change alpha plane fidelity for lossy compression" +msgstr "" + +#: libvips/foreign/webpsave.c:869 +msgid "Minimise size" +msgstr "" + +#: libvips/foreign/webpsave.c:870 +msgid "Optimise for minimum size" +msgstr "" + +#: libvips/foreign/webpsave.c:876 +msgid "Minimum keyframe spacing" +msgstr "" + +#: libvips/foreign/webpsave.c:877 +#, fuzzy +msgid "Minimum number of frames between key frames" +msgstr "maximale Anzahl von Kacheln, die zwischengespeichert werden soll" + +#: libvips/foreign/webpsave.c:883 +msgid "Maximum keyframe spacing" +msgstr "" + +#: libvips/foreign/webpsave.c:884 +#, fuzzy +msgid "Maximum number of frames between key frames" +msgstr "maximale Anzahl von Kacheln, die zwischengespeichert werden soll" + +#: libvips/foreign/webpsave.c:891 libvips/foreign/webpsave.c:912 +msgid "Level of CPU effort to reduce file size" +msgstr "" + +#: libvips/foreign/webpsave.c:897 +#, fuzzy +msgid "Target size" +msgstr "falsche Bildgröße" + +#: libvips/foreign/webpsave.c:898 +msgid "Desired target size in bytes" +msgstr "" + +#: libvips/foreign/webpsave.c:904 +msgid "Passes" +msgstr "" + +#: libvips/foreign/webpsave.c:905 +msgid "Number of entropy-analysis passes (in [1..10])" +msgstr "" + +#: libvips/foreign/webpsave.c:911 +msgid "Reduction effort" +msgstr "" + +#: libvips/foreign/webpsave.c:918 +#, fuzzy +msgid "Mixed encoding" +msgstr "Bildpunktkodierung" + +#: libvips/foreign/webpsave.c:919 +msgid "Allow mixed encoding (might reduce file size)" +msgstr "" + +#: libvips/foreign/webpsave.c:925 +msgid "Smart deblocking" +msgstr "" + +#: libvips/foreign/webpsave.c:926 +msgid "Enable auto-adjusting of the deblocking filter" +msgstr "" + +# http://de.wikipedia.org/wiki/MIME#image +#: libvips/foreign/webpsave.c:1156 +#, fuzzy +msgid "save image to webp mime" +msgstr "Bild in JPEG-MIME speichern" + +#: libvips/freqfilt/freqfilt.c:94 +#, fuzzy +msgid "frequency-domain filter operations" +msgstr "unäre Transaktionen" + +#: libvips/freqfilt/freqmult.c:126 +msgid "frequency-domain filtering" +msgstr "" + +#: libvips/freqfilt/freqmult.c:131 +#, fuzzy +msgid "Input mask image" +msgstr "Eingabebild" + +#: libvips/freqfilt/fwfft.c:145 libvips/freqfilt/fwfft.c:266 +#: libvips/freqfilt/invfft.c:124 libvips/freqfilt/invfft.c:203 +msgid "unable to create transform plan" +msgstr "Umwandlungsplan kann nicht erstellt werden" + +#: libvips/freqfilt/fwfft.c:351 +msgid "forward FFT" +msgstr "" + +#: libvips/freqfilt/invfft.c:263 +msgid "inverse FFT" +msgstr "" + +#: libvips/freqfilt/invfft.c:267 +msgid "Real" +msgstr "" + +#: libvips/freqfilt/invfft.c:268 +msgid "Output only the real part of the transform" +msgstr "" + +#: libvips/freqfilt/phasecor.c:107 +msgid "calculate phase correlation" +msgstr "" + +#: libvips/freqfilt/spectrum.c:100 +msgid "make displayable power spectrum" +msgstr "" + +#: libvips/histogram/case.c:164 +#, fuzzy +msgid "bad number of cases" +msgstr "falsche Achsenanzahl %d" + +#: libvips/histogram/case.c:169 +#, fuzzy +msgid "index image not 1-band" +msgstr "»ink«-Bild nicht 1x1 Bildpunkte" + +#: libvips/histogram/case.c:233 +msgid "use pixel values to pick cases from an array of images" +msgstr "" + +#: libvips/histogram/case.c:245 +msgid "Cases" +msgstr "" + +#: libvips/histogram/case.c:246 +#, fuzzy +msgid "Array of case images" +msgstr "Feld von Eingabebildern" + +#: libvips/histogram/hist_cum.c:158 +msgid "form cumulative histogram" +msgstr "" + +#: libvips/histogram/hist_entropy.c:107 +msgid "estimate image entropy" +msgstr "" + +#: libvips/histogram/hist_entropy.c:112 +#: libvips/histogram/hist_ismonotonic.c:119 +#, fuzzy +msgid "Input histogram image" +msgstr "Eingabebild" + +#: libvips/histogram/hist_equal.c:110 +msgid "histogram equalisation" +msgstr "" + +#: libvips/histogram/hist_equal.c:127 +msgid "Equalise with this band" +msgstr "" + +#: libvips/histogram/hist_ismonotonic.c:114 +msgid "test for monotonicity" +msgstr "" + +#: libvips/histogram/hist_ismonotonic.c:124 +msgid "Monotonic" +msgstr "" + +#: libvips/histogram/hist_ismonotonic.c:125 +msgid "true if in is monotonic" +msgstr "" + +#: libvips/histogram/hist_local.c:304 libvips/histogram/stdif.c:236 +#: libvips/morphology/rank.c:491 +msgid "window too large" +msgstr "Fenster zu groß" + +#: libvips/histogram/hist_local.c:355 +msgid "local histogram equalisation" +msgstr "" + +#: libvips/histogram/hist_local.c:374 libvips/histogram/stdif.c:309 +#: libvips/morphology/rank.c:571 +#, fuzzy +msgid "Window width in pixels" +msgstr "Kachelbreite in Bildpunkten" + +#: libvips/histogram/hist_local.c:381 libvips/histogram/stdif.c:316 +#: libvips/morphology/rank.c:578 +#, fuzzy +msgid "Window height in pixels" +msgstr "Kachelhöhe in Bildpunkten" + +#: libvips/histogram/hist_local.c:387 +#, fuzzy +msgid "Max slope" +msgstr "Kacheln maximal" + +#: libvips/histogram/hist_local.c:388 +msgid "Maximum slope (CLAHE)" +msgstr "" + +#: libvips/histogram/hist_match.c:154 +msgid "match two histograms" +msgstr "" + +#: libvips/histogram/hist_match.c:162 +#, fuzzy +msgid "Input histogram" +msgstr "Eingabebild" + +#: libvips/histogram/hist_match.c:167 libvips/mosaicing/match.c:196 +#: libvips/mosaicing/merge.c:122 libvips/mosaicing/mosaic1.c:498 +#: libvips/mosaicing/mosaic.c:179 +msgid "Reference" +msgstr "" + +#: libvips/histogram/hist_match.c:168 +msgid "Reference histogram" +msgstr "" + +#: libvips/histogram/hist_norm.c:137 +msgid "normalise histogram" +msgstr "" + +#: libvips/histogram/histogram.c:223 +#, fuzzy +msgid "histogram operations" +msgstr "binäre Transaktionen" + +#: libvips/histogram/hist_plot.c:329 +msgid "plot histogram" +msgstr "" + +#: libvips/histogram/hist_unary.c:84 +#, fuzzy +msgid "hist_unary operations" +msgstr "unäre Transaktionen" + +#: libvips/histogram/maplut.c:110 +#, c-format +msgid "%d overflows detected" +msgstr "%d Überläufe entdeckt" + +#: libvips/histogram/maplut.c:738 +msgid "map an image though a lut" +msgstr "" + +#: libvips/histogram/maplut.c:756 +msgid "LUT" +msgstr "" + +#: libvips/histogram/maplut.c:757 +#, fuzzy +msgid "Look-up table image" +msgstr "ein Bild kopieren" + +#: libvips/histogram/maplut.c:763 +msgid "Apply one-band lut to this band of in" +msgstr "" + +#: libvips/histogram/percent.c:105 +msgid "find threshold for percent of pixels" +msgstr "" + +#: libvips/histogram/percent.c:115 +msgid "Percent" +msgstr "" + +#: libvips/histogram/percent.c:116 +#, fuzzy +msgid "Percent of pixels" +msgstr "Einheitsvektor von Bildpunkten" + +#: libvips/histogram/percent.c:123 +msgid "Threshold above which lie percent of pixels" +msgstr "" + +#: libvips/histogram/stdif.c:240 +#, fuzzy +msgid "too many bands" +msgstr "zu viele Argumente" + +#: libvips/histogram/stdif.c:290 +msgid "statistical difference" +msgstr "" + +#: libvips/histogram/stdif.c:322 +#, fuzzy +msgid "Mean weight" +msgstr "Kachelhöhe" + +#: libvips/histogram/stdif.c:323 +#, fuzzy +msgid "Weight of new mean" +msgstr "Höhe des extrahierten Bereichs" + +#: libvips/histogram/stdif.c:330 +msgid "New mean" +msgstr "" + +#: libvips/histogram/stdif.c:336 +msgid "Deviation weight" +msgstr "" + +#: libvips/histogram/stdif.c:337 +msgid "Weight of new deviation" +msgstr "" + +#: libvips/histogram/stdif.c:343 +#, fuzzy +msgid "Deviation" +msgstr "Beschreibung" + +#: libvips/histogram/stdif.c:344 +msgid "New deviation" +msgstr "" + +#: libvips/iofuncs/buf.c:609 +#, c-format +msgid "%zd bytes of binary data" +msgstr "" + +#: libvips/iofuncs/connection.c:126 +#, fuzzy +msgid "Descriptor" +msgstr "Beschreibung" + +#: libvips/iofuncs/connection.c:127 +#, fuzzy +msgid "File descriptor for read or write" +msgstr "Datei-Deskriptor, in den geschrieben werden soll" + +#: libvips/iofuncs/connection.c:134 +#, fuzzy +msgid "Name of file to open" +msgstr "falscher Dateityp" + +#: libvips/iofuncs/error.c:296 +#, fuzzy +msgid "system error" +msgstr "Lesefehler" + +#: libvips/iofuncs/error.c:443 +msgid "image must be uncoded" +msgstr "Bild muss unkodiert sein" + +#: libvips/iofuncs/error.c:471 +#, fuzzy +msgid "image coding must be 'none' or 'labq'" +msgstr "Bildkodierung muss NONE oder LABQ sein" + +#: libvips/iofuncs/error.c:499 +msgid "unknown image coding" +msgstr "unbekannte Bildkodierung" + +#: libvips/iofuncs/error.c:524 +#, fuzzy, c-format +msgid "coding '%s' only" +msgstr "Nur LABQ-Kodierung" + +#: libvips/iofuncs/error.c:549 +msgid "image must one band" +msgstr "Bild muss ein Band haben" + +#: libvips/iofuncs/error.c:574 +#, c-format +msgid "image must have %d bands" +msgstr "Bild muss %d Bänder haben" + +#: libvips/iofuncs/error.c:599 +msgid "image must have one or three bands" +msgstr "Bild muss ein oder drei Bänder haben" + +#: libvips/iofuncs/error.c:625 +#, fuzzy, c-format +msgid "image must have at least %d bands" +msgstr "Bild muss %d Bänder haben" + +#: libvips/iofuncs/error.c:653 +msgid "images must have the same number of bands, or one must be single-band" +msgstr "" +"Bilder müssen die gleiche Anzahl Bänder haben oder eines muss ein Band haben" + +#: libvips/iofuncs/error.c:680 +#, c-format +msgid "image must have 1 or %d bands" +msgstr "Bild muss ein oder %d Bänder haben" + +#: libvips/iofuncs/error.c:704 +msgid "image must be non-complex" +msgstr "Bild muss nicht-komplex sein" + +#: libvips/iofuncs/error.c:728 +msgid "image must be complex" +msgstr "Bild muss komplex sein" + +#: libvips/iofuncs/error.c:755 +#, fuzzy +msgid "image must be two-band or complex" +msgstr "Bild muss nicht-komplex sein" + +#: libvips/iofuncs/error.c:781 +#, c-format +msgid "image must be %s" +msgstr "Bild muss %s sein" + +#: libvips/iofuncs/error.c:806 +msgid "image must be integer" +msgstr "Bild muss ganzzahlig sein" + +#: libvips/iofuncs/error.c:831 +msgid "image must be unsigned integer" +msgstr "Bild muss aus vorzeichenlosen Ganzzahlen bestehen" + +#: libvips/iofuncs/error.c:859 +msgid "image must be 8- or 16-bit integer, signed or unsigned" +msgstr "" +"Bild muss aus 8- oder 16-Bit Ganzzahlen mit oder ohne Vorzeichen bestehen" + +#: libvips/iofuncs/error.c:885 +msgid "image must be 8- or 16-bit unsigned integer" +msgstr "Bild muss aus 8- oder 16-Bit vorzeichenlosen Ganzzahlen bestehen" + +#: libvips/iofuncs/error.c:911 +msgid "image must be 8- or 16-bit unsigned integer, or float" +msgstr "" +"Bild muss aus 8- oder 16-Bit vorzeichenlosen Ganzzahlen oder " +"Fließkommazahlen bestehen" + +#: libvips/iofuncs/error.c:938 +msgid "image must be unsigned int or float" +msgstr "" +"Bild muss aus 8- oder 16-Bit vorzeichenlosen Ganz- oder Fließkommazahlen " +"bestehen" + +#: libvips/iofuncs/error.c:964 +msgid "images must match in size" +msgstr "Bilder müssen in der Größe passen" + +#: libvips/iofuncs/error.c:990 +#, fuzzy +msgid "images must be odd and square" +msgstr "Bild muss %d Bänder haben" + +#: libvips/iofuncs/error.c:1016 +msgid "images must have the same number of bands" +msgstr "Bilder müssen die gleiche Anzahl Bänder haben" + +#: libvips/iofuncs/error.c:1070 +msgid "images must have the same band format" +msgstr "Bilder müssen das gleiche Bandformat haben" + +#: libvips/iofuncs/error.c:1096 +msgid "images must have the same coding" +msgstr "Bilder müssen die gleiche Kodierung haben" + +#: libvips/iofuncs/error.c:1119 +#, fuzzy, c-format +msgid "vector must have %d elements" +msgstr "Vektor muss 1 oder %d Elemente haben" + +#: libvips/iofuncs/error.c:1155 +#, fuzzy +msgid "vector must have 1 element" +msgstr "Vektor muss 1 oder %d Elemente haben" + +#: libvips/iofuncs/error.c:1158 +#, c-format +msgid "vector must have 1 or %d elements" +msgstr "Vektor muss 1 oder %d Elemente haben" + +#: libvips/iofuncs/error.c:1183 +msgid "histograms must have width or height 1" +msgstr "Histogramme müssen eine Breite oder Höhe von eins haben" + +#: libvips/iofuncs/error.c:1188 +msgid "histograms must have not have more than 65536 elements" +msgstr "Histogramm dürfen nicht mehr als 65536 Elemente haben" + +#: libvips/iofuncs/error.c:1224 +#, fuzzy +msgid "matrix image too large" +msgstr "Zoomfaktoren zu groß" + +#: libvips/iofuncs/error.c:1229 +#, fuzzy +msgid "matrix image must have one band" +msgstr "Bild muss %d Bänder haben" + +#: libvips/iofuncs/error.c:1263 +#, fuzzy +msgid "separable matrix images must have width or height 1" +msgstr "Histogramme müssen eine Breite oder Höhe von eins haben" + +#: libvips/iofuncs/error.c:1289 +#, fuzzy +msgid "precision must be int or float" +msgstr "" +"Bild muss aus 8- oder 16-Bit vorzeichenlosen Ganz- oder Fließkommazahlen " +"bestehen" + +#: libvips/iofuncs/generate.c:696 +msgid "demand hint not set" +msgstr "Hinweisanfrage nicht gesetzt" + +#: libvips/iofuncs/generate.c:715 libvips/iofuncs/generate.c:743 +msgid "generate() called twice" +msgstr "generate() zweimal aufgerufen" + +#: libvips/iofuncs/generate.c:784 libvips/iofuncs/image.c:3235 +#, c-format +msgid "unable to output to a %s image" +msgstr "es kann nicht zu einem %s-Bild ausgegeben werden" + +#: libvips/iofuncs/ginputsource.c:164 libvips/iofuncs/ginputsource.c:229 +#, c-format +msgid "Error while seeking: %s" +msgstr "" + +#: libvips/iofuncs/ginputsource.c:185 +msgid "Cannot truncate VipsGInputStream" +msgstr "" + +#: libvips/iofuncs/ginputsource.c:206 +#, fuzzy, c-format +msgid "Error while reading: %s" +msgstr "Fehler beim Lesen von XML: %s" + +#: libvips/iofuncs/ginputsource.c:275 +msgid "Stream to wrap" +msgstr "" + +#: libvips/iofuncs/header.c:1380 +#, c-format +msgid "field \"%s\" not found" +msgstr "Feld »%s« nicht gefunden" + +#: libvips/iofuncs/header.c:1614 +#, c-format +msgid "field \"%s\" is of type %s, not %s" +msgstr "Feld »%s« ist vom Typ %s, nicht %s" + +#: libvips/iofuncs/header.c:1888 +#, fuzzy, c-format +msgid "field \"%s\" is of type %s, not VipsRefString" +msgstr "Feld »%s« ist vom Typ %s, nicht %s" + +#: libvips/iofuncs/image.c:539 +msgid "unable to close fd" +msgstr "»fd« kann nicht geschlossen werden" + +#: libvips/iofuncs/image.c:762 +#, fuzzy, c-format +msgid "%s %s: %d x %d pixels, %d threads, %d x %d tiles, %d lines in buffer" +msgstr "%s %s: %d Threads, %d x %d Kacheln, Gruppen von %d Scan-Zeilen" + +#: libvips/iofuncs/image.c:775 +#, c-format +msgid "%s %s: %d%% complete" +msgstr "%s %s: %d%% komplett" + +#: libvips/iofuncs/image.c:794 +#, fuzzy, c-format +msgid "%s %s: done in %.3gs \n" +msgstr "%s %s: Erledigt in %ds \n" + +#: libvips/iofuncs/image.c:976 +#, c-format +msgid "unable to open \"%s\", file too short" +msgstr "»%s« kann nicht geöffnet werden, Datei zu klein" + +#: libvips/iofuncs/image.c:985 +#, c-format +msgid "%s is longer than expected" +msgstr "%s ist länger als erwartet" + +#: libvips/iofuncs/image.c:1003 +#, c-format +msgid "bad mode \"%s\"" +msgstr "falscher Modus »%s«" + +#: libvips/iofuncs/image.c:1075 +msgid "image class" +msgstr "Bildklasse" + +#: libvips/iofuncs/image.c:1173 +msgid "Image filename" +msgstr "Bilddateiname" + +#: libvips/iofuncs/image.c:1180 +msgid "Open mode" +msgstr "Öffnen-Modus" + +#: libvips/iofuncs/image.c:1186 +msgid "Kill" +msgstr "töten" + +#: libvips/iofuncs/image.c:1187 +msgid "Block evaluation on this image" +msgstr "Blockauswertung dieses Bildes" + +#: libvips/iofuncs/image.c:1193 +msgid "Demand style" +msgstr "Nachfragestil" + +#: libvips/iofuncs/image.c:1194 +msgid "Preferred demand style for this image" +msgstr "für dieses Bild bevorzugter Nachfragestil" + +#: libvips/iofuncs/image.c:1207 +msgid "Foreign buffer" +msgstr "Fremdpuffer" + +#: libvips/iofuncs/image.c:1208 +msgid "Pointer to foreign pixels" +msgstr "Puffer für fremde Bildpunkte" + +#: libvips/iofuncs/image.c:1660 +#, c-format +msgid "killed for image \"%s\"" +msgstr "für Bild »%s« abgeschossen" + +#: libvips/iofuncs/image.c:2069 +msgid "memory area too small --- should be %" +msgstr "" + +#: libvips/iofuncs/image.c:2258 +#, fuzzy +msgid "unable to load source" +msgstr "Verlauf kann nicht gelesen werden" + +#: libvips/iofuncs/image.c:2369 +#, c-format +msgid "bad array length --- should be %d, you passed %d" +msgstr "" + +#: libvips/iofuncs/image.c:2886 libvips/iofuncs/image.c:2888 +#: libvips/iofuncs/memory.c:336 libvips/iofuncs/memory.c:338 +#: libvips/iofuncs/memory.c:409 libvips/iofuncs/memory.c:411 +#, c-format +msgid "out of memory --- size == %dMB" +msgstr "Hauptspeicher reicht nicht aus – Größe == %dMB" + +#: libvips/iofuncs/image.c:3179 +msgid "bad image descriptor" +msgstr "falscher Bild-Deskriptor" + +#: libvips/iofuncs/image.c:3298 +#, c-format +msgid "auto-rewind for %s failed" +msgstr "automatischer Rücklauf für %s fehlgeschlagen" + +#: libvips/iofuncs/image.c:3372 libvips/iofuncs/image.c:3502 +#: libvips/iofuncs/image.c:3679 +msgid "image not readable" +msgstr "Bild nicht lesbar" + +#: libvips/iofuncs/image.c:3417 libvips/iofuncs/image.c:3643 +msgid "no image data" +msgstr "keine Bilddaten" + +#: libvips/iofuncs/image.c:3523 libvips/iofuncs/image.c:3709 +#: libvips/iofuncs/image.c:3718 +msgid "image already written" +msgstr "Bild bereits geschrieben" + +#: libvips/iofuncs/image.c:3547 libvips/iofuncs/image.c:3730 +msgid "image not writeable" +msgstr "Bild nicht schreibbar" + +#: libvips/iofuncs/image.c:3602 +msgid "bad file type" +msgstr "falscher Dateityp" + +#: libvips/iofuncs/init.c:316 tools/vips.c:772 +#, fuzzy, c-format +msgid "unable to load \"%s\" -- %s" +msgstr "»mmap« nicht möglich: \"%s\" - %s" + +#: libvips/iofuncs/init.c:1270 +#, fuzzy +msgid "flag not in [0, 5]" +msgstr "Schalter nicht -1 oder 1" + +#: libvips/iofuncs/mapfile.c:189 libvips/iofuncs/mapfile.c:355 +msgid "unable to CreateFileMapping" +msgstr "»CreateFileMapping« nicht möglich" + +#: libvips/iofuncs/mapfile.c:196 libvips/iofuncs/mapfile.c:367 +msgid "unable to MapViewOfFile" +msgstr "»MapViewOfFile« nicht möglich" + +#: libvips/iofuncs/mapfile.c:235 +msgid "unable to mmap" +msgstr "»mmap« nicht möglich" + +#: libvips/iofuncs/mapfile.c:250 libvips/iofuncs/mapfile.c:361 +msgid "unable to UnmapViewOfFile" +msgstr "»UnmapViewOfFile« nicht möglich" + +#: libvips/iofuncs/mapfile.c:256 +msgid "unable to munmap file" +msgstr "»munmap« der Datei nicht möglich" + +#: libvips/iofuncs/mapfile.c:278 +msgid "file is less than 64 bytes" +msgstr "Datei ist weniger als 64 Byte groß" + +#: libvips/iofuncs/mapfile.c:283 libvips/iofuncs/mapfile.c:317 +msgid "unable to get file status" +msgstr "Dateistatus kann nicht abgefragt werden" + +#: libvips/iofuncs/mapfile.c:289 +msgid "not a regular file" +msgstr "keine reguläre Datei" + +#: libvips/iofuncs/mapfile.c:323 +msgid "unable to read data" +msgstr "Daten können nicht gelesen werden" + +#: libvips/iofuncs/mapfile.c:387 +#, c-format +msgid "unable to mmap: \"%s\" - %s" +msgstr "»mmap« nicht möglich: \"%s\" - %s" + +#: libvips/iofuncs/mapfile.c:398 +#, c-format +msgid "unable to mmap \"%s\" to same address" +msgstr "»mmap %s« zur gleichen Adresse nicht möglich" + +#: libvips/iofuncs/object.c:346 +#, c-format +msgid "parameter %s not set" +msgstr "Parameter %s nicht gesetzt" + +#: libvips/iofuncs/object.c:781 +#, c-format +msgid "no property named `%s'" +msgstr "keine Eigenschaft namens »%s«" + +#: libvips/iofuncs/object.c:787 +#, c-format +msgid "no vips argument named `%s'" +msgstr "kein VIPS-Argument namens »%s«" -#: libvips/foreign/openslideload.c:190 -msgid "Associated" -msgstr "dazugehörig" +#: libvips/iofuncs/object.c:793 +#, c-format +msgid "argument `%s' has no instance" +msgstr "Argument »%s« hat keine Instanz" -#: libvips/foreign/openslideload.c:191 -msgid "Load this associated image" -msgstr "dieses zugehörige Bild laden" +#: libvips/iofuncs/object.c:1533 libvips/iofuncs/operation.c:749 +#: libvips/resample/interpolate.c:659 +#, c-format +msgid "class \"%s\" not found" +msgstr "Klasse »%s« nicht gefunden" -#: libvips/foreign/tiffload.c:130 -msgid "load tiff from file" -msgstr "TIFF aus Datei laden" +#: libvips/iofuncs/object.c:1584 +msgid "base class" +msgstr "Basisklasse" -#: libvips/foreign/tiffload.c:149 -msgid "Page" -msgstr "Seite" +#: libvips/iofuncs/object.c:1598 +msgid "Nickname" +msgstr "Nickname" -#: libvips/foreign/tiffload.c:150 -msgid "Load this page from the file" -msgstr "diese Seite aus der Datei laden" +#: libvips/iofuncs/object.c:1599 +msgid "Class nickname" +msgstr "Klassen-Nickname" -#: libvips/foreign/fitsload.c:107 -msgid "load a FITS image" -msgstr "ein FITS-Bild laden" +#: libvips/iofuncs/object.c:1605 +msgid "Description" +msgstr "Beschreibung" -#: libvips/foreign/vipssave.c:114 -msgid "save image to vips file" -msgstr "Bild in Vips-Datei speichern" +#: libvips/iofuncs/object.c:1606 +msgid "Class description" +msgstr "Klassenbeschreibung" -#: libvips/foreign/radsave.c:108 -msgid "save image to Radiance file" -msgstr "Bild in Radiance-Datei speichern" +#: libvips/iofuncs/object.c:1844 +#, c-format +msgid "no value supplied for argument '%s'" +msgstr "" -#: libvips/foreign/openexrload.c:125 -msgid "load an OpenEXR image" -msgstr "ein OpenEXR-Bild laden" +#: libvips/iofuncs/object.c:1847 +#, c-format +msgid "no value supplied for argument '%s' ('%s')" +msgstr "" -#: libvips/foreign/analyzeload.c:114 -msgid "load an Analyze6 image" -msgstr "ein Analyze6-Bild laden" +#: libvips/iofuncs/object.c:2039 libvips/iofuncs/object.c:2058 +#, fuzzy, c-format +msgid "'%s' is not an integer" +msgstr "»%s« ist keine positive Ganzzahl" -#: libvips/foreign/pngload.c:124 -msgid "load png from file" -msgstr "PNG-Datei aus Datei laden" +#: libvips/iofuncs/object.c:2481 +#, fuzzy, c-format +msgid "expected string or ), saw %s" +msgstr "%s erwartet, %s gesehen" -#: libvips/foreign/tiffsave.c:159 -msgid "save image to tiff file" -msgstr "Bild in TIFF-Datei speichern" +#: libvips/iofuncs/object.c:2524 +#, c-format +msgid "unable to set '%s'" +msgstr "»%s« kann nicht gesetzt werden" -#: libvips/foreign/tiffsave.c:176 libvips/foreign/pngsave.c:103 -msgid "Compression" -msgstr "Komprimierung" +#: libvips/iofuncs/object.c:2537 +msgid "not , or ) after parameter" +msgstr "kein »,« oder »)« nach Parameter" -#: libvips/foreign/tiffsave.c:177 -msgid "Compression for this file" -msgstr "Komprimierung für diese Datei" +#: libvips/iofuncs/object.c:2544 +msgid "extra tokens after ')'" +msgstr "keine zusätzlichen Token nach »)«" -#: libvips/foreign/tiffsave.c:184 libvips/foreign/jpegsave.c:124 -msgid "Q" -msgstr "Q" +#: libvips/iofuncs/operation.c:235 +#, c-format +msgid "%d pixels calculated" +msgstr "" -#: libvips/foreign/tiffsave.c:185 libvips/foreign/jpegsave.c:125 -msgid "Q factor" -msgstr "Q-Faktor" +#: libvips/iofuncs/operation.c:343 +msgid "default enum" +msgstr "" -#: libvips/foreign/tiffsave.c:191 -# http://de.wikipedia.org/wiki/Abhängige_und_unabhängige_Variable -msgid "predictor" -msgstr "Prädiktor" +#: libvips/iofuncs/operation.c:347 +msgid "allowed enums" +msgstr "" -#: libvips/foreign/tiffsave.c:192 -msgid "Compression prediction" -msgstr "Prognose der Komprimierung" +#: libvips/iofuncs/operation.c:375 +msgid "default flags" +msgstr "" -#: libvips/foreign/tiffsave.c:199 libvips/foreign/jpegsave.c:131 -msgid "profile" -msgstr "Profil" +#: libvips/iofuncs/operation.c:380 +msgid "allowed flags" +msgstr "" -#: libvips/foreign/tiffsave.c:200 libvips/foreign/jpegsave.c:132 -msgid "ICC profile to embed" -msgstr "einzubettendes ICC-Profil" +#: libvips/iofuncs/operation.c:396 libvips/iofuncs/operation.c:404 +#: libvips/iofuncs/operation.c:416 +msgid "default" +msgstr "" -#: libvips/foreign/tiffsave.c:206 -msgid "Tile" -msgstr "Kachel" +#: libvips/iofuncs/operation.c:407 libvips/iofuncs/operation.c:419 +#, fuzzy +msgid "min" +msgstr "in" -#: libvips/foreign/tiffsave.c:207 -msgid "Write a tiled tiff" -msgstr "ein gekacheltes TIFF schreiben" +#: libvips/iofuncs/operation.c:409 libvips/iofuncs/operation.c:421 +msgid "max" +msgstr "" -#: libvips/foreign/tiffsave.c:227 -msgid "Pyramid" -msgstr "Pyramide" +#: libvips/iofuncs/operation.c:618 +#, fuzzy +msgid "operation is blocked" +msgstr "Transaktionen" -#: libvips/foreign/tiffsave.c:228 -msgid "Write a pyramidal tiff" -msgstr "ein pyramidenförmiges TIFF schreiben" +#: libvips/iofuncs/operation.c:664 +msgid "operations" +msgstr "Transaktionen" -#: libvips/foreign/tiffsave.c:234 -msgid "Squash" -msgstr "quetschen" +#: libvips/iofuncs/operation.c:755 +#, fuzzy, c-format +msgid "\"%s\" is not an instantiable class" +msgstr "»%s« ist kein bekanntes Dateiformat" -#: libvips/foreign/tiffsave.c:235 -msgid "Squash images down to 1 bit" -msgstr "Bilder auf ein Bit zusammenquetschen" +#: libvips/iofuncs/operation.c:1225 +#, c-format +msgid "unknown argument '%s'" +msgstr "unbekanntes Argument »%s«" -#: libvips/foreign/tiffsave.c:241 libvips/foreign/tiffsave.c:242 -msgid "Resolution unit" -msgstr "Einheit der Auflösung" +#: libvips/iofuncs/operation.c:1350 +msgid "too few arguments" +msgstr "zu wenige Argumente" -#: libvips/foreign/tiffsave.c:263 -# http://de.wikipedia.org/wiki/Liste_von_Dateinamenserweiterungen/T -msgid "Bigtiff" -msgstr "BigTIFF" +#: libvips/iofuncs/operation.c:1469 +msgid "too many arguments" +msgstr "zu viele Argumente" -#: libvips/foreign/tiffsave.c:264 -msgid "Write a bigtiff image" -msgstr "ein BigTIFF-Bild schreiben" +#: libvips/iofuncs/region.c:565 libvips/iofuncs/region.c:635 +#: libvips/iofuncs/region.c:777 libvips/iofuncs/region.c:1848 +msgid "valid clipped to nothing" +msgstr "gültig an nichts angeklammert" -#: libvips/foreign/csv.c:183 -#, c-format -msgid "error parsing number, line %d, column %d" -msgstr "Fehler beim Auswerten von Nummer, Zeile %d, Spalte %d" +#: libvips/iofuncs/region.c:675 +msgid "bad image type" +msgstr "falscher Bildtyp" -#: libvips/foreign/csv.c:237 -msgid "end of file while skipping start" -msgstr "Dateiende während des Überspringens des Startes" +#: libvips/iofuncs/region.c:719 +msgid "no pixel data on attached image" +msgstr "keine Bildpunktdaten in angehängtem Bild" -#: libvips/foreign/csv.c:246 libvips/iofuncs/util.c:1072 -#: libvips/iofuncs/util.c:1078 -msgid "unable to seek" -msgstr "kann nicht gesucht werden" +#: libvips/iofuncs/region.c:725 +msgid "images do not match in pixel size" +msgstr "Bilder passen in der Bildpunktgröße nicht zusammen" -#: libvips/foreign/csv.c:257 -msgid "empty line" -msgstr "leere Zeile" +#: libvips/iofuncs/region.c:758 libvips/iofuncs/region.c:1830 +msgid "dest too small" +msgstr "Ziel zu klein" -#: libvips/foreign/csv.c:301 -#, c-format -msgid "unexpected EOF, line %d col %d" -msgstr "unerwartetes Dateiende, Zeile %d, Spalte %d" +#: libvips/iofuncs/region.c:847 +msgid "bad position" +msgstr "falsche Position" + +#: libvips/iofuncs/region.c:1628 +#, fuzzy +msgid "stop requested" +msgstr "Fehler abgefragt" -#: libvips/foreign/csv.c:307 +#: libvips/iofuncs/region.c:1711 libvips/iofuncs/region.c:1901 #, c-format -msgid "unexpected EOL, line %d col %d" -msgstr "unerwartetes Zeilenende, Zeile %d, Spalte %d" +msgid "unable to input from a %s image" +msgstr "Eingabe von einem %s-Bild nicht möglich" -#: libvips/foreign/vipsload.c:121 -msgid "load vips from file" -msgstr "Vips aus einer Datei laden" +#: libvips/iofuncs/region.c:1735 +msgid "incomplete header" +msgstr "unvollständige Kopfzeilen" -#: libvips/foreign/magickload.c:131 -msgid "load file with ImageMagick" -msgstr "Datei mit ImageMagick laden" +#: libvips/iofuncs/region.c:1804 +msgid "inappropriate region type" +msgstr "Ungeeigneter Regionstyp" -#: libvips/foreign/matload.c:116 -# http://www.dateiendung.com/format/mat -msgid "load mat from file" -msgstr "Mat aus Datei laden" +#: libvips/iofuncs/sbuf.c:85 +msgid "buffered source" +msgstr "" + +#: libvips/iofuncs/sbuf.c:280 +#, fuzzy +msgid "end of file" +msgstr "ln des Bildes" -#: libvips/foreign/jpegload.c:118 +#: libvips/iofuncs/sink.c:262 #, c-format -msgid "bad shrink factor %d" -msgstr "falscher Schrumpffaktor %d" +msgid "stop function failed for image \"%s\"" +msgstr "»stop«-Funktion für Bild »%s« fehlgeschlagen" -#: libvips/foreign/jpegload.c:140 -msgid "load jpeg" -msgstr "JPEG laden" +#: libvips/iofuncs/sink.c:299 +#, c-format +msgid "start function failed for image \"%s\"" +msgstr "»start«-Funktion für Bild »%s« fehlgeschlagen" -#: libvips/foreign/jpegload.c:146 -msgid "Shrink" -msgstr "verkleinern" +#: libvips/iofuncs/sink.c:331 +msgid "per-thread state for sink" +msgstr "Status pro Thread für »sink«" -#: libvips/foreign/jpegload.c:147 -msgid "Shrink factor on load" -msgstr "falscher Verkleinerungsfaktor %d" +#: libvips/iofuncs/sinkdisc.c:108 libvips/iofuncs/util.c:477 +msgid "write failed" +msgstr "Schreiben fehlgeschlagen" -#: libvips/foreign/jpegload.c:153 -msgid "Fail" -msgstr "scheitern" +#: libvips/iofuncs/sinkdisc.c:137 +msgid "per-thread state for sinkdisc" +msgstr "Status pro Thread für »sinkdisc«" -#: libvips/foreign/jpegload.c:154 -msgid "Fail on first warning" -msgstr "scheitert bei erster Warnung" +#: libvips/iofuncs/sinkmemory.c:109 +msgid "per-thread state for sinkmemory" +msgstr "Status pro Thread für »sinkmemory«" -#: libvips/foreign/jpegload.c:234 -msgid "load jpeg from file" -msgstr "JPEG aus Datei laden" +#: libvips/iofuncs/sinkscreen.c:196 +msgid "per-thread state for render" +msgstr "Status pro Thread für »render«" -#: libvips/foreign/jpegload.c:309 -msgid "load jpeg from buffer" -msgstr "JPEG aus Puffer laden" +#: libvips/iofuncs/sinkscreen.c:1122 +msgid "bad parameters" +msgstr "falsche Parameter" -#: libvips/foreign/jpegload.c:315 libvips/foreign/jpegsave.c:260 -#: libvips/foreign/pngsave.c:228 -msgid "Buffer" -msgstr "Puffer" +#: libvips/iofuncs/source.c:281 libvips/iofuncs/target.c:114 +#, fuzzy +msgid "don't set 'filename' and 'descriptor'" +msgstr "kein Datei-Deskriptor" -#: libvips/foreign/jpegload.c:316 -msgid "Buffer to load from" +#: libvips/iofuncs/source.c:358 +msgid "input source" +msgstr "" + +#: libvips/iofuncs/source.c:366 libvips/iofuncs/target.c:304 +msgid "Blob" +msgstr "" + +#: libvips/iofuncs/source.c:367 +#, fuzzy +msgid "Blob to load from" msgstr "Puffer, aus dem geladen werden soll" -#: libvips/foreign/openslide2vips.c:134 -msgid "invalid associated image name" -msgstr "ungültiger zugehöriger Bildname" +#: libvips/iofuncs/source.c:512 +#, fuzzy +msgid "unimplemented target" +msgstr "nicht implementierte Maske" -#: libvips/foreign/openslide2vips.c:159 -msgid "failure opening slide" -msgstr "Fehler beim Öffnen des Dias" +#: libvips/iofuncs/source.c:649 +#, fuzzy +msgid "unable to open for read" +msgstr "Datei »%s« kann nicht zum Lesen geöffnet werden" -#: libvips/foreign/openslide2vips.c:166 -msgid "invalid slide level" -msgstr "ungültige Diastufe" +#: libvips/iofuncs/source.c:890 +#, fuzzy +msgid "pipe too long" +msgstr "»%s« zu lang" -#: libvips/foreign/openslide2vips.c:202 -#, c-format -msgid "getting dimensions: %s" -msgstr "Abfragen der Abmessungen: %s" +#: libvips/iofuncs/source.c:1165 libvips/iofuncs/source.c:1190 +#: libvips/iofuncs/target.c:206 +msgid "bad 'whence'" +msgstr "" -#: libvips/foreign/openslide2vips.c:209 -msgid "image dimensions overflow int" -msgstr "Überlaufganzzahl der Bildabmessungen" +#: libvips/iofuncs/source.c:1211 +#, fuzzy +msgid "bad seek to %" +msgstr "falscher Schrumpffaktor %d" + +#: libvips/iofuncs/sourcecustom.c:173 +msgid "Custom source" +msgstr "" + +#: libvips/iofuncs/sourceginput.c:219 +msgid "GInputStream source" +msgstr "" + +#: libvips/iofuncs/sourceginput.c:227 +msgid "Stream" +msgstr "" + +#: libvips/iofuncs/sourceginput.c:228 +#, fuzzy +msgid "GInputStream to read from" +msgstr "Name der Datei, aus der geladen werden soll" + +#: libvips/iofuncs/system.c:185 +#, fuzzy +msgid "unable to substitute input filename" +msgstr "»munmap« der Datei nicht möglich" + +#: libvips/iofuncs/system.c:191 +#, fuzzy +msgid "unable to substitute output filename" +msgstr "es kann nicht zu einem %s-Bild ausgegeben werden" + +#: libvips/iofuncs/system.c:226 +#, fuzzy, c-format +msgid "command \"%s\" failed" +msgstr "Befehl fehlgeschlagen: »%s«" -#: libvips/foreign/openslide2vips.c:274 +#: libvips/iofuncs/system.c:234 #, c-format -msgid "reading region: %s" -msgstr "Region wird gelesen: %s" +msgid "stderr output: %s" +msgstr "" + +#: libvips/iofuncs/system.c:269 +msgid "run an external command" +msgstr "" + +#: libvips/iofuncs/system.c:290 +msgid "Command" +msgstr "" + +#: libvips/iofuncs/system.c:291 +msgid "Command to run" +msgstr "" + +#: libvips/iofuncs/system.c:297 +#, fuzzy +msgid "Input format" +msgstr "Eingabebild" -#: libvips/foreign/openslide2vips.c:348 +#: libvips/iofuncs/system.c:298 +#, fuzzy +msgid "Format for input filename" +msgstr "erstes Eingabebild" + +#: libvips/iofuncs/system.c:304 +#, fuzzy +msgid "Output format" +msgstr "Ausgabebild" + +#: libvips/iofuncs/system.c:305 +msgid "Format for output filename" +msgstr "" + +#: libvips/iofuncs/system.c:312 +msgid "Command log" +msgstr "" + +#: libvips/iofuncs/target.c:295 +#, fuzzy +msgid "File descriptor should output to memory" +msgstr "Datei-Deskriptor, in den geschrieben werden soll" + +#: libvips/iofuncs/target.c:305 +#, fuzzy +msgid "Blob to save to" +msgstr "Puffer, in den gespeichert werden soll" + +#: libvips/iofuncs/target.c:474 +#, fuzzy +msgid "write error" +msgstr "Lesefehler" + +#: libvips/iofuncs/targetcustom.c:235 +msgid "Custom target" +msgstr "" + +#: libvips/iofuncs/thread.c:179 +msgid "unable to create thread" +msgstr "Thread kann nicht erstellt werden" + +#: libvips/iofuncs/thread.c:214 libvips/iofuncs/thread.c:243 #, c-format -msgid "reading associated image: %s" -msgstr "zugehöriges Bild wird gelesen: %s" +msgid "threads clipped to %d" +msgstr "Threads an %d angeheftet" -#: libvips/foreign/analyze2vips.c:308 -msgid "header file size incorrect" -msgstr "Kopfdatendateigröße nicht korrekt" +#: libvips/iofuncs/threadpool.c:193 +msgid "per-thread state for vipsthreadpool" +msgstr "Status pro Thread für »vipsthreadpool«" -#: libvips/foreign/analyze2vips.c:353 -msgid "header size incorrect" -msgstr "Kopfdatengröße nicht korrekt" +#: libvips/iofuncs/type.c:958 +#, fuzzy, c-format +msgid "unable to convert \"%s\" to int" +msgstr "»%s« kann nicht zur Eingabe geöffnet werden" + +#: libvips/iofuncs/util.c:455 +msgid "unable to get file stats" +msgstr "Dateistatus kann nicht abgefragt werden" -#: libvips/foreign/analyze2vips.c:371 +#: libvips/iofuncs/util.c:619 #, c-format -msgid "%d-dimensional images not supported" -msgstr "%d-dimensionale Bilder nicht unterstützt" +msgid "unable to open file \"%s\" for reading" +msgstr "Datei »%s« kann nicht zum Lesen geöffnet werden" -#: libvips/foreign/analyze2vips.c:424 +#: libvips/iofuncs/util.c:641 #, c-format -msgid "datatype %d not supported" -msgstr "Datentyp %d nicht unterstützt" +msgid "unable to open file \"%s\" for writing" +msgstr "Datei »%s« kann nicht zum Schreiben geöffnet werden" -#: libvips/foreign/tiff2vips.c:262 libvips/foreign/tiff2vips.c:285 -#: libvips/foreign/tiff2vips.c:303 +#: libvips/iofuncs/util.c:662 #, c-format -msgid "required field %d missing" -msgstr "benötigtes Feld %d fehlt" +msgid "\"%s\" too long" +msgstr "»%s« zu lang" -#: libvips/foreign/tiff2vips.c:266 +#: libvips/iofuncs/util.c:710 #, c-format -msgid "required field %d=%d, not %d" -msgstr "benötigtes Feld %d=%d, nicht %d" +msgid "error reading from file \"%s\"" +msgstr "Fehler beim Lesen von Datei »%s«" -#: libvips/foreign/tiff2vips.c:650 -#, c-format -msgid "%d bits per sample palette image not supported" -msgstr "%d Bit pro Musterfarbpalettenbild nicht unterstützt" +#: libvips/iofuncs/util.c:756 +#, fuzzy, c-format +msgid "write error (%zd out of %zd blocks written)" +msgstr "Schreibfehler (%zd aus %zd Blöcken geschrieben) … Platte voll?" -#: libvips/foreign/tiff2vips.c:659 -msgid "bad colormap" -msgstr "falsche Farbzusammenstellung" +#: libvips/iofuncs/util.c:1003 +msgid "unable to seek" +msgstr "kann nicht gesucht werden" -#: libvips/foreign/tiff2vips.c:716 libvips/foreign/tiff2vips.c:747 -msgid "3 or 4 bands RGB TIFF only" -msgstr "nur RGB-TIFF mit drei oder vier Bändern" +#: libvips/iofuncs/util.c:1028 libvips/iofuncs/util.c:1035 +msgid "unable to truncate" +msgstr "kann nicht gekürzt werden" -#: libvips/foreign/tiff2vips.c:818 -msgid "4 or 5 bands CMYK TIFF only" -msgstr "nur CMYK-TIFF mit vier oder fünf Bändern" +#: libvips/iofuncs/util.c:1121 +#, fuzzy, c-format +msgid "unable to remove directory \"%s\", %s" +msgstr "Daten für »%s« können nicht gelesen werden, %s" -#: libvips/foreign/tiff2vips.c:869 -msgid "unknown resolution unit" -msgstr "unbekannte Auflösungseinheit" +#: libvips/iofuncs/util.c:1138 +#, fuzzy, c-format +msgid "unable to rename file \"%s\" as \"%s\", %s" +msgstr "" +"Datei »%s« kann nicht gelesen werden\n" +"libMagick-Fehler: %s %s" + +#: libvips/iofuncs/util.c:1267 +msgid "unexpected end of string" +msgstr "Unerwartetes Ende der Zeichenkette" -#: libvips/foreign/tiff2vips.c:874 +#: libvips/iofuncs/util.c:1285 libvips/iofuncs/util.c:1355 #, c-format -msgid "" -"no resolution information for TIFF image \"%s\" -- defaulting to 1 pixel per " -"mm" +msgid "expected %s, saw %s" +msgstr "%s erwartet, %s gesehen" + +#: libvips/iofuncs/util.c:1664 +msgid "no such enum type" msgstr "" -"Keine Auflösungsinformationen für TIFF-Bild »%s« – Standard auf 1 Bildpunkt " -"pro mm" -#: libvips/foreign/tiff2vips.c:946 -#, c-format -msgid "unsupported sample format %d for lab image" -msgstr "nicht unterstütztes Musterformat %d für LAB-Bild" +#: libvips/iofuncs/util.c:1682 +#, fuzzy, c-format +msgid "enum '%s' has no member '%s', should be one of: %s" +msgstr "Aufzählung »%s« hat keinen Bestandteil »%s«" -#: libvips/foreign/tiff2vips.c:956 -#, c-format -msgid "unsupported depth %d for LAB image" -msgstr "nicht unterstützte Tiefe %d für LAB-Bild" +#: libvips/iofuncs/util.c:1701 +msgid "no such flag type" +msgstr "" -#: libvips/foreign/tiff2vips.c:995 -#, c-format -msgid "unsupported sample format %d for greyscale image" -msgstr "nicht unterstütztes Musterformat %d für Graustufenbild" +#: libvips/iofuncs/util.c:1720 +#, fuzzy, c-format +msgid "flags '%s' has no member '%s'" +msgstr "Aufzählung »%s« hat keinen Bestandteil »%s«" -#: libvips/foreign/tiff2vips.c:1004 +#: libvips/iofuncs/vips.c:338 #, c-format -msgid "unsupported depth %d for greyscale image" -msgstr "nicht unterstützte Tiefe %d für Graustufenbild" +msgid "\"%s\" is not a VIPS image" +msgstr "»%s« ist kein VIPS-Bild" -#: libvips/foreign/tiff2vips.c:1052 -#, c-format -msgid "unsupported sample format %d for rgb image" -msgstr "nicht unterstütztes Musterformat %d für RGB-Bild" +#: libvips/iofuncs/vips.c:395 +msgid "unknown coding" +msgstr "unbekannte Kodierung" -#: libvips/foreign/tiff2vips.c:1061 -#, c-format -msgid "unsupported depth %d for RGB image" -msgstr "nicht unterstützte Tiefe %d für RGB-Bild" +#: libvips/iofuncs/vips.c:405 +msgid "malformed LABQ image" +msgstr "" -#: libvips/foreign/tiff2vips.c:1075 -#, c-format -msgid "unknown photometric interpretation %d" -msgstr "unbekannte fotometrische Deutung %d" +#: libvips/iofuncs/vips.c:414 +#, fuzzy +msgid "malformed RAD image" +msgstr "kein RAD-Bild" -#: libvips/foreign/tiff2vips.c:1331 libvips/foreign/radiance.c:959 -msgid "read error" +#: libvips/iofuncs/vips.c:485 +msgid "unable to read history" +msgstr "Verlauf kann nicht gelesen werden" + +#: libvips/iofuncs/vips.c:518 +#, fuzzy +msgid "more than 100 megabytes of XML? sufferin' succotash!" +msgstr "mehr als 10 Megabyte XML? Leidende Succotash!" + +#: libvips/iofuncs/vips.c:552 +#, fuzzy +msgid "unable to allocate read buffer" +msgstr "In den Puffer kann nicht geschrieben werden." + +#: libvips/iofuncs/vips.c:558 +msgid "read error while fetching XML" +msgstr "" + +#: libvips/iofuncs/vips.c:570 +#, fuzzy +msgid "XML parse error" msgstr "Lesefehler" -#: libvips/foreign/tiff2vips.c:1444 -#, c-format -msgid "bad page number %d" -msgstr "falsche Seitennummer %d" +#: libvips/iofuncs/vips.c:635 +msgid "incorrect namespace in XML" +msgstr "falscher Namensraum in XML" -#: libvips/foreign/tiff2vips.c:1465 libvips/foreign/vips2tiff.c:286 -#, c-format -msgid "unable to open \"%s\" for input" -msgstr "»%s« kann nicht zur Eingabe geöffnet werden" +#: libvips/iofuncs/vips.c:683 +msgid "error transforming from save format" +msgstr "Fehler beim Umwandeln vom gespeicherten Format" -#: libvips/foreign/tiff2vips.c:1520 libvips/foreign/tiff2vips.c:1550 -#, c-format -msgid "TIFF file does not contain page %d" -msgstr "TIFF-Datei enthält nicht Seite %d" +#: libvips/iofuncs/vips.c:784 libvips/iofuncs/vips.c:1056 +#: libvips/iofuncs/window.c:232 +msgid "file has been truncated" +msgstr "Datei wurde gekürzt" -#: libvips/foreign/jpegsave.c:118 -msgid "save jpeg" -msgstr "JPEG speichern" +#: libvips/iofuncs/vips.c:836 libvips/iofuncs/vips.c:927 +msgid "error transforming to save format" +msgstr "Fehler beim Umwandeln in das zu speichernde Format" -#: libvips/foreign/jpegsave.c:187 -msgid "save image to jpeg file" -msgstr "Bild in JPEG-Datei speichern" +#: libvips/iofuncs/vips.c:1041 +#, c-format +msgid "unable to read header for \"%s\"" +msgstr "Kopfdaten für »%s« können nicht gelesen werden" -#: libvips/foreign/jpegsave.c:256 -msgid "save image to jpeg buffer" -msgstr "Bild in den JPEG-Puffer speichern" +#: libvips/iofuncs/vips.c:1055 libvips/iofuncs/window.c:231 +#, c-format +msgid "unable to read data for \"%s\", %s" +msgstr "Daten für »%s« können nicht gelesen werden, %s" -#: libvips/foreign/jpegsave.c:261 libvips/foreign/pngsave.c:229 -msgid "Buffer to save to" -msgstr "Puffer, in den gespeichert werden soll" +# http://radsite.lbl.gov/radiance/refer/Notes/picture_format.html +#: libvips/iofuncs/vips.c:1067 +#, fuzzy, c-format +msgid "error reading vips image metadata: %s" +msgstr "Fehler beim Lesen der Radiance-Kopfzeilen" -#: libvips/foreign/jpegsave.c:303 -msgid "error writing output" -msgstr "Fehler beim Schreiben der Ausgabe" +# http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650& +# db=man&fname=/usr/share/catman/p_man/cat3/il_c/ilAbsImg.z +#: libvips/morphology/countlines.c:135 +#, fuzzy +msgid "count lines in an image" +msgstr "absoluter Wert eines Bildes" -#: libvips/foreign/jpegsave.c:319 -# http://de.wikipedia.org/wiki/MIME#image -msgid "save image to jpeg mime" -msgstr "Bild in JPEG-MIME speichern" +#: libvips/morphology/countlines.c:139 +#, fuzzy +msgid "Nolines" +msgstr "Zeilen" -#: libvips/foreign/rawsave.c:159 -# http://de.wikipedia.org/wiki/Rohdatenformat_(Fotografie) -msgid "save image to raw file" -msgstr "Bild in Rohdatenformatdatei speichern" +#: libvips/morphology/countlines.c:140 +#, fuzzy +msgid "Number of lines" +msgstr "Anzahl der Bänder in einem Bild" -#: libvips/foreign/rawsave.c:266 -msgid "write raw image to file descriptor" -msgstr "Rohdatenbild in Datei-Deskriptor schreiben" +#: libvips/morphology/countlines.c:147 +#, fuzzy +msgid "Countlines left-right or up-down" +msgstr "von links nach rechts oder von oben nach unten zusammenführen" -#: libvips/foreign/rawsave.c:273 -msgid "File descriptor" -msgstr "Datei-Deskriptor" +#: libvips/morphology/labelregions.c:120 +#, fuzzy +msgid "label regions in an image" +msgstr "Anzahl der Bänder in einem Bild" -#: libvips/foreign/rawsave.c:274 -msgid "File descriptor to write to" -msgstr "Datei-Deskriptor, in den geschrieben werden soll" +#: libvips/morphology/labelregions.c:125 +msgid "Mask of region labels" +msgstr "" -#: libvips/foreign/ppmsave.c:109 -# http://de.wikipedia.org/wiki/Portable_Pixmap -msgid "save image to ppm file" -msgstr "Bild in PPM-Datei speichern" +#: libvips/morphology/labelregions.c:130 +msgid "Segments" +msgstr "" -#: libvips/foreign/ppmsave.c:125 -msgid "ASCII" -msgstr "ASCII" +#: libvips/morphology/labelregions.c:131 +msgid "Number of discrete contiguous regions" +msgstr "" -#: libvips/foreign/ppmsave.c:126 -msgid "save as ascii" -msgstr "Bild als ASCII speichern" +#: libvips/morphology/morph.c:885 +#, fuzzy, c-format +msgid "bad mask element (%f should be 0, 128 or 255)" +msgstr "falsches Maskenelement (%d sollte 0, 128 oder 255 sein)" -#: libvips/foreign/vips2jpeg.c:132 -#, c-format -msgid "%s" -msgstr "%s" +#: libvips/morphology/morph.c:955 +#, fuzzy +msgid "morphology operation" +msgstr "unäre Transaktionen" -#: libvips/foreign/vips2jpeg.c:363 -msgid "error setting JPEG resolution" -msgstr "Fehler beim Setzen der JPEG-Auflösung" +#: libvips/morphology/morph.c:971 +msgid "Morphology" +msgstr "" -#: libvips/foreign/vips2jpeg.c:510 -msgid "error saving EXIF" -msgstr "Fehler beim Speichern von EXIF" +#: libvips/morphology/morph.c:972 +#, fuzzy +msgid "Morphological operation to perform" +msgstr "durchzuführende Rundungstransakktion" -#: libvips/foreign/openexr2vips.c:115 -#, c-format -msgid "EXR error: %s" -msgstr "EXR-Fehler: %s" +#: libvips/morphology/morphology.c:115 +#, fuzzy +msgid "morphological operations" +msgstr "arithmetische Transaktionen" -#: libvips/foreign/magick2vips.c:215 -#, c-format -msgid "unsupported image type %d" -msgstr "nicht unterstützter Bildtyp %d" +#: libvips/morphology/nearest.c:305 +msgid "fill image zeros with nearest non-zero pixel" +msgstr "" -#: libvips/foreign/magick2vips.c:275 -#, c-format -msgid "unsupported bit depth %d" -msgstr "nicht unterstützte Bit-Tiefe %d" +#: libvips/morphology/nearest.c:309 +#, fuzzy +msgid "Out" +msgstr "Ausgabe" -#: libvips/foreign/magick2vips.c:307 -#, c-format -msgid "unsupported colorspace %d" -msgstr "nicht unterstützter Farbraum %d" +#: libvips/morphology/nearest.c:310 +msgid "Value of nearest non-zero pixel" +msgstr "" -#: libvips/foreign/magick2vips.c:622 -msgid "unable to read pixels" -msgstr "Bildpunkte können nicht gelesen werden" +#: libvips/morphology/nearest.c:316 +msgid "Distance to nearest non-zero pixel" +msgstr "" -#: libvips/foreign/magick2vips.c:658 -#, c-format -msgid "" -"unable to read file \"%s\"\n" -"libMagick error: %s %s" +#: libvips/morphology/rank.c:496 +#, fuzzy +msgid "index out of range" +msgstr " »bins« außerhalb des Bereichs [1,%d]" + +#: libvips/morphology/rank.c:560 +msgid "rank filter" msgstr "" -"Datei »%s« kann nicht gelesen werden\n" -"libMagick-Fehler: %s %s" -#: libvips/foreign/magick2vips.c:692 -#, c-format -msgid "" -"unable to ping file \"%s\"\n" -"libMagick error: %s %s" +#: libvips/morphology/rank.c:585 +msgid "Select pixel at index" msgstr "" -"Datei »%s« kann nicht angepingt werden\n" -"libMagick-Fehler: %s %s" -#: libvips/foreign/magick2vips.c:703 -msgid "bad image size" -msgstr "falsche Bildgröße" +#: libvips/mosaicing/chkpair.c:200 +msgid "inputs incompatible" +msgstr "Eingaben inkompatibel" -#: libvips/foreign/vipspng.c:230 -msgid "unsupported color type" -msgstr "nicht unterstützter Farbtyp" +#: libvips/mosaicing/chkpair.c:204 libvips/mosaicing/im_tbcalcon.c:105 +msgid "help!" +msgstr "Hilfe!" -#: libvips/foreign/vipspng.c:570 -msgid "compress should be in [0,9]" -msgstr "Komprimierung sollte in [0,9] liegen" +#: libvips/mosaicing/global_balance.c:151 +msgid "no matching '>'" +msgstr "kein passendes »>«" -#: libvips/foreign/vipspng.c:650 -#, c-format -msgid "unable to write \"%s\"" -msgstr "»%s« kann nicht geschrieben werden" +#: libvips/mosaicing/global_balance.c:160 +msgid "too many items" +msgstr "zu viele Elemente" -#: libvips/foreign/vipspng.c:749 -msgid "unable to write to buffer" -msgstr "In den Puffer kann nicht geschrieben werden." +# Propogate a transform down a tree. If dirty is set, we've been here before, +# so there is a doubling up of this node. If this is a leaf, then we have the +# same leaf twice (which, in fact, we can cope with); if this is a node, we +# have circularity. +#: libvips/mosaicing/global_balance.c:463 +msgid "circularity detected" +msgstr "Zirkularität entdeckt" -#: libvips/foreign/matlab.c:106 libvips/foreign/fits.c:178 -#: libvips/iofuncs/vips.c:143 libvips/mosaicing/global_balance.c:1181 -#: libvips/mosaicing/global_balance.c:1516 +#: libvips/mosaicing/global_balance.c:497 +#: libvips/mosaicing/global_balance.c:557 #, c-format -msgid "unable to open \"%s\"" -msgstr "»%s« kann nicht geöffnet werden" +msgid "image \"%s\" used twice as output" +msgstr "Bild »%s« zweimal als Ausgabe benutzt" -#: libvips/foreign/matlab.c:114 -#, c-format -msgid "no matrix variables in \"%s\"" -msgstr "keine Matrixvariablen in »%s«" +#: libvips/mosaicing/global_balance.c:606 +msgid "bad number of args in join line" +msgstr "falsche Anzahl von Argumenten in »join«-Zeile" -#: libvips/foreign/matlab.c:175 -#, c-format -msgid "unsupported rank %d\n" -msgstr "nicht unterstützte Rangstufe %d\n" +#: libvips/mosaicing/global_balance.c:648 +msgid "bad number of args in join1 line" +msgstr "falsche Anzahl von Argumenten in »join1«-Zeile" -#: libvips/foreign/matlab.c:188 -#, c-format -msgid "unsupported class type %d\n" -msgstr "nicht unterstützter Klassentyp %d\n" +#: libvips/mosaicing/global_balance.c:684 +msgid "bad number of args in copy line" +msgstr "falsche Anzahl von Argumenten in »copy«-Zeile" -#: libvips/foreign/matlab.c:236 -msgid "Mat_VarReadDataAll failed" -msgstr "»Mat_VarReadDataAll« fehlgeschlagen" +#: libvips/mosaicing/global_balance.c:742 +msgid "" +"mosaic root not found in desc file\n" +"is this really a mosaiced image?" +msgstr "" +"Mosaik-Wurzel nicht in Beschreibungsdatei gefunden\n" +"ist das wirklich ein Bild?" -#: libvips/foreign/jpeg2vips.c:167 -#, c-format -msgid "read gave %ld warnings" -msgstr "Lesen ergab %ld Warnungen" +#: libvips/mosaicing/global_balance.c:753 +msgid "more than one root" +msgstr "mehr als eine Wurzel" -#: libvips/foreign/jpeg2vips.c:489 -msgid "error reading resolution" -msgstr "Fehler beim Lesen der Auflösung" +#: libvips/mosaicing/global_balance.c:1525 +msgid "bad sizes" +msgstr "falsche Größen" -#: libvips/foreign/jpeg2vips.c:510 -msgid "unknown EXIF resolution unit" -msgstr "unbekannte EXIF-Auflösungseinheit" +#: libvips/mosaicing/global_balance.c:1920 +#, fuzzy +msgid "global balance an image mosaic" +msgstr "ein Radiance-Bild aus einer Datei laden" -#: libvips/foreign/jpeg2vips.c:718 -msgid "unknown JFIF resolution unit" -msgstr "unbekannte JFIF-Auflösungseinheit" +#: libvips/mosaicing/global_balance.c:1936 +msgid "Gamma" +msgstr "" -#: libvips/foreign/fits.c:240 -msgid "dimensions above 3 must be size 1" -msgstr "Dimensionen größer drei müssen die Größe eins haben" +#: libvips/mosaicing/global_balance.c:1937 +#, fuzzy +msgid "Image gamma" +msgstr "Bilddateiname" -#: libvips/foreign/fits.c:256 -#, c-format -msgid "bad number of axis %d" -msgstr "falsche Achsenanzahl %d" +#: libvips/mosaicing/global_balance.c:1943 +#, fuzzy +msgid "Int output" +msgstr "Ausgabe" -#: libvips/foreign/fits.c:272 -#, c-format -msgid "unsupported bitpix %d\n" -msgstr "nicht unterstützte »bitpix« %d\n" +#: libvips/mosaicing/global_balance.c:1944 +#, fuzzy +msgid "Integer output" +msgstr "detaillierte Ausgabe" -#: libvips/foreign/fits.c:576 libvips/iofuncs/vips.c:171 -#, c-format -msgid "unable to write to \"%s\"" -msgstr "auf »%s« kann nicht geschrieben werden" +#: libvips/mosaicing/im_avgdxdy.c:65 +msgid "no points to average" +msgstr "keine Punkte zum Mitteln" + +#: libvips/mosaicing/im_clinear.c:138 +#, fuzzy +msgid "vips_invmat failed" +msgstr "»im_invmat« fehlgeschlagen" + +#: libvips/mosaicing/im_lrcalcon.c:206 +msgid "overlap too small for your search size" +msgstr "Überlappen zu schmal für Ihre Suchgröße" -#: libvips/foreign/fits.c:637 +#: libvips/mosaicing/im_lrcalcon.c:245 #, c-format -msgid "unsupported BandFmt %d\n" -msgstr "nicht unterstütztes BandFmt %d\n" +msgid "found %d tie-points, need at least %d" +msgstr "es wurden %d Verbindungspunkte gefunden, mindestens %d sind nötig" -#: libvips/foreign/csvsave.c:112 -msgid "save image to csv file" -msgstr "Bild in CSV-Datei speichern" +#: libvips/mosaicing/im_lrcalcon.c:290 +msgid "not 1-band uchar image" +msgstr "kein »uchar«-Bild mit einem Band" -#: libvips/foreign/csvsave.c:128 libvips/foreign/csvload.c:160 -msgid "Separator" -msgstr "Trenner" +#: libvips/mosaicing/im_tbcalcon.c:119 +msgid "overlap too small" +msgstr "Überlappen zu schmal" -#: libvips/foreign/csvsave.c:129 -msgid "Separator characters" -msgstr "Trennzeichen" +#: libvips/mosaicing/lrmerge.c:786 +msgid "mwidth must be -1 or >= 0" +msgstr "»mwidth« muss -1 oder >= 0 sein" + +#: libvips/mosaicing/lrmerge.c:818 +msgid "no overlap" +msgstr "kein Überlappen" -#: libvips/foreign/ppm.c:109 -msgid "bad int" -msgstr "falsche Ganzzahl" +#: libvips/mosaicing/lrmerge.c:888 libvips/mosaicing/tbmerge.c:693 +msgid "unknown coding type" +msgstr "unbekannter Kodierungstyp" -#: libvips/foreign/ppm.c:121 -msgid "bad float" -msgstr "falsche Fließkommazahl" +#: libvips/mosaicing/lrmerge.c:906 libvips/mosaicing/tbmerge.c:711 +msgid "too much overlap" +msgstr "zu viel Überlappung" -#: libvips/foreign/ppm.c:172 -msgid "bad magic number" -msgstr "falsche magische Zahl" +#: libvips/mosaicing/lrmosaic.c:122 libvips/mosaicing/tbmosaic.c:93 +msgid "bad area parameters" +msgstr "falsche Bereichsparameter" -#: libvips/foreign/ppm.c:222 -msgid "not whitespace before start of binary data" -msgstr "kein Leerraum vor dem Start der binären Daten" +#: libvips/mosaicing/lrmosaic.c:143 libvips/mosaicing/tbmosaic.c:114 +msgid "overlap too small for search" +msgstr "Überlappen zu klein für Suche" -#: libvips/foreign/ppm.c:599 libvips/foreign/ppm.c:611 -msgid "write error ... disc full?" -msgstr "Schreibfehler … Platte voll?" +#: libvips/mosaicing/lrmosaic.c:171 libvips/mosaicing/tbmosaic.c:142 +msgid "unknown Coding type" +msgstr "unbekannter Kodierungstyp" -#: libvips/foreign/ppm.c:716 -msgid "binary >8 bit images must be float" -msgstr "binäre Bilder >8 Bit müssen aus Fließkommazahlen bestehen" +#: libvips/mosaicing/match.c:192 +#, fuzzy +msgid "first-order match of two images" +msgstr "zwei Bilder subtrahieren" -#: libvips/foreign/vips2tiff.c:270 -#, c-format -msgid "unable to open \"%s\" for output" -msgstr "»%s« kann nicht zur Ausgabe geöffnet werden" +#: libvips/mosaicing/match.c:197 libvips/mosaicing/merge.c:123 +#: libvips/mosaicing/mosaic1.c:499 libvips/mosaicing/mosaic.c:180 +#, fuzzy +msgid "Reference image" +msgstr "Zeilensprungbild" -#: libvips/foreign/vips2tiff.c:692 -msgid "layer buffer exhausted -- try making TIFF output tiles smaller" +#: libvips/mosaicing/match.c:202 libvips/mosaicing/merge.c:128 +#: libvips/mosaicing/mosaic1.c:504 libvips/mosaicing/mosaic.c:185 +msgid "Secondary" msgstr "" -"Ebenenpuffer aufgebraucht – versuchen Sie die TIFF-Ausgabekacheln zu " -"verkleinern" -#: libvips/foreign/vips2tiff.c:922 -msgid "TIFF write tile failed" -msgstr "Schreiben des TIFF-Bildes fehlgeschlagen" +#: libvips/mosaicing/match.c:203 libvips/mosaicing/merge.c:129 +#: libvips/mosaicing/mosaic1.c:505 libvips/mosaicing/mosaic.c:186 +#, fuzzy +msgid "Secondary image" +msgstr "zweites Eingabebild" -#: libvips/foreign/vips2tiff.c:998 -msgid "internal error #9876345" -msgstr "interner Fehler #9876345" +#: libvips/mosaicing/match.c:214 libvips/mosaicing/mosaic1.c:523 +msgid "xr1" +msgstr "" -#: libvips/foreign/vips2tiff.c:1251 -msgid "tile size not a multiple of 16" -msgstr "Bildgröße kein Vielfaches von 16" +#: libvips/mosaicing/match.c:215 libvips/mosaicing/match.c:222 +#: libvips/mosaicing/mosaic1.c:524 libvips/mosaicing/mosaic1.c:531 +msgid "Position of first reference tie-point" +msgstr "" -#: libvips/foreign/vips2tiff.c:1257 -msgid "can't have strip pyramid -- enabling tiling" +#: libvips/mosaicing/match.c:221 libvips/mosaicing/mosaic1.c:530 +msgid "yr1" msgstr "" -"nicht ummantelte Pyramide nicht möglich – Zerteilung wird eingeschaltet" -#: libvips/foreign/vips2tiff.c:1268 -msgid "can only pyramid LABQ and non-complex images" +#: libvips/mosaicing/match.c:228 libvips/mosaicing/mosaic1.c:537 +msgid "xs1" msgstr "" -"nur LABQ und nicht-komplexe Bilder können pyramidenartig verwendet werden" -#: libvips/foreign/vips2tiff.c:1285 -msgid "can't have 1-bit JPEG -- disabling JPEG" -msgstr "1-Bit-JPEG nicht möglich – JPEG wird ausgeschaltet" +#: libvips/mosaicing/match.c:229 libvips/mosaicing/match.c:236 +#: libvips/mosaicing/mosaic1.c:538 libvips/mosaicing/mosaic1.c:545 +msgid "Position of first secondary tie-point" +msgstr "" -#: libvips/foreign/vips2tiff.c:1463 -msgid "unsigned 8-bit int, 16-bit int, and 32-bit float only" -msgstr "nur vorzeichenlose 8-Bit-Ganzzahl und 32-Bit-Fließkommazahl" +#: libvips/mosaicing/match.c:235 libvips/mosaicing/mosaic1.c:544 +msgid "ys1" +msgstr "" -#: libvips/foreign/vips2tiff.c:1470 -msgid "1 to 5 bands only" -msgstr "nur 1 bis 5 Bänder" +#: libvips/mosaicing/match.c:242 libvips/mosaicing/mosaic1.c:551 +msgid "xr2" +msgstr "" -#: libvips/foreign/radiance.c:885 -# http://radsite.lbl.gov/radiance/refer/Notes/picture_format.html -msgid "error reading radiance header" -msgstr "Fehler beim Lesen der Radiance-Kopfzeilen" +#: libvips/mosaicing/match.c:243 libvips/mosaicing/match.c:250 +#: libvips/mosaicing/mosaic1.c:552 libvips/mosaicing/mosaic1.c:559 +msgid "Position of second reference tie-point" +msgstr "" -#: libvips/foreign/csvload.c:121 -msgid "load csv from file" -msgstr "CSV aus Datei laden" +#: libvips/mosaicing/match.c:249 libvips/mosaicing/mosaic1.c:558 +msgid "yr2" +msgstr "" -#: libvips/foreign/csvload.c:139 -msgid "Skip" -msgstr "überspringen" +#: libvips/mosaicing/match.c:256 libvips/mosaicing/mosaic1.c:565 +msgid "xs2" +msgstr "" -#: libvips/foreign/csvload.c:140 -msgid "Skip this many lines at the start of the file" -msgstr "so viele Zeilen ab dem Dateianfang überspringen" +#: libvips/mosaicing/match.c:257 libvips/mosaicing/match.c:264 +#: libvips/mosaicing/mosaic1.c:566 libvips/mosaicing/mosaic1.c:573 +msgid "Position of second secondary tie-point" +msgstr "" -#: libvips/foreign/csvload.c:146 -msgid "Lines" -msgstr "Zeilen" +#: libvips/mosaicing/match.c:263 libvips/mosaicing/mosaic1.c:572 +msgid "ys2" +msgstr "" -#: libvips/foreign/csvload.c:147 -msgid "Read this many lines from the file" -msgstr "so viele Zeilen aus der Datei lesen" +#: libvips/mosaicing/match.c:270 libvips/mosaicing/mosaic1.c:579 +#: libvips/mosaicing/mosaic.c:232 +#, fuzzy +msgid "hwindow" +msgstr "Windows-Fehler" -#: libvips/foreign/csvload.c:153 -msgid "Whitespace" -msgstr "Leerraum" +#: libvips/mosaicing/match.c:271 libvips/mosaicing/mosaic1.c:580 +#: libvips/mosaicing/mosaic.c:233 +msgid "Half window size" +msgstr "" -#: libvips/foreign/csvload.c:154 -msgid "Set of whitespace characters" -msgstr "Satz von Leerraumzeichen" +#: libvips/mosaicing/match.c:277 libvips/mosaicing/mosaic1.c:586 +#: libvips/mosaicing/mosaic.c:239 +msgid "harea" +msgstr "" -#: libvips/foreign/csvload.c:161 -msgid "Set of separator characters" -msgstr "Satz von Trennzeichen" +#: libvips/mosaicing/match.c:278 libvips/mosaicing/mosaic1.c:587 +#: libvips/mosaicing/mosaic.c:240 +#, fuzzy +msgid "Half area size" +msgstr "falsche Bildgröße" -#: libvips/foreign/pngsave.c:95 -msgid "save png" -msgstr "PNG speichern" +#: libvips/mosaicing/match.c:284 libvips/mosaicing/mosaic1.c:593 +msgid "Search" +msgstr "" -#: libvips/foreign/pngsave.c:104 -msgid "Compression factor" -msgstr "Komprimierungsfaktor" +#: libvips/mosaicing/match.c:285 libvips/mosaicing/mosaic1.c:594 +msgid "Search to improve tie-points" +msgstr "" -#: libvips/foreign/pngsave.c:110 -msgid "Interlace" +#: libvips/mosaicing/match.c:291 libvips/mosaicing/mosaic1.c:600 +#: libvips/resample/affine.c:651 libvips/resample/mapim.c:561 +#: libvips/resample/quadratic.c:351 libvips/resample/resize.c:376 +#: libvips/resample/similarity.c:127 +#, fuzzy +msgid "Interpolate" msgstr "Zeilensprung" -#: libvips/foreign/pngsave.c:111 -msgid "Interlace image" -msgstr "Zeilensprungbild" - -#: libvips/foreign/pngsave.c:162 -msgid "save image to png file" -msgstr "Bild in PNG-Datei speichern" - -#: libvips/foreign/pngsave.c:224 -msgid "save image to png buffer" -msgstr "Bild in den PNG-Puffer speichern" - -#: libvips/foreign/foreign.c:384 -msgid "load and save image files" -msgstr "Bilddateien laden und speichern" +#: libvips/mosaicing/match.c:292 libvips/mosaicing/mosaic1.c:601 +#: libvips/resample/affine.c:652 libvips/resample/mapim.c:562 +#: libvips/resample/resize.c:377 libvips/resample/similarity.c:128 +msgid "Interpolate pixels with this" +msgstr "" -#: libvips/foreign/foreign.c:525 libvips/mosaicing/im_remosaic.c:76 -#, c-format -msgid "file \"%s\" not found" -msgstr "Datei »%s« nicht gefunden" +#: libvips/mosaicing/matrixinvert.c:312 libvips/mosaicing/matrixinvert.c:328 +#: libvips/mosaicing/matrixinvert.c:353 libvips/resample/transform.c:60 +msgid "singular or near-singular matrix" +msgstr "" -#: libvips/foreign/foreign.c:534 libvips/foreign/foreign.c:1022 -#, c-format -msgid "\"%s\" is not a known file format" -msgstr "»%s« ist kein bekanntes Dateiformat" +#: libvips/mosaicing/matrixinvert.c:406 +msgid "non-square matrix" +msgstr "" -#: libvips/foreign/foreign.c:740 -msgid "images do not match" -msgstr "Bilder passen nicht zusammen" +#: libvips/mosaicing/matrixinvert.c:439 +#, fuzzy +msgid "invert an matrix" +msgstr "ein Bild invertieren" -#: libvips/foreign/foreign.c:826 -msgid "" -"VIPS_FOREIGN_PARTIAL and VIPS_FOREIGN_SEQUENTIAL both set -- using SEQUENTIAL" +#: libvips/mosaicing/matrixinvert.c:444 +msgid "An square matrix" msgstr "" -"sowohl VIPS_FOREIGN_PARTIAL als auch VIPS_FOREIGN_SEQUENTIAL setzen – " -"verwenden Sie SEQUENTIAL" -#: libvips/foreign/foreign.c:894 -msgid "file loaders" -msgstr "Dateilader" +#: libvips/mosaicing/matrixinvert.c:450 +#, fuzzy +msgid "Output matrix" +msgstr "Ausgabebild" -#: libvips/foreign/foreign.c:903 -msgid "Flags" -msgstr "Schalter" +#: libvips/mosaicing/merge.c:116 +#, fuzzy +msgid "merge two images" +msgstr "zwei Bilder hinzufügen" -#: libvips/foreign/foreign.c:904 -msgid "Flags for this file" -msgstr "Schalter für diese Datei" +#: libvips/mosaicing/merge.c:141 +#, fuzzy +msgid "Horizontal or vertical merge" +msgstr "horizontaler Versatz vom Ursprung" -#: libvips/foreign/foreign.c:910 -msgid "Disc" -msgstr "Platte" +#: libvips/mosaicing/merge.c:147 +#, fuzzy +msgid "dx" +msgstr "x" -#: libvips/foreign/foreign.c:911 -msgid "Open to disc" -msgstr "offen zur Platte" +#: libvips/mosaicing/merge.c:148 +msgid "Horizontal displacement from sec to ref" +msgstr "" -#: libvips/foreign/foreign.c:917 -msgid "Sequential" -msgstr "sequenziell" +#: libvips/mosaicing/merge.c:154 +#, fuzzy +msgid "dy" +msgstr "y" -#: libvips/foreign/foreign.c:918 -msgid "Sequential read only" -msgstr "sequenziell nur mit Lesezugriff" +#: libvips/mosaicing/merge.c:155 +msgid "Vertical displacement from sec to ref" +msgstr "" -#: libvips/foreign/foreign.c:1370 -msgid "file savers" -msgstr "Dateispeicherer" +#: libvips/mosaicing/merge.c:161 libvips/mosaicing/mosaic1.c:606 +#: libvips/mosaicing/mosaic.c:246 +#, fuzzy +msgid "Max blend" +msgstr "Mischung" -#: libvips/foreign/foreign.c:1380 -msgid "Image to save" -msgstr "zu speicherndes Bild" +#: libvips/mosaicing/merge.c:162 libvips/mosaicing/mosaic1.c:607 +#: libvips/mosaicing/mosaic.c:247 +#, fuzzy +msgid "Maximum blend size" +msgstr "Maximalwert des Bildes" -#: libvips/freq_filt/im_freq_mask.c:108 -msgid "mask sizes power of 2 only" -msgstr "Maskengröße nur Potenzen von 2" +#: libvips/mosaicing/mosaic1.c:494 +#, fuzzy +msgid "first-order mosaic of two images" +msgstr "zwei Bilder subtrahieren" -#: libvips/freq_filt/im_freq_mask.c:155 -msgid "unimplemented mask type" -msgstr "nicht implementierter Maskentyp" +#: libvips/mosaicing/mosaic1.c:517 libvips/mosaicing/mosaic.c:198 +#, fuzzy +msgid "Horizontal or vertical mosaic" +msgstr "horizontale Position des Maximums" -#: libvips/freq_filt/fmaskcir.c:158 libvips/freq_filt/fmaskcir.c:303 -#: libvips/freq_filt/fmaskcir.c:394 libvips/freq_filt/fmaskcir.c:476 -#: libvips/freq_filt/fmaskcir.c:556 -msgid "bad sizes" -msgstr "falsche Größen" +#: libvips/mosaicing/mosaic1.c:613 libvips/mosaicing/mosaic.c:253 +#, fuzzy +msgid "Search band" +msgstr "falsche Bänder" -#: libvips/freq_filt/fmaskcir.c:172 libvips/freq_filt/fmaskcir.c:228 -#: libvips/freq_filt/fmaskcir.c:242 libvips/freq_filt/fmaskcir.c:317 -#: libvips/freq_filt/fmaskcir.c:321 libvips/freq_filt/fmaskcir.c:408 -#: libvips/freq_filt/fmaskcir.c:412 libvips/freq_filt/fmaskcir.c:570 -#: libvips/freq_filt/fmaskcir.c:574 libvips/freq_filt/fmask4th.c:120 -#: libvips/freq_filt/fmask4th.c:129 libvips/freq_filt/fmask4th.c:163 -#: libvips/freq_filt/fmask4th.c:172 libvips/freq_filt/fmask4th.c:205 -#: libvips/freq_filt/fmask4th.c:214 libvips/freq_filt/fmask4th.c:252 -#: libvips/freq_filt/fmask4th.c:261 libvips/freq_filt/fmask4th.c:292 -#: libvips/freq_filt/fmask4th.c:301 libvips/freq_filt/fmask4th.c:333 -#: libvips/freq_filt/fmask4th.c:342 libvips/freq_filt/fmask4th.c:373 -#: libvips/freq_filt/fmask4th.c:387 libvips/freq_filt/fmask4th.c:423 -#: libvips/freq_filt/fmask4th.c:437 libvips/freq_filt/fmask4th.c:473 -#: libvips/freq_filt/fmask4th.c:487 libvips/freq_filt/fmask4th.c:527 -#: libvips/freq_filt/fmask4th.c:541 libvips/freq_filt/fmask4th.c:578 -#: libvips/freq_filt/fmask4th.c:592 libvips/freq_filt/fmask4th.c:629 -#: libvips/freq_filt/fmask4th.c:643 libvips/freq_filt/fmask4th.c:697 -msgid "bad args" -msgstr "falsche Argumente" - -#: libvips/freq_filt/fmaskcir.c:490 -msgid "bad args (f)" -msgstr "falsche Argumente (f)" - -#: libvips/freq_filt/fmaskcir.c:494 -msgid "bad args (ac)" -msgstr "falsche Argumente (ac)" - -#: libvips/freq_filt/fmaskcir.c:655 libvips/freq_filt/fmask4th.c:791 -msgid "unimplemented mask" -msgstr "nicht implementierte Maske" +#: libvips/mosaicing/mosaic1.c:614 libvips/mosaicing/mosaic.c:254 +msgid "Band to search for features on" +msgstr "" -#: libvips/freq_filt/im_fractsurf.c:72 -msgid "dimension should be in (2,3)" -msgstr "Dimension sollte in (2,3) liegen" +#: libvips/mosaicing/mosaic.c:175 +#, fuzzy +msgid "mosaic two images" +msgstr "zwei Bilder subtrahieren" -#: libvips/freq_filt/im_invfft.c:105 libvips/freq_filt/im_invfftr.c:124 -#: libvips/freq_filt/im_fwfft.c:125 libvips/freq_filt/im_fwfft.c:241 -msgid "unable to create transform plan" -msgstr "Umwandlungsplan kann nicht erstellt werden" +#: libvips/mosaicing/mosaic.c:204 +msgid "xref" +msgstr "" -#: libvips/freq_filt/im_invfft.c:130 libvips/freq_filt/im_invfftr.c:145 -#: libvips/freq_filt/im_fwfft.c:301 -msgid "vips configured without FFT support" -msgstr "VIPS wurde ohne FFT-Unterstützung konfiguriert" +#: libvips/mosaicing/mosaic.c:205 libvips/mosaicing/mosaic.c:212 +msgid "Position of reference tie-point" +msgstr "" -#: libvips/histograms_lut/im_stdif.c:186 -#: libvips/histograms_lut/im_lhisteq.c:159 -msgid "window too large" -msgstr "Fenster zu groß" +#: libvips/mosaicing/mosaic.c:211 +msgid "yref" +msgstr "" -#: libvips/histograms_lut/im_stdif.c:191 -#: libvips/histograms_lut/im_lhisteq.c:164 -msgid "window too small" -msgstr "Fenster zu klein" +#: libvips/mosaicing/mosaic.c:218 +msgid "xsec" +msgstr "" -#: libvips/histograms_lut/im_histnD.c:227 -#, c-format -msgid " bins out of range [1,%d]" -msgstr " »bins« außerhalb des Bereichs [1,%d]" +#: libvips/mosaicing/mosaic.c:219 libvips/mosaicing/mosaic.c:226 +msgid "Position of secondary tie-point" +msgstr "" -#: libvips/histograms_lut/im_identity.c:139 libvips/other/im_grey.c:101 -#: libvips/other/im_make_xy.c:95 -msgid "bad size" -msgstr "falsche Größe" +#: libvips/mosaicing/mosaic.c:225 +msgid "ysec" +msgstr "" -#: libvips/histograms_lut/im_buildlut.c:120 -msgid "x value not an int" -msgstr "x-Wert keine Ganzzahl" +#: libvips/mosaicing/mosaic.c:260 libvips/mosaicing/mosaic.c:267 +msgid "Integer offset" +msgstr "" -#: libvips/histograms_lut/im_buildlut.c:133 -msgid "x range too small" -msgstr "x-Bereich zu klein" +#: libvips/mosaicing/mosaic.c:261 libvips/mosaicing/mosaic.c:268 +msgid "Detected integer offset" +msgstr "" -#: libvips/histograms_lut/im_buildlut.c:278 -msgid "bad input matrix size" -msgstr "falsche Eingabematrix-Größe" +#: libvips/mosaicing/mosaic.c:275 +msgid "Detected scale" +msgstr "" -#: libvips/histograms_lut/tone.c:194 -msgid "bad in_max, out_max parameters" -msgstr "falsche »in_max«-, »out_max«-Parameter" +#: libvips/mosaicing/mosaic.c:282 +msgid "Detected rotation" +msgstr "" -#: libvips/histograms_lut/tone.c:199 -msgid "bad Lb, Lw parameters" -msgstr "falsche »Lb«-, »Lw«-Parameter" +#: libvips/mosaicing/mosaic.c:288 libvips/mosaicing/mosaic.c:295 +msgid "First-order displacement" +msgstr "" -#: libvips/histograms_lut/tone.c:204 -msgid "Ps not in range [0.0,1.0]" -msgstr "»Ps« nicht im Bereich [0.0,1.0]" +#: libvips/mosaicing/mosaic.c:289 libvips/mosaicing/mosaic.c:296 +msgid "Detected first-order displacement" +msgstr "" -#: libvips/histograms_lut/tone.c:209 -msgid "Pm not in range [0.0,1.0]" -msgstr "»Pm« nicht im Bereich [0.0,1.0]" +#: libvips/mosaicing/remosaic.c:89 +#, c-format +msgid "file \"%s\" not found" +msgstr "Datei »%s« nicht gefunden" -#: libvips/histograms_lut/tone.c:214 -msgid "Ph not in range [0.0,1.0]" -msgstr "»Ph« nicht im Bereich [0.0,1.0]" +#: libvips/mosaicing/remosaic.c:117 +#, c-format +msgid "substitute image \"%s\" is not the same size as \"%s\"" +msgstr "Bild zum Ersetzen »%s« hat nicht die gleiche Größe wie »%s«" -#: libvips/histograms_lut/tone.c:219 -msgid "S not in range [-30,+30]" -msgstr "»S« nicht im Bereich [-30,+30]" +#: libvips/mosaicing/remosaic.c:160 +#, fuzzy +msgid "rebuild an mosaiced image" +msgstr "Bilddateien laden und speichern" -#: libvips/histograms_lut/tone.c:224 -msgid "M not in range [-30,+30]" -msgstr "»M« nicht im Bereich [-30,+30]" +#: libvips/mosaicing/remosaic.c:176 +msgid "old_str" +msgstr "" -#: libvips/histograms_lut/tone.c:229 -msgid "H not in range [-30,+30]" -msgstr "»H« nicht im Bereich [-30,+30]" +#: libvips/mosaicing/remosaic.c:177 +msgid "Search for this string" +msgstr "" -#: libvips/histograms_lut/im_invertlut.c:132 -msgid "element out of range [0,1]" -msgstr "Element außerhalb des Bereichs [0,1]" +#: libvips/mosaicing/remosaic.c:183 +msgid "new_str" +msgstr "" -#: libvips/histograms_lut/im_invertlut.c:287 -msgid "bad input matrix" -msgstr "falsche Eingabematrix" +#: libvips/mosaicing/remosaic.c:184 +msgid "And swap for this string" +msgstr "" -#: libvips/histograms_lut/im_invertlut.c:292 -msgid "bad lut_size" -msgstr "falsche »lut_size«" +#: libvips/resample/affine.c:516 +msgid "output coordinates out of range" +msgstr "Ausgabekoordinaten außerhalb des Bereichs" -#: libvips/histograms_lut/im_maplut.c:97 -#, c-format -msgid "%d overflows detected" -msgstr "%d Überläufe entdeckt" +#: libvips/resample/affine.c:640 +#, fuzzy +msgid "affine transform of an image" +msgstr "Band aus einem Bild extrahieren" -#: libvips/inplace/im_draw_line.c:389 -msgid "mask image not 1 band 8 bit uncoded" -msgstr "Maskenbild nicht 8-Bit-kodiert mit einem Band" +#: libvips/resample/affine.c:644 +msgid "Matrix" +msgstr "" -#: libvips/inplace/im_draw_line.c:395 -msgid "ink image does not match in image" -msgstr "»ink«-Bild passt nicht in das Bild" +#: libvips/resample/affine.c:645 +msgid "Transformation matrix" +msgstr "" -#: libvips/inplace/im_draw_line.c:399 -msgid "ink image not 1x1 pixels" -msgstr "»ink«-Bild nicht 1x1 Bildpunkte" +#: libvips/resample/affine.c:657 +#, fuzzy +msgid "Output rect" +msgstr "Ausgabe" -#: libvips/iofuncs/sink.c:105 -#, c-format -msgid "stop function failed for image \"%s\"" -msgstr "»stop«-Funktion für Bild »%s« fehlgeschlagen" +#: libvips/resample/affine.c:658 +msgid "Area of output to generate" +msgstr "" -#: libvips/iofuncs/sink.c:142 -#, c-format -msgid "start function failed for image \"%s\"" -msgstr "»start«-Funktion für Bild »%s« fehlgeschlagen" +#: libvips/resample/affine.c:664 libvips/resample/affine.c:671 +#: libvips/resample/similarity.c:140 libvips/resample/similarity.c:147 +#, fuzzy +msgid "Output offset" +msgstr "Ausgabewert" -#: libvips/iofuncs/sink.c:175 -msgid "per-thread state for sink" -msgstr "Status pro Thread für »sink«" +#: libvips/resample/affine.c:665 libvips/resample/similarity.c:141 +msgid "Horizontal output displacement" +msgstr "" -#: libvips/iofuncs/memory.c:231 -msgid "vips_free: too many frees" -msgstr "vips_free: zu viele Frees" +#: libvips/resample/affine.c:672 libvips/resample/similarity.c:148 +msgid "Vertical output displacement" +msgstr "" -#: libvips/iofuncs/memory.c:235 -msgid "vips_free: too much free" -msgstr "vips_free: zu viel frei" +#: libvips/resample/affine.c:678 libvips/resample/affine.c:685 +#: libvips/resample/resize.c:360 libvips/resample/resize.c:367 +#: libvips/resample/similarity.c:154 libvips/resample/similarity.c:161 +#, fuzzy +msgid "Input offset" +msgstr "Xoffset" -#: libvips/iofuncs/memory.c:295 libvips/iofuncs/memory.c:298 -#, c-format -msgid "out of memory --- size == %dMB" -msgstr "Hauptspeicher reicht nicht aus – Größe == %dMB" +#: libvips/resample/affine.c:679 libvips/resample/resize.c:361 +#: libvips/resample/similarity.c:155 +msgid "Horizontal input displacement" +msgstr "" -#: libvips/iofuncs/vips.c:286 -#, c-format -msgid "\"%s\" is not a VIPS image" -msgstr "»%s« ist kein VIPS-Bild" +#: libvips/resample/affine.c:686 libvips/resample/resize.c:368 +#: libvips/resample/similarity.c:162 +msgid "Vertical input displacement" +msgstr "" -#: libvips/iofuncs/vips.c:374 -msgid "unable to read history" -msgstr "Verlauf kann nicht gelesen werden" +#: libvips/resample/bicubic.cpp:629 +#, fuzzy +msgid "bicubic interpolation (Catmull-Rom)" +msgstr "doppelt kubische Interpolation (Catmull-Rom)" -#: libvips/iofuncs/vips.c:407 -msgid "more than a 10 megabytes of XML? sufferin' succotash!" -msgstr "mehr als 10 Megabyte XML? Leidende Succotash!" +#: libvips/resample/interpolate.c:185 +msgid "VIPS interpolators" +msgstr "VIPS-Interpolatoren" -#: libvips/iofuncs/vips.c:455 -msgid "incorrect namespace in XML" -msgstr "falscher Namensraum in XML" +#: libvips/resample/interpolate.c:361 +#, fuzzy +msgid "nearest-neighbour interpolation" +msgstr "Nächste-Nachbar-Interpolation" -#: libvips/iofuncs/vips.c:579 -msgid "error transforming from save format" -msgstr "Fehler beim Umwandeln vom gespeicherten Format" +#: libvips/resample/interpolate.c:579 +#, fuzzy +msgid "bilinear interpolation" +msgstr "Bilineare Interpolation" -#: libvips/iofuncs/vips.c:680 -#, c-format -msgid "unable to set property \"%s\" to value \"%s\"." -msgstr "Eigenschaft »%s« kann nicht auf Wert »%s« gesetzt werden." +#: libvips/resample/lbb.cpp:872 +#, fuzzy +msgid "reduced halo bicubic" +msgstr "doppelt kubische Halo-Reduzierung" -#: libvips/iofuncs/vips.c:728 -msgid "error transforming to save format" -msgstr "Fehler beim Umwandeln in das zu speichernde Format" +#: libvips/resample/mapim.c:551 +#, fuzzy +msgid "resample with a map image" +msgstr "ein Bild nachmachen" -#: libvips/iofuncs/vips.c:776 libvips/iofuncs/vips.c:973 -#: libvips/iofuncs/window.c:237 -msgid "file has been truncated" -msgstr "Datei wurde gekürzt" +#: libvips/resample/mapim.c:556 +msgid "Index pixels with this" +msgstr "" -#: libvips/iofuncs/vips.c:890 libvips/iofuncs/vips.c:899 -#: libvips/iofuncs/vips.c:922 -msgid "xml save error" -msgstr "XML-Fehler beim Speichern" +#: libvips/resample/nohalo.cpp:1551 +#, fuzzy +msgid "edge sharpening resampler with halo reduction" +msgstr "neues Kantenschärfungsmuster mit Halo-Reduzierung" -#: libvips/iofuncs/vips.c:959 -#, c-format -msgid "unable to read header for \"%s\"" -msgstr "Kopfdaten für »%s« können nicht gelesen werden" +#: libvips/resample/quadratic.c:269 +msgid "coefficient matrix must have width 2" +msgstr "" -#: libvips/iofuncs/vips.c:972 libvips/iofuncs/window.c:236 -#, c-format -msgid "unable to read data for \"%s\", %s" -msgstr "Daten für »%s« können nicht gelesen werden, %s" +#: libvips/resample/quadratic.c:291 +msgid "coefficient matrix must have height 1, 3, 4 or 6" +msgstr "" -#: libvips/iofuncs/vips.c:984 -#, c-format -msgid "error reading XML: %s" -msgstr "Fehler beim Lesen von XML: %s" +#: libvips/resample/quadratic.c:341 +msgid "resample an image with a quadratic transform" +msgstr "" -#: libvips/iofuncs/generate.c:343 libvips/iofuncs/header.c:611 -msgid "too many images" -msgstr "zu viele Bilder" +#: libvips/resample/quadratic.c:345 +msgid "Coeff" +msgstr "" -#: libvips/iofuncs/generate.c:606 -msgid "demand hint not set" -msgstr "Hinweisanfrage nicht gesetzt" +#: libvips/resample/quadratic.c:346 +msgid "Coefficient matrix" +msgstr "" -#: libvips/iofuncs/generate.c:625 libvips/iofuncs/generate.c:650 -msgid "generate() called twice" -msgstr "generate() zweimal aufgerufen" +#: libvips/resample/quadratic.c:352 +msgid "Interpolate values with this" +msgstr "" -#: libvips/iofuncs/generate.c:682 libvips/iofuncs/image.c:1873 -#, c-format -msgid "unable to output to a %s image" -msgstr "es kann nicht zu einem %s-Bild ausgegeben werden" +#: libvips/resample/reduce.c:199 +#, fuzzy +msgid "reduce an image" +msgstr "ein Bild nachmachen" -#: libvips/iofuncs/region.c:212 -#, c-format -msgid "start function failed for image %s" -msgstr "Startfunktion für Bild %s fehlgeschlagen" +#: libvips/resample/reduce.c:205 libvips/resample/reduceh.cpp:586 +#: libvips/resample/shrink.c:149 libvips/resample/shrinkh.c:353 +#, fuzzy +msgid "Hshrink" +msgstr "verkleinern" -#: libvips/iofuncs/region.c:528 libvips/iofuncs/region.c:598 -#: libvips/iofuncs/region.c:745 libvips/iofuncs/region.c:1241 -msgid "valid clipped to nothing" -msgstr "gültig an nichts angeklammert" +#: libvips/resample/reduce.c:206 libvips/resample/reduce.c:236 +#: libvips/resample/reduceh.cpp:587 libvips/resample/reduceh.cpp:610 +#: libvips/resample/shrink.c:150 libvips/resample/shrink.c:166 +#: libvips/resample/shrinkh.c:354 libvips/resample/shrinkh.c:370 +#, fuzzy +msgid "Horizontal shrink factor" +msgstr "falscher Schrumpffaktor %d" -#: libvips/iofuncs/region.c:642 -msgid "bad image type" -msgstr "falscher Bildtyp" +#: libvips/resample/reduce.c:212 libvips/resample/reducev.cpp:1070 +#: libvips/resample/shrink.c:142 libvips/resample/shrinkv.c:427 +#, fuzzy +msgid "Vshrink" +msgstr "verkleinern" -#: libvips/iofuncs/region.c:687 -msgid "no pixel data on attached image" -msgstr "keine Bildpunktdaten in angehängtem Bild" +#: libvips/resample/reduce.c:213 libvips/resample/reduce.c:243 +#: libvips/resample/reducev.cpp:1071 libvips/resample/reducev.cpp:1094 +#: libvips/resample/shrink.c:143 libvips/resample/shrink.c:173 +#: libvips/resample/shrinkv.c:428 libvips/resample/shrinkv.c:444 +#, fuzzy +msgid "Vertical shrink factor" +msgstr "falscher Schrumpffaktor %d" -#: libvips/iofuncs/region.c:693 -msgid "images do not match in pixel size" -msgstr "Bilder passen in der Bildpunktgröße nicht zusammen" +#: libvips/resample/reduce.c:219 libvips/resample/reduceh.cpp:593 +#: libvips/resample/reducev.cpp:1077 libvips/resample/resize.c:343 +msgid "Kernel" +msgstr "" -#: libvips/iofuncs/region.c:726 libvips/iofuncs/region.c:1223 -msgid "dest too small" -msgstr "Ziel zu klein" +#: libvips/resample/reduce.c:220 libvips/resample/reduceh.cpp:594 +#: libvips/resample/reducev.cpp:1078 libvips/resample/resize.c:344 +msgid "Resampling kernel" +msgstr "" -#: libvips/iofuncs/region.c:813 -msgid "bad position" -msgstr "falsche Position" +#: libvips/resample/reduce.c:226 libvips/resample/reduceh.cpp:600 +#: libvips/resample/reducev.cpp:1084 libvips/resample/resize.c:350 +msgid "Gap" +msgstr "" -#: libvips/iofuncs/region.c:1102 libvips/iofuncs/region.c:1294 -#, c-format -msgid "unable to input from a %s image" -msgstr "Eingabe von einem %s-Bild nicht möglich" +#: libvips/resample/reduce.c:227 libvips/resample/reduceh.cpp:601 +#: libvips/resample/reducev.cpp:1085 libvips/resample/resize.c:351 +msgid "Reducing gap" +msgstr "" -#: libvips/iofuncs/region.c:1126 -msgid "incomplete header" -msgstr "unvollständige Kopfzeilen" +#: libvips/resample/reduce.c:235 libvips/resample/reduceh.cpp:609 +#: libvips/resample/shrink.c:165 libvips/resample/shrinkh.c:369 +#, fuzzy +msgid "Xshrink" +msgstr "verkleinern" -#: libvips/iofuncs/region.c:1197 -msgid "inappropriate region type" -msgstr "Ungeeigneter Regionstyp" +#: libvips/resample/reduce.c:242 libvips/resample/reducev.cpp:1093 +#: libvips/resample/shrink.c:172 libvips/resample/shrinkv.c:443 +#, fuzzy +msgid "Yshrink" +msgstr "verkleinern" -#: libvips/iofuncs/init.c:366 -msgid "evaluate with N concurrent threads" -msgstr "mit N gleichzeitigen Threads auswerten" +#: libvips/resample/reduce.c:251 libvips/resample/reduceh.cpp:618 +#: libvips/resample/reducev.cpp:1102 libvips/resample/resize.c:384 +msgid "Centre" +msgstr "" -#: libvips/iofuncs/init.c:369 -msgid "set tile width to N (DEBUG)" -msgstr "Bildbreite auf N setzen (DEBUG)" +#: libvips/resample/reduce.c:252 libvips/resample/reduceh.cpp:619 +#: libvips/resample/reducev.cpp:1103 libvips/resample/resize.c:385 +msgid "Use centre sampling convention" +msgstr "" -#: libvips/iofuncs/init.c:372 -msgid "set tile height to N (DEBUG)" -msgstr "Bildhöhe auf N setzen (DEBUG)" +#: libvips/resample/reduceh.cpp:414 libvips/resample/reducev.cpp:848 +#, fuzzy +msgid "reduce factor should be >= 1.0" +msgstr "Schrumpffaktoren sollten >=1 sein" -#: libvips/iofuncs/init.c:375 -msgid "set thinstrip height to N (DEBUG)" -msgstr "»thinstrip«-Höhe auf N setzen (DEBUG)" +#: libvips/resample/reduceh.cpp:437 libvips/resample/reducev.cpp:870 +#, fuzzy +msgid "reduce gap should be >= 1.0" +msgstr "Schrumpffaktoren sollten >=1 sein" -#: libvips/iofuncs/init.c:378 -msgid "set fatstrip height to N (DEBUG)" -msgstr "»fatstrip«-Höhe auf N setzen (DEBUG)" +#: libvips/resample/reduceh.cpp:467 libvips/resample/reducev.cpp:900 +#, fuzzy +msgid "reduce factor too large" +msgstr "Zoomfaktoren zu groß" -#: libvips/iofuncs/init.c:381 -msgid "show progress feedback" -msgstr "Fortschrittsrückmeldung anzeigen" +#: libvips/resample/reduceh.cpp:580 libvips/resample/shrinkh.c:347 +#, fuzzy +msgid "shrink an image horizontally" +msgstr "horizontal so oft wiederholen" -#: libvips/iofuncs/init.c:384 -msgid "leak-check on exit" -msgstr "Lückenprüfung beim Beenden" +#: libvips/resample/reducev.cpp:1064 libvips/resample/shrinkv.c:421 +#, fuzzy +msgid "shrink an image vertically" +msgstr "vertikal so oft wiederholen" -#: libvips/iofuncs/init.c:387 -msgid "images larger than N are decompressed to disc" -msgstr "Bilder, die größer als N sind, werden auf die Platte dekomprimiert" +#: libvips/resample/resample.c:136 +#, fuzzy +msgid "resample operations" +msgstr "arithmetische Transaktionen" -#: libvips/iofuncs/init.c:390 -msgid "disable vectorised versions of operations" -msgstr "vektorgesteuerte Versionen von Transaktionen deaktivieren" +#: libvips/resample/resize.c:323 +#, fuzzy +msgid "resize an image" +msgstr "ein Bild nachmachen" -#: libvips/iofuncs/init.c:393 -msgid "cache at most N operations" -msgstr "höchstens N Transaktionen zwischenspeichern" +#: libvips/resample/resize.c:329 +#, fuzzy +msgid "Scale factor" +msgstr "Q-Faktor" -#: libvips/iofuncs/init.c:396 -msgid "cache at most N bytes in memory" -msgstr "höchstens N Byte zwischenspeichern" +#: libvips/resample/resize.c:330 +msgid "Scale image by this factor" +msgstr "" -#: libvips/iofuncs/init.c:399 -msgid "allow at most N open files" -msgstr "höchstens N offene Dateien erlauben" +#: libvips/resample/resize.c:336 +#, fuzzy +msgid "Vertical scale factor" +msgstr "vertikaler Versatz vom Ursprung" -#: libvips/iofuncs/init.c:402 -msgid "trace operation cache" -msgstr "Transaktionszwischenspeicher aufzeichnen" +#: libvips/resample/resize.c:337 +msgid "Vertical scale image by this factor" +msgstr "" -#: libvips/iofuncs/init.c:405 -msgid "dump operation cache on exit" -msgstr "Transaktionszwischenspeicher beim Beenden ausgeben" +#: libvips/resample/shrink.c:133 +#, fuzzy +msgid "shrink an image" +msgstr "ein Bild invertieren" -#: libvips/iofuncs/init.c:428 -msgid "VIPS Options" -msgstr "VIPS-Optionen" +#: libvips/resample/shrink.c:156 libvips/resample/shrinkh.c:360 +#: libvips/resample/shrinkv.c:434 +msgid "Ceil" +msgstr "" -#: libvips/iofuncs/init.c:428 -msgid "Show VIPS options" -msgstr "VIPS-Optionen anzeigen" +#: libvips/resample/shrink.c:157 libvips/resample/shrinkh.c:361 +#: libvips/resample/shrinkv.c:435 +#, fuzzy +msgid "Round-up output dimensions" +msgstr "falsche Abmessungen" -#: libvips/iofuncs/image.c:293 -msgid "unable to close fd" -msgstr "»fd« kann nicht geschlossen werden" +#: libvips/resample/shrinkh.c:283 libvips/resample/shrinkv.c:327 +msgid "shrink factors should be >= 1" +msgstr "Schrumpffaktoren sollten >=1 sein" -#: libvips/iofuncs/image.c:373 -#, c-format -msgid "%dx%d %s, %d band, %s" -msgid_plural "%dx%d %s, %d bands, %s" -msgstr[0] "%dx%d %s, %d Band, %s" -msgstr[1] "%dx%d %s, %d Bänder, %s" +#: libvips/resample/similarity.c:123 +msgid "base similarity transform" +msgstr "" -#: libvips/iofuncs/image.c:403 -#, c-format -msgid " %s, %d band, %s" -msgid_plural " %s, %d bands, %s" -msgstr[0] " %s, %d band, %s" -msgstr[1] " %s, %d Bänder, %s" +#: libvips/resample/similarity.c:197 +msgid "similarity transform of an image" +msgstr "" -#: libvips/iofuncs/image.c:529 -#, c-format -msgid "%s %s: %d threads, %d x %d tiles, groups of %d scanlines" -msgstr "%s %s: %d Threads, %d x %d Kacheln, Gruppen von %d Scan-Zeilen" +#: libvips/resample/similarity.c:201 +msgid "Scale by this factor" +msgstr "" -#: libvips/iofuncs/image.c:542 -#, c-format -msgid "%s %s: %d%% complete" -msgstr "%s %s: %d%% komplett" +#: libvips/resample/similarity.c:208 libvips/resample/similarity.c:277 +msgid "Rotate clockwise by this many degrees" +msgstr "" -#. Spaces at end help to erase the %complete message we overwrite. -#. -#: libvips/iofuncs/image.c:559 -#, c-format -msgid "%s %s: done in %ds \n" -msgstr "%s %s: Erledigt in %ds \n" +#: libvips/resample/similarity.c:273 +#, fuzzy +msgid "rotate an image by a number of degrees" +msgstr "Tangens des Bildes (Winkel in Grad)" -#: libvips/iofuncs/image.c:738 -#, c-format -msgid "unable to open \"%s\", file too short" -msgstr "»%s« kann nicht geöffnet werden, Datei zu klein" +#: libvips/resample/thumbnail.c:959 +#, fuzzy +msgid "thumbnail generation" +msgstr "- Miniaturansichten-Generator" -#: libvips/iofuncs/image.c:748 -#, c-format -msgid "%s is longer than expected" -msgstr "%s ist länger als erwartet" +#: libvips/resample/thumbnail.c:974 +#, fuzzy +msgid "Target width" +msgstr "Kachelbreite" -#: libvips/iofuncs/image.c:765 -#, c-format -msgid "bad mode \"%s\"" -msgstr "falscher Modus »%s«" +#: libvips/resample/thumbnail.c:975 +msgid "Size to this width" +msgstr "" -#: libvips/iofuncs/image.c:820 -msgid "image class" -msgstr "Bildklasse" +#: libvips/resample/thumbnail.c:981 +#, fuzzy +msgid "Target height" +msgstr "Kachelhöhe" -#: libvips/iofuncs/image.c:916 -msgid "Image filename" -msgstr "Bilddateiname" +#: libvips/resample/thumbnail.c:982 +#, fuzzy +msgid "Size to this height" +msgstr "Kachelhöhe" -#: libvips/iofuncs/image.c:922 -msgid "Mode" -msgstr "Modus" +#: libvips/resample/thumbnail.c:989 +msgid "Only upsize, only downsize, or both" +msgstr "" -#: libvips/iofuncs/image.c:923 -msgid "Open mode" -msgstr "Öffnen-Modus" +#: libvips/resample/thumbnail.c:995 +msgid "No rotate" +msgstr "" -#: libvips/iofuncs/image.c:929 -msgid "Kill" -msgstr "töten" +#: libvips/resample/thumbnail.c:996 +msgid "Don't use orientation tags to rotate image upright" +msgstr "" -#: libvips/iofuncs/image.c:930 -msgid "Block evaluation on this image" -msgstr "Blockauswertung dieses Bildes" +#: libvips/resample/thumbnail.c:1002 +msgid "Crop" +msgstr "" -#: libvips/iofuncs/image.c:936 -msgid "Demand style" -msgstr "Nachfragestil" +#: libvips/resample/thumbnail.c:1003 +msgid "Reduce to fill target rectangle, then crop" +msgstr "" -#: libvips/iofuncs/image.c:937 -msgid "Preferred demand style for this image" -msgstr "für dieses Bild bevorzugter Nachfragestil" +#: libvips/resample/thumbnail.c:1009 +#, fuzzy +msgid "Linear" +msgstr "Zeilen" -#: libvips/iofuncs/image.c:950 -msgid "Foreign buffer" -msgstr "Fremdpuffer" +#: libvips/resample/thumbnail.c:1010 +msgid "Reduce in linear light" +msgstr "" -#: libvips/iofuncs/image.c:951 -msgid "Pointer to foreign pixels" -msgstr "Puffer für fremde Bildpunkte" +#: libvips/resample/thumbnail.c:1016 +#, fuzzy +msgid "Import profile" +msgstr "Profil" -#: libvips/iofuncs/image.c:1215 -#, c-format -msgid "killed for image \"%s\"" -msgstr "für Bild »%s« abgeschossen" +#: libvips/resample/thumbnail.c:1017 +msgid "Fallback import profile" +msgstr "" -#: libvips/iofuncs/image.c:1815 -msgid "bad image descriptor" -msgstr "falscher Bild-Deskriptor" +#: libvips/resample/thumbnail.c:1023 +#, fuzzy +msgid "Export profile" +msgstr "Profil" -#: libvips/iofuncs/image.c:1917 -#, c-format -msgid "auto-rewind for %s failed" -msgstr "automatischer Rücklauf für %s fehlgeschlagen" +#: libvips/resample/thumbnail.c:1024 +msgid "Fallback export profile" +msgstr "" -#: libvips/iofuncs/image.c:1973 libvips/iofuncs/image.c:2168 -#: libvips/iofuncs/image.c:2185 -msgid "no image data" -msgstr "keine Bilddaten" +#: libvips/resample/thumbnail.c:1050 +#, fuzzy +msgid "Auto rotate" +msgstr "Winkel zum Drehen eines Bildes" -#: libvips/iofuncs/image.c:2041 libvips/iofuncs/image.c:2208 -msgid "image not readable" -msgstr "Bild nicht lesbar" +#: libvips/resample/thumbnail.c:1051 +msgid "Use orientation tags to rotate image upright" +msgstr "" -#: libvips/iofuncs/image.c:2062 libvips/iofuncs/image.c:2238 -#: libvips/iofuncs/image.c:2247 -msgid "image already written" -msgstr "Bild bereits geschrieben" +# http://www.dateiendung.com/format/mat +#: libvips/resample/thumbnail.c:1192 +#, fuzzy +msgid "generate thumbnail from file" +msgstr "Mat aus Datei laden" -#: libvips/iofuncs/image.c:2086 libvips/iofuncs/image.c:2259 -msgid "image not writeable" -msgstr "Bild nicht schreibbar" +#: libvips/resample/thumbnail.c:1199 +#, fuzzy +msgid "Filename to read from" +msgstr "Name der Datei, aus der geladen werden soll" -#: libvips/iofuncs/image.c:2132 -msgid "bad file type" -msgstr "falscher Dateityp" +#: libvips/resample/thumbnail.c:1439 +msgid "generate thumbnail from buffer" +msgstr "" -#: libvips/iofuncs/sinkscreen.c:185 -msgid "per-thread state for render" -msgstr "Status pro Thread für »render«" +#: libvips/resample/thumbnail.c:1452 libvips/resample/thumbnail.c:1665 +#, fuzzy +msgid "Extra options" +msgstr "unäre Transaktionen" -#: libvips/iofuncs/sinkscreen.c:537 libvips/iofuncs/sinkdisc.c:236 -#: libvips/iofuncs/threadpool.c:606 -msgid "unable to create thread" -msgstr "Thread kann nicht erstellt werden" +#: libvips/resample/thumbnail.c:1453 libvips/resample/thumbnail.c:1666 +msgid "Options that are passed on to the underlying loader" +msgstr "" -#: libvips/iofuncs/mapfile.c:130 libvips/iofuncs/mapfile.c:297 -msgid "unable to CreateFileMapping" -msgstr "»CreateFileMapping« nicht möglich" +#: libvips/resample/thumbnail.c:1652 +msgid "generate thumbnail from source" +msgstr "" -#: libvips/iofuncs/mapfile.c:138 libvips/iofuncs/mapfile.c:309 -msgid "unable to MapViewOfFile" -msgstr "»MapViewOfFile« nicht möglich" +#: libvips/resample/thumbnail.c:1776 +#, fuzzy +msgid "generate thumbnail from image" +msgstr "Band aus einem Bild extrahieren" -#: libvips/iofuncs/mapfile.c:178 -msgid "unable to mmap" -msgstr "»mmap« nicht möglich" +#: libvips/resample/vsqbs.cpp:378 +msgid "B-Splines with antialiasing smoothing" +msgstr "B-Splines mit Kantenglättung" -#: libvips/iofuncs/mapfile.c:179 +#: tools/vips.c:166 #, c-format -msgid "" -"map failed (%s), running very low on system resources, expect a crash soon" +msgid "'%s' is not the name of a vips class" msgstr "" -"»map« fehlgeschlagen (%s), die Systemressourcen werden knapp, ein Absturz " -"steht bevor" -#: libvips/iofuncs/mapfile.c:196 libvips/iofuncs/mapfile.c:303 -msgid "unable to UnmapViewOfFile" -msgstr "»UnmapViewOfFile« nicht möglich" +#: tools/vips.c:282 +#, fuzzy, c-format +msgid "'%s' is not the name of a vips operation" +msgstr "genannte VIPS-Transaktion ausführen" -#: libvips/iofuncs/mapfile.c:202 -msgid "unable to munmap file" -msgstr "»munmap« der Datei nicht möglich" +#: tools/vips.c:355 +#, c-format +msgid "no package or function \"%s\"" +msgstr "kein Paket oder Funktion »%s«" -#: libvips/iofuncs/mapfile.c:224 -msgid "file is less than 64 bytes" -msgstr "Datei ist weniger als 64 Byte groß" +#: tools/vips.c:584 +#, fuzzy +msgid "execute vips operation OPER" +msgstr "genannte VIPS-Transaktion ausführen" -#: libvips/iofuncs/mapfile.c:229 libvips/iofuncs/mapfile.c:263 -msgid "unable to get file status" -msgstr "Dateistatus kann nicht abgefragt werden" +#: tools/vips.c:627 +#, fuzzy +msgid "Operation help" +msgstr "Transaktion" -#: libvips/iofuncs/mapfile.c:235 -msgid "not a regular file" -msgstr "keine reguläre Datei" +#: tools/vips.c:706 +msgid "[ACTION] [OPTIONS] [PARAMETERS] - VIPS driver program" +msgstr "[AKTION] [OPTIONEN] [PARAMETER] - VIPS-Treiberprogramm" -#: libvips/iofuncs/mapfile.c:269 -msgid "unable to read data" -msgstr "Daten können nicht gelesen werden" +#: tools/vips.c:916 +#, c-format +msgid "unknown action \"%s\"" +msgstr "unbekannte Aktion »%s«" -#: libvips/iofuncs/mapfile.c:329 +#: tools/vipsedit.c:129 #, c-format -msgid "unable to mmap: \"%s\" - %s" -msgstr "»mmap« nicht möglich: \"%s\" - %s" +msgid "'%s' is not a positive integer" +msgstr "»%s« ist keine positive Ganzzahl" + +#: tools/vipsedit.c:142 +msgid "unable to start VIPS" +msgstr "VIPS kann nicht gestartet werden" + +#: tools/vipsedit.c:165 +#, fuzzy +msgid "vipsedit - edit vips file header" +msgstr "»vipsfile« - »vipsfile«-Kopfzeilen bearbeiten" + +#: tools/vipsedit.c:193 +#, fuzzy, c-format +msgid "usage: %s [OPTION...] vips-file\n" +msgstr "Aufruf: %s [OPTION …] vipsfile\n" -#: libvips/iofuncs/mapfile.c:339 +#: tools/vipsedit.c:200 #, c-format -msgid "unable to mmap \"%s\" to same address" -msgstr "»mmap %s« zur gleichen Adresse nicht möglich" +msgid "could not open image %s" +msgstr "Bild %s konnte nicht geöffnet werden" -#: libvips/iofuncs/base64.c:170 -msgid "too little data" -msgstr "zu wenige Daten" +#: tools/vipsedit.c:206 +#, c-format +msgid "could not read VIPS header for %s" +msgstr "VIPS-Kopfzeilen für %s konnten nicht gelesen werden" -#: libvips/iofuncs/object.c:148 +#: tools/vipsedit.c:216 #, c-format -msgid "parameter %s not set" -msgstr "Parameter %s nicht gesetzt" +msgid "bad endian-ness %s, should be 'big' or 'little'" +msgstr "falsche Byte-Reihenfolge %s, sollte »big« oder »little« sein" -#: libvips/iofuncs/object.c:505 +#: tools/vipsedit.c:230 #, c-format -msgid "no property named `%s'" -msgstr "keine Eigenschaft namens »%s«" +msgid "bad format %s" +msgstr "falsches Format %s" -#: libvips/iofuncs/object.c:513 +#: tools/vipsedit.c:244 #, c-format -msgid "no vips argument named `%s'" -msgstr "kein VIPS-Argument namens »%s«" +msgid "bad interpretation %s" +msgstr "falsche Interpretation »%s« " -#: libvips/iofuncs/object.c:520 +#: tools/vipsedit.c:254 #, c-format -msgid "argument `%s' has no instance" -msgstr "Argument »%s« hat keine Instanz" +msgid "bad coding %s" +msgstr "falsche Kodierung %s" -#: libvips/iofuncs/object.c:1248 libvips/iofuncs/operation.c:287 -#: libvips/resample/interpolate.c:615 +#: tools/vipsedit.c:268 #, c-format -msgid "class \"%s\" not found" -msgstr "Klasse »%s« nicht gefunden" +msgid "could not seek on %s" +msgstr "auf %s konnte nicht gesucht werden" -#: libvips/iofuncs/object.c:1297 -msgid "base class" -msgstr "Basisklasse" +#: tools/vipsedit.c:271 +#, c-format +msgid "could not write to %s" +msgstr "auf %s konnte nicht geschrieben werden" -#: libvips/iofuncs/object.c:1311 -msgid "Nickname" -msgstr "Nickname" +#: tools/vipsedit.c:278 +msgid "could not get ext data" +msgstr "zusätzliche Daten konnten nicht abgefragt werden" -#: libvips/iofuncs/object.c:1312 -msgid "Class nickname" -msgstr "Klassen-Nickname" +#: tools/vipsedit.c:287 +msgid "could not set extension" +msgstr "Erweiterung konnte nicht gesetzt werden" -#: libvips/iofuncs/object.c:1318 -msgid "Description" -msgstr "Beschreibung" +#: tools/vipsheader.c:221 +msgid "- print image header" +msgstr "- Bild-Kopfzeilen ausgeben" -#: libvips/iofuncs/object.c:1319 -msgid "Class description" -msgstr "Klassenbeschreibung" +#: tools/vipsthumbnail.c:447 +#, fuzzy +msgid "bad geometry spec" +msgstr "falsche Gittergeometrie" -#: libvips/iofuncs/object.c:1509 -#, c-format -msgid "enum '%s' has no member '%s'" -msgstr "Aufzählung »%s« hat keinen Bestandteil »%s«" +#: tools/vipsthumbnail.c:516 +msgid "- thumbnail generator" +msgstr "- Miniaturansichten-Generator" -#: libvips/iofuncs/object.c:1769 -#, c-format -msgid "unable to set '%s'" -msgstr "»%s« kann nicht gesetzt werden" +#~ msgid "coords outside image" +#~ msgstr "Koordinaten außerhalb des Bildes" -#: libvips/iofuncs/object.c:1777 -msgid "not , or ) after parameter" -msgstr "kein »,« oder »)« nach Parameter" +#~ msgid "absolute value" +#~ msgstr "absoluter Wert" -#: libvips/iofuncs/object.c:1784 -msgid "extra tokens after ')'" -msgstr "keine zusätzlichen Token nach »)«" +#~ msgid "average value of image" +#~ msgstr "Durchschnittswert des Bildes" -#. File length unit. -#. -#: libvips/iofuncs/buf.c:520 -msgid "bytes" -msgstr "Byte" - -#. Kilo byte unit. -#. -#: libvips/iofuncs/buf.c:524 -msgid "KB" -msgstr "KB" - -#. Mega byte unit. -#. -#: libvips/iofuncs/buf.c:528 -msgid "MB" -msgstr "MB" - -#. Giga byte unit. -#. -#: libvips/iofuncs/buf.c:532 -msgid "GB" -msgstr "GB" +# im_exptra() transforms element x of input to +# pow(e, x) in output. +#~ msgid "10^pel of image" +#~ msgstr "10^pel des Bildes" -#. Tera byte unit. -#. -#: libvips/iofuncs/buf.c:536 -msgid "TB" -msgstr "TB" +#~ msgid "e^pel of image" +#~ msgstr "e^pel des Bildes" -#: libvips/iofuncs/util.c:639 -msgid "unable to get file stats" -msgstr "Dateistatus kann nicht abgefragt werden" +#~ msgid "x^pel of image" +#~ msgstr "x^pel des Bildes" -#: libvips/iofuncs/util.c:656 libvips/iofuncs/sinkdisc.c:262 -msgid "write failed" -msgstr "Schreiben fehlgeschlagen" +#~ msgid "[x,y,z]^pel of image" +#~ msgstr "[x,y,z]^pel des Bildes" -#: libvips/iofuncs/util.c:720 -#, c-format -msgid "unable to open file \"%s\" for reading" -msgstr "Datei »%s« kann nicht zum Lesen geöffnet werden" +#~ msgid "photographic negative" +#~ msgstr "Fotonegativ" -#: libvips/iofuncs/util.c:742 -#, c-format -msgid "unable to open file \"%s\" for writing" -msgstr "Datei »%s« kann nicht zum Schreiben geöffnet werden" +#~ msgid "calculate a*in + b = outfile" +#~ msgstr "Berechnen von a*in + b = Ausgabedatei" -#: libvips/iofuncs/util.c:767 -#, c-format -msgid "\"%s\" too long" -msgstr "»%s« zu lang" +#~ msgid "vectors not equal length" +#~ msgstr "Vektoren ungleicher Länge" -#: libvips/iofuncs/util.c:784 -msgid "out of memory" -msgstr "Hauptspeicher reicht nicht aus" +#~ msgid "calculate a*in + b -> out, a and b vectors" +#~ msgstr "Berechnen von a*in + b -> out, a und b Vektoren" -#: libvips/iofuncs/util.c:810 -#, c-format -msgid "error reading from file \"%s\"" -msgstr "Fehler beim Lesen von Datei »%s«" +#~ msgid "log10 of image" +#~ msgstr "log10 des Bildes" -#: libvips/iofuncs/util.c:857 -#, c-format -msgid "write error (%zd out of %zd blocks written) ... disc full?" -msgstr "Schreibfehler (%zd aus %zd Blöcken geschrieben) … Platte voll?" +#~ msgid "atan of image (result in degrees)" +#~ msgstr "Arkustangens des Bildes (Ergebnis in Grad)" + +#~ msgid "cos of image (angles in degrees)" +#~ msgstr "Kosinus des Bildes (Winkel in Grad)" + +#~ msgid "acos of image (result in degrees)" +#~ msgstr "Arkuskosinus des Bildes (Ergebnis in Grad)" + +# hinter diesem String folgt ein Flag. +#~ msgid "round to smallest integer value not less than" +#~ msgstr "auf kleinsten ganzzahligen Wert runden, nicht weniger als" + +# hinter diesem String folgt ein Flag. +#~ msgid "round to largest integer value not greater than" +#~ msgstr "auf größten ganzzahligen Wert runden, nicht größer als" + +# hinter diesem String folgt ein Flag. +#~ msgid "round to nearest integer value" +#~ msgstr "auf nächsten ganzzahligen Wert runden" + +#~ msgid "sin of image (angles in degrees)" +#~ msgstr "Sinus des Bildes (Winkel in Grad)" + +#~ msgid "average image bands" +#~ msgstr "durchschnittliche Bildbänder" + +#~ msgid "unit vector in direction of value" +#~ msgstr "Einheitsvektor in Richtung des Wertes" + +#~ msgid "asin of image (result in degrees)" +#~ msgstr "Arkussinus des Bildes (Ergebnis in Grad)" + +#~ msgid "position of maximum value of image, averaging in case of draw" +#~ msgstr "" +#~ "Position des Maximalwerts des Bildes, durchschnittlich im Fall des " +#~ "Zeichnens" + +#~ msgid "position and value of n maxima of image" +#~ msgstr "Position und Wert von n Maxima des Bildes" -#: libvips/iofuncs/util.c:1106 libvips/iofuncs/util.c:1113 -msgid "unable to truncate" -msgstr "kann nicht gekürzt werden" +#~ msgid "position and value of n minima of image" +#~ msgstr "Position und Wert von n Minima des Bildes" -#: libvips/iofuncs/util.c:1297 -msgid "unexpected end of string" -msgstr "Unerwartetes Ende der Zeichenkette" +#~ msgid "measure averages of a grid of patches" +#~ msgstr "Durchschnittsmaße eine Gitters aus Flickstücken" -#: libvips/iofuncs/util.c:1315 -#, c-format -msgid "expected %s, saw %s" -msgstr "%s erwartet, %s gesehen" +#~ msgid "remainder after integer division by a constant" +#~ msgstr "Rest nach Ganzzahldivision durch eine Konstante" -#: libvips/iofuncs/util.c:1485 -#, c-format -msgid "unable to make temporary file %s" -msgstr "temporäre Datei %s kann nicht erstellt werden" +#~ msgid "remainder after integer division by a vector of constants" +#~ msgstr "Rest nach Ganzzahldivision durch einen Vektor von Konstanten" -#: libvips/iofuncs/operation.c:97 -msgid "input" -msgstr "Eingabe" +#~ msgid "pel^x of image" +#~ msgstr "pel^x des Bildes" -#: libvips/iofuncs/operation.c:97 -msgid "output" -msgstr "Ausgabe" +#~ msgid "pel^[x,y,z] of image" +#~ msgstr "pel^[x,y,z] des Bildes" -#: libvips/iofuncs/operation.c:246 -msgid "operations" -msgstr "Transaktionen" +#~ msgid "many image statistics in one pass" +#~ msgstr "viele Bildstatistiken in einem Durchgang" -#: libvips/iofuncs/operation.c:273 -msgid "usage:" -msgstr "Aufruf:" +#~ msgid "pixelwise linear regression" +#~ msgstr "bildpunktweise lineare Regression" -#: libvips/iofuncs/operation.c:699 -#, c-format -msgid "unknown argument '%s'" -msgstr "unbekanntes Argument »%s«" +#~ msgid "phase of cross power spectrum of two complex images" +#~ msgstr "Phase des Kreuzleistungsspektrums zweier komplexer Bilder" -#: libvips/iofuncs/operation.c:810 -msgid "too few arguments" -msgstr "zu wenige Argumente" +#~ msgid "single band images only" +#~ msgstr "nur Einzelbandbilder" -#: libvips/iofuncs/operation.c:931 -msgid "too many arguments" -msgstr "zu viele Argumente" +#~ msgid "uncoded images only" +#~ msgstr "nur unkodierte Bilder" -#: libvips/iofuncs/header.c:210 -#, c-format -msgid "unknown band format %d" -msgstr "unbekanntes Bandformat %d" +#~ msgid "pow( left, right)" +#~ msgstr "pow( links, rechts)" -#: libvips/iofuncs/header.c:781 -#, c-format -msgid "field \"%s\" not found" -msgstr "Feld »%s« nicht gefunden" +#~ msgid "pow( @in, @c )" +#~ msgstr "pow( @in, @c )" -#: libvips/iofuncs/header.c:949 #, c-format -msgid "field \"%s\" is of type %s, not %s" -msgstr "Feld »%s« ist vom Typ %s, nicht %s" +#~ msgid "" +#~ "intent %d (%s) not supported by profile \"%s\"; falling back to default " +#~ "intent (usually PERCEPTUAL)" +#~ msgstr "" +#~ "Ziel-%d (%s) nicht von Profil »%s« unterstützt; Rückfall auf " +#~ "Standardabsicht (normalerweise WAHRNEHMUNG)" -#: libvips/iofuncs/sinkmemory.c:108 -msgid "per-thread state for sinkmemory" -msgstr "Status pro Thread für »sinkmemory«" - -#: libvips/iofuncs/sinkdisc.c:121 -msgid "per-thread state for sinkdisc" -msgstr "Status pro Thread für »sinkdisc«" +#~ msgid "CMYK input profile needs a 4 band input image" +#~ msgstr "CMYK-Eingabeprofil benötigt ein Eingabebild mit vier Bändern" -#: libvips/iofuncs/error.c:210 -msgid "windows error" -msgstr "Windows-Fehler" +#~ msgid "RGB input profile needs a 3 band input image" +#~ msgstr "RGB-Eingabeprofil benötigt ein Eingabebild mit drei Bändern" -#: libvips/iofuncs/error.c:219 -msgid "unix error" -msgstr "Unix-Fehler" +#~ msgid "uchar or ushort input only" +#~ msgstr "nur »uchar« oder »ushort«-Eingabe" -#: libvips/iofuncs/error.c:304 libvips/iofuncs/error.c:305 -#: libvips/iofuncs/error.c:354 libvips/iofuncs/error.c:355 #, c-format -msgid "%s: " -msgstr "%s: " +#~ msgid "" +#~ "intent %d (%s) not supported by profile; falling back to default intent " +#~ "(usually PERCEPTUAL)" +#~ msgstr "" +#~ "Ziel-%d (%s) nicht vom Profil unterstützt; Rückfall auf Standardabsicht " +#~ "(normalerweise WAHRNEHMUNG)" -#: libvips/iofuncs/error.c:304 -msgid "vips diagnostic" -msgstr "Vips-Diagnose" +#~ msgid "CMYK profile needs a 4 band input image" +#~ msgstr "CMYK-Profil benötigt ein Eingabebild mit vier Bändern" -#: libvips/iofuncs/error.c:354 -msgid "vips warning" -msgstr "Vips-Warnung" +#~ msgid "RGB profile needs a 3 band input image" +#~ msgstr "RGB-Profil benötigt ein Eingabebild mit drei Bändern" -#: libvips/iofuncs/error.c:438 -msgid "image must be uncoded" -msgstr "Bild muss unkodiert sein" +#~ msgid "lcms library not linked to this VIPS" +#~ msgstr "gegen die »lcms«-Bibliothek wird in diesem VIPS nicht verlinkt" -#: libvips/iofuncs/error.c:466 -msgid "image coding must be NONE or LABQ" -msgstr "Bildkodierung muss NONE oder LABQ sein" +#~ msgid "lmcs library not linked to this VIPS" +#~ msgstr "gegen die »lmcs«-Bibliothek wird in diesem VIPS nicht verlinkt" -#: libvips/iofuncs/error.c:494 -msgid "unknown image coding" -msgstr "unbekannte Bildkodierung" +#~ msgid "out of range [0,255]" +#~ msgstr "außerhalb des Bereichs [0,255]" -#: libvips/iofuncs/error.c:520 -msgid "Radiance coding only" -msgstr "Nur Radiance-Kodierung" +#~ msgid "bad display type" +#~ msgstr "falsche Anzeigetyp" -#: libvips/iofuncs/error.c:546 -msgid "LABQ coding only" -msgstr "Nur LABQ-Kodierung" +#~ msgid "display unknown" +#~ msgstr "Anzeige unbekannt" -#: libvips/iofuncs/error.c:570 -msgid "image must one band" -msgstr "Bild muss ein Band haben" +#~ msgid "input not 3-band uncoded char" +#~ msgstr "Eingabe ist kein unkodiertes Zeichen mit drei Bändern" -#: libvips/iofuncs/error.c:595 -#, c-format -msgid "image must have %d bands" -msgstr "Bild muss %d Bänder haben" +#~ msgid "3-band uncoded float only" +#~ msgstr "nur unkodierte Fließkommazahlen mit drei Bändern" -#: libvips/iofuncs/error.c:620 -msgid "image must have one or three bands" -msgstr "Bild muss ein oder drei Bänder haben" +#~ msgid "bad greyscale mask size" +#~ msgstr "falsche Grauskala-Maskengröße" -#: libvips/iofuncs/error.c:648 -msgid "images must have the same number of bands, or one must be single-band" -msgstr "" -"Bilder müssen die gleiche Anzahl Bänder haben oder eines muss ein Band haben" +#, c-format +#~ msgid "bad greyscale mask value, row %d" +#~ msgstr "falscher Grauskala-Maskenwert, Reihe %d" -#: libvips/iofuncs/error.c:675 #, c-format -msgid "image must have 1 or %d bands" -msgstr "Bild muss ein oder %d Bänder haben" +#~ msgid "%d underflows and %d overflows detected" +#~ msgstr "%d Unter- und %d Überläufe entdeckt" -#: libvips/iofuncs/error.c:699 -msgid "image must be non-complex" -msgstr "Bild muss nicht-komplex sein" +#~ msgid "pangoft2 support disabled" +#~ msgstr "Pangoft2-Unterstützung deaktiviert" -#: libvips/iofuncs/error.c:723 -msgid "image must be complex" -msgstr "Bild muss komplex sein" +#~ msgid "zoom factors should be >= 0" +#~ msgstr "Zoomfaktoren sollten >=0 sein" -#: libvips/iofuncs/error.c:749 -#, c-format -msgid "image must be %s" -msgstr "Bild muss %s sein" +#~ msgid "vectors not same length" +#~ msgstr "Vektoren ungleicher Länge" -#: libvips/iofuncs/error.c:774 -msgid "image must be integer" -msgstr "Bild muss ganzzahlig sein" +#~ msgid "direction" +#~ msgstr "Richtung" -#: libvips/iofuncs/error.c:799 -msgid "image must be unsigned integer" -msgstr "Bild muss aus vorzeichenlosen Ganzzahlen bestehen" +#~ msgid "bad arguments" +#~ msgstr "falsche Argumente" -#: libvips/iofuncs/error.c:827 -msgid "image must be 8- or 16-bit integer, signed or unsigned" -msgstr "" -"Bild muss aus 8- oder 16-Bit Ganzzahlen mit oder ohne Vorzeichen bestehen" +#~ msgid "image does not have that many bands" +#~ msgstr "Bild hat nicht so viele Bänder" -#: libvips/iofuncs/error.c:854 -msgid "image must be 8- or 16-bit unsigned integer" -msgstr "Bild muss aus 8- oder 16-Bit vorzeichenlosen Ganzzahlen bestehen" +#~ msgid "factors should both be >= 1" +#~ msgstr "beide Faktoren sollten >=1 sein" -#: libvips/iofuncs/error.c:880 -msgid "image must be 8- or 16-bit unsigned integer, or float" -msgstr "" -"Bild muss aus 8- oder 16-Bit vorzeichenlosen Ganzzahlen oder " -"Fließkommazahlen bestehen" +#~ msgid "parameters would result in zero size output image" +#~ msgstr "Parameter würden zu einem Ausgabebild der Größe Null führen" -#: libvips/iofuncs/error.c:908 -msgid "image must be unsigned int or float" -msgstr "" -"Bild muss aus 8- oder 16-Bit vorzeichenlosen Ganz- oder Fließkommazahlen " -"bestehen" +#, c-format +#~ msgid "%d overflows and %d underflows detected" +#~ msgstr "%d Über- und %d Unterläufe entdeckt" -#: libvips/iofuncs/error.c:933 -msgid "images must match in size" -msgstr "Bilder müssen in der Größe passen" +#~ msgid "expect 1xN or Nx1 input mask" +#~ msgstr "1xN- oder Nx1-Eingabemaske wird erwartet" -#: libvips/iofuncs/error.c:959 -msgid "images must have the same number of bands" -msgstr "Bilder müssen die gleiche Anzahl Bänder haben" +# ref und in sind Objekte +#~ msgid "ref not smaller than or equal to in" +#~ msgstr "»ref« nicht kleiner oder gleich »in«" -#: libvips/iofuncs/error.c:1013 -msgid "images must have the same band format" -msgstr "Bilder müssen das gleiche Bandformat haben" +#~ msgid "end of file while skipping start" +#~ msgstr "Dateiende während des Überspringens des Startes" -#: libvips/iofuncs/error.c:1039 -msgid "images must have the same coding" -msgstr "Bilder müssen die gleiche Kodierung haben" +#, c-format +#~ msgid "unexpected EOF, line %d col %d" +#~ msgstr "unerwartetes Dateiende, Zeile %d, Spalte %d" -#: libvips/iofuncs/error.c:1064 #, c-format -msgid "vector must have 1 or %d elements" -msgstr "Vektor muss 1 oder %d Elemente haben" +#~ msgid "unexpected EOL, line %d col %d" +#~ msgstr "unerwartetes Zeilenende, Zeile %d, Spalte %d" -#: libvips/iofuncs/error.c:1089 -msgid "histograms must have width or height 1" -msgstr "Histogramme müssen eine Breite oder Höhe von eins haben" +#, c-format +#~ msgid "required field %d=%d, not %d" +#~ msgstr "benötigtes Feld %d=%d, nicht %d" -#: libvips/iofuncs/error.c:1094 -msgid "histograms must have not have more than 65536 elements" -msgstr "Histogramm dürfen nicht mehr als 65536 Elemente haben" +#~ msgid "4 or 5 bands CMYK TIFF only" +#~ msgstr "nur CMYK-TIFF mit vier oder fünf Bändern" -#: libvips/iofuncs/error.c:1123 libvips/iofuncs/error.c:1151 -msgid "nonsense mask parameters" -msgstr "unsinnige Maskenparameter" +#, c-format +#~ msgid "" +#~ "no resolution information for TIFF image \"%s\" -- defaulting to 1 pixel " +#~ "per mm" +#~ msgstr "" +#~ "Keine Auflösungsinformationen für TIFF-Bild »%s« – Standard auf 1 " +#~ "Bildpunkt pro mm" -#: libvips/iofuncs/error.c:1176 -msgid "mask must be 1D" -msgstr "Maske muss 1D sein" +#, c-format +#~ msgid "unsupported sample format %d for lab image" +#~ msgstr "nicht unterstütztes Musterformat %d für LAB-Bild" -#: libvips/iofuncs/threadpool.c:217 #, c-format -msgid "threads clipped to %d" -msgstr "Threads an %d angeheftet" +#~ msgid "unsupported depth %d for LAB image" +#~ msgstr "nicht unterstützte Tiefe %d für LAB-Bild" -#: libvips/iofuncs/threadpool.c:281 -msgid "per-thread state for vipsthreadpool" -msgstr "Status pro Thread für »vipsthreadpool«" +#, c-format +#~ msgid "unsupported sample format %d for greyscale image" +#~ msgstr "nicht unterstütztes Musterformat %d für Graustufenbild" -#: libvips/morphology/im_profile.c:104 -msgid "dir not 0 or 1" -msgstr "»dir« nicht 0 oder 1" +#, c-format +#~ msgid "unsupported depth %d for greyscale image" +#~ msgstr "nicht unterstützte Tiefe %d für Graustufenbild" -#: libvips/morphology/morphology.c:311 #, c-format -msgid "bad mask element (%d should be 0, 128 or 255)" -msgstr "falsches Maskenelement (%d sollte 0, 128 oder 255 sein)" +#~ msgid "unsupported sample format %d for rgb image" +#~ msgstr "nicht unterstütztes Musterformat %d für RGB-Bild" -#: libvips/morphology/im_zerox.c:141 -msgid "flag not -1 or 1" -msgstr "Schalter nicht -1 oder 1" +#, c-format +#~ msgid "unsupported depth %d for RGB image" +#~ msgstr "nicht unterstützte Tiefe %d für RGB-Bild" -#: libvips/morphology/im_zerox.c:145 -msgid "image too narrow" -msgstr "Bild zu schmal" +#~ msgid "error writing output" +#~ msgstr "Fehler beim Schreiben der Ausgabe" -#: libvips/morphology/im_cntlines.c:81 -msgid "flag should be 0 (horizontal) or 1 (vertical)" -msgstr "Schalter sollte 0 (horizontal) oder 1 (vertikal) sein" +#~ msgid "File descriptor" +#~ msgstr "Datei-Deskriptor" -#: libvips/morphology/im_rank.c:365 -msgid "image too small for window" -msgstr "Bild zu klein für Fenster" +#~ msgid "error setting JPEG resolution" +#~ msgstr "Fehler beim Setzen der JPEG-Auflösung" -#: libvips/morphology/im_rank_image.c:303 -msgid "zero input images!" -msgstr "null Eingabebilder" +#, c-format +#~ msgid "" +#~ "unable to ping file \"%s\"\n" +#~ "libMagick error: %s %s" +#~ msgstr "" +#~ "Datei »%s« kann nicht angepingt werden\n" +#~ "libMagick-Fehler: %s %s" -#: libvips/morphology/im_rank_image.c:308 #, c-format -msgid "index should be in range 0 - %d" -msgstr "Index sollte im Bereich 0 - %d liegen" +#~ msgid "unable to write \"%s\"" +#~ msgstr "»%s« kann nicht geschrieben werden" -#: libvips/mosaicing/im_lrmerge.c:213 libvips/mosaicing/im_lrmerge.c:262 -#: libvips/mosaicing/im_lrmerge.c:603 libvips/mosaicing/im_tbmerge.c:163 -#: libvips/mosaicing/im_tbmerge.c:217 libvips/mosaicing/im_tbmerge.c:535 -msgid "internal error" -msgstr "interner Fehler" +#~ msgid "error reading resolution" +#~ msgstr "Fehler beim Lesen der Auflösung" -#: libvips/mosaicing/im_lrmerge.c:703 -msgid "mwidth must be -1 or >= 0" -msgstr "»mwidth« muss -1 oder >= 0 sein" +#~ msgid "bad int" +#~ msgstr "falsche Ganzzahl" -#: libvips/mosaicing/im_lrmerge.c:732 -msgid "no overlap" -msgstr "kein Überlappen" +#~ msgid "bad float" +#~ msgstr "falsche Fließkommazahl" -#: libvips/mosaicing/im_lrmerge.c:803 libvips/mosaicing/im_tbmerge.c:634 -#: libvips/resample/im_affine.c:469 -msgid "unknown coding type" -msgstr "unbekannter Kodierungstyp" +#~ msgid "not whitespace before start of binary data" +#~ msgstr "kein Leerraum vor dem Start der binären Daten" -#: libvips/mosaicing/im_lrmerge.c:820 libvips/mosaicing/im_tbmerge.c:652 -msgid "too much overlap" -msgstr "zu viel Überlappung" +#~ msgid "write error ... disc full?" +#~ msgstr "Schreibfehler … Platte voll?" -#: libvips/mosaicing/im_remosaic.c:104 -#, c-format -msgid "substitute image \"%s\" is not the same size as \"%s\"" -msgstr "Bild zum Ersetzen »%s« hat nicht die gleiche Größe wie »%s«" +#~ msgid "binary >8 bit images must be float" +#~ msgstr "binäre Bilder >8 Bit müssen aus Fließkommazahlen bestehen" -#: libvips/mosaicing/im_tbmosaic.c:89 libvips/mosaicing/im_lrmosaic.c:113 -msgid "bad area parameters" -msgstr "falsche Bereichsparameter" +#~ msgid "layer buffer exhausted -- try making TIFF output tiles smaller" +#~ msgstr "" +#~ "Ebenenpuffer aufgebraucht – versuchen Sie die TIFF-Ausgabekacheln zu " +#~ "verkleinern" -#: libvips/mosaicing/im_tbmosaic.c:110 libvips/mosaicing/im_lrmosaic.c:134 -msgid "overlap too small for search" -msgstr "Überlappen zu klein für Suche" +#~ msgid "internal error #9876345" +#~ msgstr "interner Fehler #9876345" -#: libvips/mosaicing/im_tbmosaic.c:143 libvips/mosaicing/im_lrmosaic.c:167 -msgid "unknown Coding type" -msgstr "unbekannter Kodierungstyp" +#~ msgid "can't have strip pyramid -- enabling tiling" +#~ msgstr "" +#~ "nicht ummantelte Pyramide nicht möglich – Zerteilung wird eingeschaltet" -#: libvips/mosaicing/im_chkpair.c:200 -msgid "inputs incompatible" -msgstr "Eingaben inkompatibel" +#~ msgid "unsigned 8-bit int, 16-bit int, and 32-bit float only" +#~ msgstr "nur vorzeichenlose 8-Bit-Ganzzahl und 32-Bit-Fließkommazahl" -#: libvips/mosaicing/im_chkpair.c:204 libvips/mosaicing/im_tbcalcon.c:102 -msgid "help!" -msgstr "Hilfe!" +#~ msgid "1 to 5 bands only" +#~ msgstr "nur 1 bis 5 Bänder" -#: libvips/mosaicing/im_tbcalcon.c:116 -msgid "overlap too small" -msgstr "Überlappen zu schmal" +#~ msgid "images do not match" +#~ msgstr "Bilder passen nicht zusammen" -#: libvips/mosaicing/global_balance.c:145 -msgid "no matching '>'" -msgstr "kein passendes »>«" +#~ msgid "mask sizes power of 2 only" +#~ msgstr "Maskengröße nur Potenzen von 2" -#: libvips/mosaicing/global_balance.c:154 -msgid "too many items" -msgstr "zu viele Elemente" +#~ msgid "unimplemented mask type" +#~ msgstr "nicht implementierter Maskentyp" -# Propogate a transform down a tree. If dirty is set, we've been here before, -# so there is a doubling up of this node. If this is a leaf, then we have the -# same leaf twice (which, in fact, we can cope with); if this is a node, we -# have circularity. -#: libvips/mosaicing/global_balance.c:448 -msgid "circularity detected" -msgstr "Zirkularität entdeckt" +#~ msgid "bad args" +#~ msgstr "falsche Argumente" -#: libvips/mosaicing/global_balance.c:482 -#: libvips/mosaicing/global_balance.c:538 -#, c-format -msgid "image \"%s\" used twice as output" -msgstr "Bild »%s« zweimal als Ausgabe benutzt" +#~ msgid "bad args (f)" +#~ msgstr "falsche Argumente (f)" -#: libvips/mosaicing/global_balance.c:587 -msgid "bad number of args in join line" -msgstr "falsche Anzahl von Argumenten in »join«-Zeile" +#~ msgid "bad args (ac)" +#~ msgstr "falsche Argumente (ac)" -#: libvips/mosaicing/global_balance.c:629 -msgid "bad number of args in join1 line" -msgstr "falsche Anzahl von Argumenten in »join1«-Zeile" +#~ msgid "dimension should be in (2,3)" +#~ msgstr "Dimension sollte in (2,3) liegen" -#: libvips/mosaicing/global_balance.c:665 -msgid "bad number of args in copy line" -msgstr "falsche Anzahl von Argumenten in »copy«-Zeile" +#~ msgid "window too small" +#~ msgstr "Fenster zu klein" -#: libvips/mosaicing/global_balance.c:723 -msgid "" -"mosaic root not found in desc file\n" -"is this really a mosaiced image?" -msgstr "" -"Mosaik-Wurzel nicht in Beschreibungsdatei gefunden\n" -"ist das wirklich ein Bild?" +#~ msgid "bad input matrix size" +#~ msgstr "falsche Eingabematrix-Größe" -#: libvips/mosaicing/global_balance.c:734 -msgid "more than one root" -msgstr "mehr als eine Wurzel" +#~ msgid "bad in_max, out_max parameters" +#~ msgstr "falsche »in_max«-, »out_max«-Parameter" -#: libvips/mosaicing/global_balance.c:1053 -msgid "empty overlap!" -msgstr "leere Überlappung!" +#~ msgid "bad Lb, Lw parameters" +#~ msgstr "falsche »Lb«-, »Lw«-Parameter" -#: libvips/mosaicing/im_avgdxdy.c:64 -msgid "no points to average" -msgstr "keine Punkte zum Mitteln" +#~ msgid "Ps not in range [0.0,1.0]" +#~ msgstr "»Ps« nicht im Bereich [0.0,1.0]" -#: libvips/mosaicing/im_lrcalcon.c:203 -msgid "overlap too small for your search size" -msgstr "Überlappen zu schmal für Ihre Suchgröße" +#~ msgid "Pm not in range [0.0,1.0]" +#~ msgstr "»Pm« nicht im Bereich [0.0,1.0]" -#: libvips/mosaicing/im_lrcalcon.c:242 -#, c-format -msgid "found %d tie-points, need at least %d" -msgstr "es wurden %d Verbindungspunkte gefunden, mindestens %d sind nötig" +#~ msgid "Ph not in range [0.0,1.0]" +#~ msgstr "»Ph« nicht im Bereich [0.0,1.0]" -#: libvips/mosaicing/im_lrcalcon.c:287 -msgid "not 1-band uchar image" -msgstr "kein »uchar«-Bild mit einem Band" +#~ msgid "S not in range [-30,+30]" +#~ msgstr "»S« nicht im Bereich [-30,+30]" -#: libvips/mosaicing/im_clinear.c:136 -msgid "im_invmat failed" -msgstr "»im_invmat« fehlgeschlagen" +#~ msgid "M not in range [-30,+30]" +#~ msgstr "»M« nicht im Bereich [-30,+30]" -#: libvips/other/im_zone.c:80 -msgid "size must be even and positive" -msgstr "Größe muss gerade und positiv sein" +#~ msgid "H not in range [-30,+30]" +#~ msgstr "»H« nicht im Bereich [-30,+30]" -#: libvips/other/im_sines.c:88 -msgid "wrong sizes" -msgstr "falsche Größen" +#~ msgid "bad lut_size" +#~ msgstr "falsche »lut_size«" -#: libvips/other/im_sines.c:101 -msgid "calloc failed" -msgstr "»calloc« fehlgeschlagen" +#~ msgid "mask image not 1 band 8 bit uncoded" +#~ msgstr "Maskenbild nicht 8-Bit-kodiert mit einem Band" -#: libvips/other/im_eye.c:83 -msgid "factor should be in [1,0)" -msgstr "Faktor sollte in [0,1) liegen" +#, c-format +#~ msgid "unable to set property \"%s\" to value \"%s\"." +#~ msgstr "Eigenschaft »%s« kann nicht auf Wert »%s« gesetzt werden." -#: libvips/resample/im_affine.c:410 -msgid "output coordinates out of range" -msgstr "Ausgabekoordinaten außerhalb des Bereichs" +#, c-format +#~ msgid "start function failed for image %s" +#~ msgstr "Startfunktion für Bild %s fehlgeschlagen" -#: libvips/resample/im_shrink.c:346 -msgid "shrink factors should be >= 1" -msgstr "Schrumpffaktoren sollten >=1 sein" +#~ msgid "evaluate with N concurrent threads" +#~ msgstr "mit N gleichzeitigen Threads auswerten" -#: libvips/resample/interpolate.c:180 -msgid "VIPS interpolators" -msgstr "VIPS-Interpolatoren" +#~ msgid "set tile width to N (DEBUG)" +#~ msgstr "Bildbreite auf N setzen (DEBUG)" -#: libvips/resample/interpolate.c:361 -msgid "Nearest-neighbour interpolation" -msgstr "Nächste-Nachbar-Interpolation" +#~ msgid "set tile height to N (DEBUG)" +#~ msgstr "Bildhöhe auf N setzen (DEBUG)" -#: libvips/resample/interpolate.c:532 -msgid "Bilinear interpolation" -msgstr "Bilineare Interpolation" +#~ msgid "set thinstrip height to N (DEBUG)" +#~ msgstr "»thinstrip«-Höhe auf N setzen (DEBUG)" -#: libvips/resample/im_rightshift_size.c:120 -msgid "shift by zero: falling back to im_copy" -msgstr "verschieben um Null: Rückfall auf »im_copy«" +#~ msgid "set fatstrip height to N (DEBUG)" +#~ msgstr "»fatstrip«-Höhe auf N setzen (DEBUG)" -#: libvips/resample/im_rightshift_size.c:124 -msgid "would result in zero size output image" -msgstr "würde in einem Ausgabebild der Größe Null resultieren" +#~ msgid "show progress feedback" +#~ msgstr "Fortschrittsrückmeldung anzeigen" -#: libvips/resample/im_rightshift_size.c:132 -msgid "image and band_fmt must match in sign" -msgstr "Bild und Band-Fmt müssen im Kennzeichen zusammenpassen" +#~ msgid "leak-check on exit" +#~ msgstr "Lückenprüfung beim Beenden" -#: libvips/video/im_video_test.c:51 -msgid "error requested" -msgstr "Fehler abgefragt" +#~ msgid "images larger than N are decompressed to disc" +#~ msgstr "Bilder, die größer als N sind, werden auf die Platte dekomprimiert" -#: libvips/video/im_video_v4l1.c:241 -msgid "no file descriptor" -msgstr "kein Datei-Deskriptor" +#~ msgid "disable vectorised versions of operations" +#~ msgstr "vektorgesteuerte Versionen von Transaktionen deaktivieren" -#: libvips/video/im_video_v4l1.c:246 -#, c-format -msgid "ioctl(0x%x) failed: %s" -msgstr "ioctl(0x%x) fehlgeschlagen: %s" +#~ msgid "cache at most N operations" +#~ msgstr "höchstens N Transaktionen zwischenspeichern" -#: libvips/video/im_video_v4l1.c:295 -#, c-format -msgid "cannot open video device \"%s\"" -msgstr "Videogerät »%s« kann nicht geöffnet werden" +#~ msgid "cache at most N bytes in memory" +#~ msgstr "höchstens N Byte zwischenspeichern" + +#~ msgid "allow at most N open files" +#~ msgstr "höchstens N offene Dateien erlauben" + +#~ msgid "trace operation cache" +#~ msgstr "Transaktionszwischenspeicher aufzeichnen" + +#~ msgid "dump operation cache on exit" +#~ msgstr "Transaktionszwischenspeicher beim Beenden ausgeben" + +#~ msgid "VIPS Options" +#~ msgstr "VIPS-Optionen" -#: libvips/video/im_video_v4l1.c:303 -msgid "cannot get video capability" -msgstr "Videofähigkeit kann nicht abgefragt werden" +#~ msgid "Show VIPS options" +#~ msgstr "VIPS-Optionen anzeigen" -#: libvips/video/im_video_v4l1.c:312 -msgid "card cannot capture to memory" -msgstr "Karte kann nicht in Speicher digitalisiert werden" +#, c-format +#~ msgid "%dx%d %s, %d band, %s" +#~ msgid_plural "%dx%d %s, %d bands, %s" +#~ msgstr[0] "%dx%d %s, %d Band, %s" +#~ msgstr[1] "%dx%d %s, %d Bänder, %s" -#: libvips/video/im_video_v4l1.c:458 -msgid "unable to map memory" -msgstr "Speicher kann nicht abgebildet werden" +#, c-format +#~ msgid " %s, %d band, %s" +#~ msgid_plural " %s, %d bands, %s" +#~ msgstr[0] " %s, %d band, %s" +#~ msgstr[1] " %s, %d Bänder, %s" -#: libvips/video/im_video_v4l1.c:470 #, c-format -msgid "channel not between 0 and %d" -msgstr "Kanal nicht zwischen 0 und %d" +#~ msgid "" +#~ "map failed (%s), running very low on system resources, expect a crash soon" +#~ msgstr "" +#~ "»map« fehlgeschlagen (%s), die Systemressourcen werden knapp, ein Absturz " +#~ "steht bevor" -#: libvips/video/im_video_v4l1.c:698 -msgid "compiled without im_video_v4l1 support" -msgstr "ohne »im_video_v4l1«-Unterstützung kompiliert" +#~ msgid "too little data" +#~ msgstr "zu wenige Daten" -#: tools/edvips.c:82 -msgid "tag file as big or little-endian" -msgstr "Kennzeichendatei als Big- oder Little-Endian" +#~ msgid "bytes" +#~ msgstr "Byte" -#: tools/edvips.c:84 -msgid "set width to N pixels" -msgstr "Breite auf N Bildpunkte setzen" +#~ msgid "KB" +#~ msgstr "KB" -#: tools/edvips.c:86 -msgid "set height to N pixels" -msgstr "Höhe auf N Bildpunkte setzen" +#~ msgid "MB" +#~ msgstr "MB" -#: tools/edvips.c:88 -msgid "set Bands to N" -msgstr "Bänder auf N setzen" +#~ msgid "TB" +#~ msgstr "TB" -#: tools/edvips.c:90 -msgid "set BandFmt to F (eg. uchar, float)" -msgstr "»BandFmt« auf F setzen (z.B. uchar, float)" +#, c-format +#~ msgid "unable to make temporary file %s" +#~ msgstr "temporäre Datei %s kann nicht erstellt werden" -#: tools/edvips.c:92 -msgid "set interpretation to I (eg. xyz)" -msgstr "Interpretation aif I setzen (z.B. xyz)" +#~ msgid "usage:" +#~ msgstr "Aufruf:" -#: tools/edvips.c:94 -msgid "set Coding to C (eg. labq)" -msgstr "Kodierung auf C setzen (z.B. labq)" +#, c-format +#~ msgid "%s: " +#~ msgstr "%s: " -#: tools/edvips.c:96 -msgid "set Xres to R pixels/mm" -msgstr "»Xres« auf R Bildpunkte/mm setzen" +#~ msgid "vips diagnostic" +#~ msgstr "Vips-Diagnose" -#: tools/edvips.c:98 -msgid "set Yres to R pixels/mm" -msgstr "»Yres« auf R Bildpunkte/mm setzen" +#~ msgid "vips warning" +#~ msgstr "Vips-Warnung" -#: tools/edvips.c:100 -msgid "set Xoffset to N pixels" -msgstr "»Xoffset« auf N Bildpunkte setzen" +#~ msgid "nonsense mask parameters" +#~ msgstr "unsinnige Maskenparameter" -#: tools/edvips.c:102 -msgid "set Yoffset to N pixels" -msgstr "»Yoffset« auf N Bildpunkte setzen" +#~ msgid "mask must be 1D" +#~ msgstr "Maske muss 1D sein" -#: tools/edvips.c:104 -msgid "replace extension block with stdin" -msgstr "Erweiterungsblock mit STDIN ersetzen" +#~ msgid "dir not 0 or 1" +#~ msgstr "»dir« nicht 0 oder 1" -#: tools/edvips.c:106 -msgid "set Xsize to N (deprecated, use width)" -msgstr "»Xsize« auf N setzen (missbilligt, benutzen Sie »width«)" +#~ msgid "flag should be 0 (horizontal) or 1 (vertical)" +#~ msgstr "Schalter sollte 0 (horizontal) oder 1 (vertikal) sein" -#: tools/edvips.c:108 -msgid "set Ysize to N (deprecated, use height)" -msgstr "»Ysize« auf N setzen (missbilligt, benutzen Sie »height«)" +#~ msgid "image too small for window" +#~ msgstr "Bild zu klein für Fenster" -#: tools/edvips.c:110 -msgid "set Type to T (deprecated, use interpretation)" -msgstr "Typ auf N setzen (missbilligt, benutzen Sie »interpretation«" +#~ msgid "zero input images!" +#~ msgstr "null Eingabebilder" -#: tools/edvips.c:121 #, c-format -msgid "'%s' is not a positive integer" -msgstr "»%s« ist keine positive Ganzzahl" +#~ msgid "index should be in range 0 - %d" +#~ msgstr "Index sollte im Bereich 0 - %d liegen" -#: tools/edvips.c:133 -msgid "unable to start VIPS" -msgstr "VIPS kann nicht gestartet werden" +#~ msgid "size must be even and positive" +#~ msgstr "Größe muss gerade und positiv sein" -#: tools/edvips.c:138 -msgid "vipsfile - edit vipsfile header" -msgstr "»vipsfile« - »vipsfile«-Kopfzeilen bearbeiten" +#~ msgid "wrong sizes" +#~ msgstr "falsche Größen" -#: tools/edvips.c:150 -#, c-format -msgid "usage: %s [OPTION...] vipsfile\n" -msgstr "Aufruf: %s [OPTION …] vipsfile\n" +#~ msgid "calloc failed" +#~ msgstr "»calloc« fehlgeschlagen" -#: tools/edvips.c:157 -#, c-format -msgid "could not open image %s" -msgstr "Bild %s konnte nicht geöffnet werden" +#~ msgid "factor should be in [1,0)" +#~ msgstr "Faktor sollte in [0,1) liegen" -#: tools/edvips.c:160 -#, c-format -msgid "could not read VIPS header for %s" -msgstr "VIPS-Kopfzeilen für %s konnten nicht gelesen werden" +#~ msgid "shift by zero: falling back to im_copy" +#~ msgstr "verschieben um Null: Rückfall auf »im_copy«" -#: tools/edvips.c:169 -#, c-format -msgid "bad endian-ness %s, should be 'big' or 'little'" -msgstr "falsche Byte-Reihenfolge %s, sollte »big« oder »little« sein" +#~ msgid "would result in zero size output image" +#~ msgstr "würde in einem Ausgabebild der Größe Null resultieren" -#: tools/edvips.c:182 -#, c-format -msgid "bad format %s" -msgstr "falsches Format %s" +#~ msgid "image and band_fmt must match in sign" +#~ msgstr "Bild und Band-Fmt müssen im Kennzeichen zusammenpassen" -#: tools/edvips.c:190 #, c-format -msgid "bad interpretation %s" -msgstr "falsche Interpretation »%s« " +#~ msgid "ioctl(0x%x) failed: %s" +#~ msgstr "ioctl(0x%x) fehlgeschlagen: %s" -#: tools/edvips.c:198 #, c-format -msgid "bad coding %s" -msgstr "falsche Kodierung %s" +#~ msgid "cannot open video device \"%s\"" +#~ msgstr "Videogerät »%s« kann nicht geöffnet werden" -#: tools/edvips.c:211 -#, c-format -msgid "could not seek on %s" -msgstr "auf %s konnte nicht gesucht werden" +#~ msgid "cannot get video capability" +#~ msgstr "Videofähigkeit kann nicht abgefragt werden" + +#~ msgid "card cannot capture to memory" +#~ msgstr "Karte kann nicht in Speicher digitalisiert werden" + +#~ msgid "unable to map memory" +#~ msgstr "Speicher kann nicht abgebildet werden" -#: tools/edvips.c:214 #, c-format -msgid "could not write to %s" -msgstr "auf %s konnte nicht geschrieben werden" +#~ msgid "channel not between 0 and %d" +#~ msgstr "Kanal nicht zwischen 0 und %d" -#: tools/edvips.c:221 -msgid "could not get ext data" -msgstr "zusätzliche Daten konnten nicht abgefragt werden" +#~ msgid "compiled without im_video_v4l1 support" +#~ msgstr "ohne »im_video_v4l1«-Unterstützung kompiliert" -#: tools/edvips.c:230 -msgid "could not set extension" -msgstr "Erweiterung konnte nicht gesetzt werden" +#~ msgid "tag file as big or little-endian" +#~ msgstr "Kennzeichendatei als Big- oder Little-Endian" -#: tools/find_mosaic.c:112 tools/find_mosaic.c:122 tools/find_mosaic.c:144 -#: tools/find_mosaic.c:154 tools/find_mosaic.c:163 tools/find_mosaic.c:184 -#: tools/find_mosaic.c:194 tools/find_mosaic.c:203 tools/mergeup.c:238 -#: tools/mergeup.c:248 tools/mergeup.c:270 tools/mergeup.c:280 -#: tools/mergeup.c:289 tools/mergeup.c:310 tools/mergeup.c:320 -#: tools/mergeup.c:329 -#, c-format -msgid "bad file name format '%s'" -msgstr "falsches Dateinamensformat »%s«" +#~ msgid "set width to N pixels" +#~ msgstr "Breite auf N Bildpunkte setzen" -#: tools/header.c:85 -msgid "show all fields" -msgstr "alle Felder anzeigen" +#~ msgid "set height to N pixels" +#~ msgstr "Höhe auf N Bildpunkte setzen" -#: tools/header.c:87 -msgid "" -"print value of FIELD (\"getext\" reads extension block, \"Hist\" reads image " -"history)" -msgstr "" -"Wert von FELD ausgeben (»getext« liest Erweiterungsblock, »Hist« liest " -"Bildchronik)" +#~ msgid "set BandFmt to F (eg. uchar, float)" +#~ msgstr "»BandFmt« auf F setzen (z.B. uchar, float)" -#: tools/header.c:210 -msgid "- print image header" -msgstr "- Bild-Kopfzeilen ausgeben" +#~ msgid "set interpretation to I (eg. xyz)" +#~ msgstr "Interpretation aif I setzen (z.B. xyz)" -#: tools/mergeup.c:381 -msgid "allocation failure in mergeup" -msgstr "Reservierung in »mergeup« gescheitert" +#~ msgid "set Coding to C (eg. labq)" +#~ msgstr "Kodierung auf C setzen (z.B. labq)" -#: tools/mergeup.c:391 -msgid "Need more than one image" -msgstr "Mehr als ein Bild benötigt" +#~ msgid "set Xres to R pixels/mm" +#~ msgstr "»Xres« auf R Bildpunkte/mm setzen" -#: tools/vips.c:101 -msgid "load PLUGIN" -msgstr "ERWEITERUNG laden" +#~ msgid "set Yres to R pixels/mm" +#~ msgstr "»Yres« auf R Bildpunkte/mm setzen" -#: tools/vips.c:102 -msgid "PLUGIN" -msgstr "ERWEITERUNG" +#~ msgid "set Xoffset to N pixels" +#~ msgstr "»Xoffset« auf N Bildpunkte setzen" -#: tools/vips.c:104 -msgid "print version" -msgstr "Version ausgeben" +#~ msgid "set Yoffset to N pixels" +#~ msgstr "»Yoffset« auf N Bildpunkte setzen" -#: tools/vips.c:147 -#, c-format -msgid "no package or function \"%s\"" -msgstr "kein Paket oder Funktion »%s«" +#~ msgid "replace extension block with stdin" +#~ msgstr "Erweiterungsblock mit STDIN ersetzen" -#: tools/vips.c:917 -msgid "list classes|packages|all|package-name|operation-name" -msgstr "classes|packages|all|package-name|operation-name aufführen" +#~ msgid "set Xsize to N (deprecated, use width)" +#~ msgstr "»Xsize« auf N setzen (missbilligt, benutzen Sie »width«)" -#: tools/vips.c:919 -msgid "generate headers for C++ binding" -msgstr "Header für C++-Anbindung erzeugen" +#~ msgid "set Ysize to N (deprecated, use height)" +#~ msgstr "»Ysize« auf N setzen (missbilligt, benutzen Sie »height«)" -#: tools/vips.c:921 -msgid "generate bodies for C++ binding" -msgstr "Rumpfdaten für C++-Anbindung erzeugen" +#~ msgid "set Type to T (deprecated, use interpretation)" +#~ msgstr "Typ auf N setzen (missbilligt, benutzen Sie »interpretation«" -#: tools/vips.c:923 -msgid "generate links for vips/bin" -msgstr "Verweise für VIPS/Bin erzeugen" +#, c-format +#~ msgid "bad file name format '%s'" +#~ msgstr "falsches Dateinamensformat »%s«" -#: tools/vips.c:1043 -msgid "[ACTION] [OPTIONS] [PARAMETERS] - VIPS driver program" -msgstr "[AKTION] [OPTIONEN] [PARAMETER] - VIPS-Treiberprogramm" +#~ msgid "show all fields" +#~ msgstr "alle Felder anzeigen" -#: tools/vips.c:1111 -msgid "possible actions:\n" -msgstr "mögliche Aktionen:\n" +#~ msgid "" +#~ "print value of FIELD (\"getext\" reads extension block, \"Hist\" reads " +#~ "image history)" +#~ msgstr "" +#~ "Wert von FELD ausgeben (»getext« liest Erweiterungsblock, »Hist« liest " +#~ "Bildchronik)" -#: tools/vips.c:1116 -msgid "execute named vips operation" -msgstr "genannte VIPS-Transaktion ausführen" +#~ msgid "allocation failure in mergeup" +#~ msgstr "Reservierung in »mergeup« gescheitert" -#: tools/vips.c:1118 -#, c-format -msgid "unknown action \"%s\"" -msgstr "unbekannte Aktion »%s«" +#~ msgid "Need more than one image" +#~ msgstr "Mehr als ein Bild benötigt" -#: tools/vipsthumbnail.c:54 -msgid "set thumbnail size to SIZE" -msgstr "Miniaturansicht auf GRÖẞE setzen" +#~ msgid "load PLUGIN" +#~ msgstr "ERWEITERUNG laden" -#: tools/vipsthumbnail.c:55 -msgid "SIZE" -msgstr "GRÖẞE" +#~ msgid "PLUGIN" +#~ msgstr "ERWEITERUNG" -#: tools/vipsthumbnail.c:57 -msgid "set output to FORMAT" -msgstr "Ausgabe auf FORMAT setzen" +#~ msgid "list classes|packages|all|package-name|operation-name" +#~ msgstr "classes|packages|all|package-name|operation-name aufführen" -#: tools/vipsthumbnail.c:58 -msgid "FORMAT" -msgstr "FORMAT" +#~ msgid "generate headers for C++ binding" +#~ msgstr "Header für C++-Anbindung erzeugen" -#: tools/vipsthumbnail.c:60 -msgid "resample with INTERPOLATOR" -msgstr "neues Muster mit INTERPOLATOR erstellen" +#~ msgid "generate bodies for C++ binding" +#~ msgstr "Rumpfdaten für C++-Anbindung erzeugen" -#: tools/vipsthumbnail.c:61 -msgid "INTERPOLATOR" -msgstr "INTERPOLATOR" +#~ msgid "generate links for vips/bin" +#~ msgstr "Verweise für VIPS/Bin erzeugen" -#: tools/vipsthumbnail.c:63 -msgid "don't sharpen thumbnail" -msgstr "Miniaturansicht nicht schärfen" +#~ msgid "possible actions:\n" +#~ msgstr "mögliche Aktionen:\n" -#: tools/vipsthumbnail.c:65 -msgid "export with PROFILE" -msgstr "mit PROFIL exportieren" +#~ msgid "SIZE" +#~ msgstr "GRÖẞE" -#: tools/vipsthumbnail.c:66 tools/vipsthumbnail.c:69 -msgid "PROFILE" -msgstr "PROFIL" +#~ msgid "set output to FORMAT" +#~ msgstr "Ausgabe auf FORMAT setzen" -#: tools/vipsthumbnail.c:68 -msgid "import untagged images with PROFILE" -msgstr "nicht gekennzeichnetes Bild mit PROFIL importieren" +#~ msgid "FORMAT" +#~ msgstr "FORMAT" -#: tools/vipsthumbnail.c:71 -msgid "don't delete profile from exported image" -msgstr "Profil aus exportiertem Bild nicht löschen" +#~ msgid "resample with INTERPOLATOR" +#~ msgstr "neues Muster mit INTERPOLATOR erstellen" -#: tools/vipsthumbnail.c:73 -msgid "verbose output" -msgstr "detaillierte Ausgabe" +#~ msgid "INTERPOLATOR" +#~ msgstr "INTERPOLATOR" -#: tools/vipsthumbnail.c:412 -msgid "- thumbnail generator" -msgstr "- Miniaturansichten-Generator" +#~ msgid "don't sharpen thumbnail" +#~ msgstr "Miniaturansicht nicht schärfen" -#: libvips/resample/bicubic.cpp:430 -msgid "Bicubic interpolation (Catmull-Rom)" -msgstr "doppelt kubische Interpolation (Catmull-Rom)" +#~ msgid "export with PROFILE" +#~ msgstr "mit PROFIL exportieren" -#: libvips/resample/nohalo.cpp:1577 -msgid "Edge sharpening resampler with halo reduction" -msgstr "neues Kantenschärfungsmuster mit Halo-Reduzierung" +#~ msgid "PROFILE" +#~ msgstr "PROFIL" -#: libvips/resample/vsqbs.cpp:400 -msgid "B-Splines with antialiasing smoothing" -msgstr "B-Splines mit Kantenglättung" +#~ msgid "import untagged images with PROFILE" +#~ msgstr "nicht gekennzeichnetes Bild mit PROFIL importieren" -#: libvips/resample/lbb.cpp:861 -msgid "Reduced halo bicubic" -msgstr "doppelt kubische Halo-Reduzierung" +#~ msgid "don't delete profile from exported image" +#~ msgstr "Profil aus exportiertem Bild nicht löschen" diff --git a/po/en_GB.po b/po/en_GB.po index de7c19c669..854155d0ed 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -1,6350 +1,7547 @@ # en_GB for vips - # Copyright (C) 2017 # This file is distributed under the same license as the vips package. # John Cupitt , 2017. # -#, fuzzy - msgid "" msgstr "" -"Project-Id-Version: vips 8.5\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-02-22 13:13+0000\n" -"PO-Revision-Date: \n" +"POT-Creation-Date: 2025-01-30 14:51+0000\n" "Last-Translator: John Cupitt \n" -"Language-Team: \n" "Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libvips/arithmetic/min.c:431 -msgid "find image minimum" +#: libvips/arithmetic/abs.c:200 +msgid "absolute value of an image" +msgstr "" + +#: libvips/arithmetic/add.c:178 +msgid "add two images" +msgstr "" + +#: libvips/arithmetic/arithmetic.c:392 +#, c-format +msgid "not one band or %d bands" +msgstr "" + +#: libvips/arithmetic/arithmetic.c:397 libvips/foreign/spngsave.c:423 +msgid "bad bands" +msgstr "" + +#: libvips/arithmetic/arithmetic.c:725 +msgid "arithmetic operations" msgstr "" -#: ../libvips/arithmetic/min.c:439 ../libvips/arithmetic/stats.c:420 -#: ../libvips/arithmetic/deviate.c:221 ../libvips/arithmetic/max.c:438 -#: ../libvips/arithmetic/hist_find_ndim.c:298 -#: ../libvips/arithmetic/measure.c:210 ../libvips/arithmetic/hist_find.c:450 -#: ../libvips/arithmetic/hough.c:185 ../libvips/arithmetic/arithmetic.c:639 -#: ../libvips/arithmetic/avg.c:214 -#: ../libvips/arithmetic/hist_find_indexed.c:391 ../libvips/colour/colour.c:427 -#: ../libvips/colour/sRGB2scRGB.c:249 ../libvips/colour/scRGB2BW.c:243 -#: ../libvips/colour/scRGB2sRGB.c:271 ../libvips/colour/colourspace.c:592 -#: ../libvips/conversion/conversion.c:200 -#: ../libvips/convolution/convolution.c:135 -#: ../libvips/convolution/gaussblur.c:125 ../libvips/convolution/sharpen.c:319 -#: ../libvips/convolution/correlation.c:163 ../libvips/create/create.c:101 -#: ../libvips/foreign/foreign.c:984 ../libvips/freqfilt/freqfilt.c:104 -#: ../libvips/histogram/hist_equal.c:114 ../libvips/histogram/stdif.c:300 -#: ../libvips/histogram/histogram.c:232 ../libvips/histogram/hist_entropy.c:119 -#: ../libvips/histogram/hist_norm.c:147 ../libvips/histogram/hist_plot.c:348 -#: ../libvips/histogram/hist_local.c:364 ../libvips/histogram/maplut.c:700 -#: ../libvips/iofuncs/system.c:284 ../libvips/morphology/morph.c:143 -#: ../libvips/morphology/rank.c:413 ../libvips/mosaicing/merge.c:121 -#: ../libvips/mosaicing/im_remosaic.c:170 -#: ../libvips/mosaicing/global_balance.c:1777 ../libvips/mosaicing/mosaic.c:192 -#: ../libvips/mosaicing/match.c:216 ../libvips/mosaicing/mosaic1.c:501 -#: ../libvips/resample/resample.c:138 ../libvips/resample/thumbnail.c:520 +#: libvips/arithmetic/arithmetic.c:731 libvips/arithmetic/avg.c:235 +#: libvips/arithmetic/deviate.c:237 libvips/arithmetic/hist_find.c:431 +#: libvips/arithmetic/hist_find_indexed.c:475 +#: libvips/arithmetic/hist_find_ndim.c:313 libvips/arithmetic/hough.c:179 +#: libvips/arithmetic/max.c:452 libvips/arithmetic/measure.c:201 +#: libvips/arithmetic/min.c:452 libvips/arithmetic/stats.c:442 +#: libvips/colour/CMYK2XYZ.c:126 libvips/colour/colour.c:415 +#: libvips/colour/colourspace.c:563 libvips/colour/scRGB2BW.c:243 +#: libvips/colour/scRGB2sRGB.c:276 libvips/colour/scRGB2XYZ.c:197 +#: libvips/colour/sRGB2scRGB.c:294 libvips/colour/XYZ2CMYK.c:125 +#: libvips/colour/XYZ2scRGB.c:206 libvips/conversion/conversion.c:346 +#: libvips/conversion/switch.c:202 libvips/convolution/canny.c:448 +#: libvips/convolution/convolution.c:134 libvips/convolution/correlation.c:162 +#: libvips/convolution/edge.c:223 libvips/convolution/gaussblur.c:138 +#: libvips/convolution/sharpen.c:328 libvips/create/create.c:124 +#: libvips/foreign/foreign.c:1215 libvips/freqfilt/freqfilt.c:104 +#: libvips/histogram/case.c:252 libvips/histogram/hist_entropy.c:117 +#: libvips/histogram/hist_equal.c:120 libvips/histogram/hist_local.c:367 +#: libvips/histogram/hist_norm.c:147 libvips/histogram/histogram.c:232 +#: libvips/histogram/hist_plot.c:339 libvips/histogram/maplut.c:750 +#: libvips/histogram/stdif.c:300 libvips/iofuncs/system.c:284 +#: libvips/morphology/morph.c:959 libvips/morphology/rank.c:564 +#: libvips/mosaicing/global_balance.c:1930 libvips/mosaicing/match.c:208 +#: libvips/mosaicing/matrixinvert.c:449 libvips/mosaicing/merge.c:134 +#: libvips/mosaicing/mosaic1.c:510 libvips/mosaicing/mosaic.c:191 +#: libvips/mosaicing/remosaic.c:170 libvips/resample/resample.c:146 +#: libvips/resample/thumbnail.c:968 msgid "Output" msgstr "" -#: ../libvips/arithmetic/min.c:440 ../libvips/arithmetic/deviate.c:222 -#: ../libvips/arithmetic/max.c:439 ../libvips/arithmetic/avg.c:215 -#: ../libvips/histogram/hist_entropy.c:120 +#: libvips/arithmetic/arithmetic.c:732 libvips/arithmetic/hough.c:180 +#: libvips/colour/CMYK2XYZ.c:127 libvips/colour/colour.c:416 +#: libvips/colour/colourspace.c:564 libvips/colour/scRGB2BW.c:244 +#: libvips/colour/scRGB2sRGB.c:277 libvips/colour/scRGB2XYZ.c:198 +#: libvips/colour/sRGB2scRGB.c:295 libvips/colour/XYZ2CMYK.c:126 +#: libvips/colour/XYZ2scRGB.c:207 libvips/conversion/conversion.c:347 +#: libvips/conversion/switch.c:203 libvips/convolution/canny.c:449 +#: libvips/convolution/convolution.c:135 libvips/convolution/correlation.c:163 +#: libvips/convolution/edge.c:224 libvips/convolution/gaussblur.c:139 +#: libvips/convolution/sharpen.c:329 libvips/create/create.c:125 +#: libvips/foreign/foreign.c:1216 libvips/freqfilt/freqfilt.c:105 +#: libvips/histogram/case.c:253 libvips/histogram/hist_equal.c:121 +#: libvips/histogram/hist_local.c:368 libvips/histogram/hist_norm.c:148 +#: libvips/histogram/histogram.c:233 libvips/histogram/hist_plot.c:340 +#: libvips/histogram/maplut.c:751 libvips/histogram/stdif.c:301 +#: libvips/iofuncs/system.c:285 libvips/morphology/morph.c:960 +#: libvips/morphology/rank.c:565 libvips/mosaicing/global_balance.c:1931 +#: libvips/mosaicing/match.c:209 libvips/mosaicing/merge.c:135 +#: libvips/mosaicing/mosaic1.c:511 libvips/mosaicing/mosaic.c:192 +#: libvips/mosaicing/remosaic.c:171 libvips/resample/resample.c:147 +#: libvips/resample/thumbnail.c:969 +msgid "Output image" +msgstr "" + +#: libvips/arithmetic/avg.c:227 +msgid "find image average" +msgstr "" + +#: libvips/arithmetic/avg.c:236 libvips/arithmetic/deviate.c:238 +#: libvips/arithmetic/max.c:453 libvips/arithmetic/min.c:453 +#: libvips/histogram/hist_entropy.c:118 msgid "Output value" msgstr "" -#: ../libvips/arithmetic/min.c:446 ../libvips/arithmetic/max.c:445 -#: ../libvips/arithmetic/getpoint.c:153 ../libvips/conversion/embed.c:569 -#: ../libvips/conversion/wrap.c:125 ../libvips/draw/draw_image.c:265 -#: ../libvips/draw/draw_mask.c:329 ../libvips/draw/draw_flood.c:552 -msgid "x" +#: libvips/arithmetic/binary.c:89 +msgid "binary operations" msgstr "" -#: ../libvips/arithmetic/min.c:447 -msgid "Horizontal position of minimum" +#: libvips/arithmetic/binary.c:96 libvips/arithmetic/find_trim.c:216 +#: libvips/arithmetic/measure.c:221 libvips/colour/colour.c:684 +#: libvips/conversion/extract.c:200 libvips/draw/draw_flood.c:593 +#: libvips/draw/draw_rect.c:173 libvips/draw/draw_smudge.c:215 +msgid "Left" msgstr "" -#: ../libvips/arithmetic/min.c:453 ../libvips/arithmetic/max.c:452 -#: ../libvips/arithmetic/getpoint.c:160 ../libvips/conversion/embed.c:576 -#: ../libvips/conversion/wrap.c:132 ../libvips/draw/draw_image.c:272 -#: ../libvips/draw/draw_mask.c:336 ../libvips/draw/draw_flood.c:559 -msgid "y" +#: libvips/arithmetic/binary.c:97 +msgid "Left-hand image argument" msgstr "" -#: ../libvips/arithmetic/min.c:454 -msgid "Vertical position of minimum" +#: libvips/arithmetic/binary.c:102 libvips/colour/colour.c:690 +msgid "Right" msgstr "" -#: ../libvips/arithmetic/min.c:460 ../libvips/arithmetic/max.c:459 -#: ../libvips/create/invertlut.c:295 ../libvips/create/identity.c:158 -msgid "Size" +#: libvips/arithmetic/binary.c:103 +msgid "Right-hand image argument" msgstr "" -#: ../libvips/arithmetic/min.c:461 -msgid "Number of minimum values to find" +#: libvips/arithmetic/boolean.c:269 +msgid "boolean operation on two images" msgstr "" -#: ../libvips/arithmetic/min.c:467 ../libvips/arithmetic/max.c:466 -#: ../libvips/arithmetic/getpoint.c:146 -msgid "Output array" +#: libvips/arithmetic/boolean.c:277 libvips/arithmetic/boolean.c:577 +#: libvips/arithmetic/complex.c:258 libvips/arithmetic/complex.c:538 +#: libvips/arithmetic/complex.c:771 libvips/arithmetic/math2.c:241 +#: libvips/arithmetic/math2.c:471 libvips/arithmetic/math.c:261 +#: libvips/arithmetic/relational.c:246 libvips/arithmetic/relational.c:611 +#: libvips/conversion/bandbool.c:238 tools/vips.c:627 +msgid "Operation" msgstr "" -#: ../libvips/arithmetic/min.c:468 ../libvips/arithmetic/max.c:467 -#: ../libvips/arithmetic/getpoint.c:147 -msgid "Array of output values" +#: libvips/arithmetic/boolean.c:278 libvips/arithmetic/boolean.c:578 +#: libvips/conversion/bandbool.c:239 +msgid "Boolean to perform" msgstr "" -#: ../libvips/arithmetic/min.c:474 ../libvips/arithmetic/max.c:473 -msgid "x array" +#: libvips/arithmetic/boolean.c:569 +msgid "boolean operations against a constant" msgstr "" -#: ../libvips/arithmetic/min.c:475 ../libvips/arithmetic/max.c:474 -msgid "Array of horizontal positions" +#: libvips/arithmetic/clamp.c:155 +msgid "clamp values of an image" msgstr "" -#: ../libvips/arithmetic/min.c:481 ../libvips/arithmetic/max.c:480 -msgid "y array" +#: libvips/arithmetic/clamp.c:162 +msgid "Min" msgstr "" -#: ../libvips/arithmetic/min.c:482 ../libvips/arithmetic/max.c:481 -msgid "Array of vertical positions" +#: libvips/arithmetic/clamp.c:163 +msgid "Minimum value" msgstr "" -#: ../libvips/arithmetic/sum.c:141 -msgid "sum an array of images" +#: libvips/arithmetic/clamp.c:169 +msgid "Max" msgstr "" -#: ../libvips/arithmetic/stats.c:412 ../libvips/arithmetic/avg.c:206 -msgid "find image average" +#: libvips/arithmetic/clamp.c:170 +msgid "Maximum value" msgstr "" -#: ../libvips/arithmetic/stats.c:421 ../libvips/arithmetic/measure.c:211 -msgid "Output array of statistics" +#: libvips/arithmetic/complex.c:251 +msgid "perform a complex operation on an image" msgstr "" -#: ../libvips/arithmetic/project.c:322 -msgid "find image projections" +#: libvips/arithmetic/complex.c:259 libvips/arithmetic/complex.c:772 +msgid "Complex to perform" msgstr "" -#: ../libvips/arithmetic/project.c:330 ../libvips/arithmetic/profile.c:300 -msgid "Columns" +#: libvips/arithmetic/complex.c:531 +msgid "complex binary operations on two images" msgstr "" -#: ../libvips/arithmetic/project.c:331 -msgid "Sums of columns" +#: libvips/arithmetic/complex.c:539 +msgid "Binary complex operation to perform" msgstr "" -#: ../libvips/arithmetic/project.c:336 ../libvips/arithmetic/profile.c:306 -msgid "Rows" +#: libvips/arithmetic/complex.c:762 +msgid "get a component from a complex image" msgstr "" -#: ../libvips/arithmetic/project.c:337 -msgid "Sums of rows" +#: libvips/arithmetic/complex.c:978 +msgid "form a complex image from two real images" msgstr "" -#: ../libvips/arithmetic/hough_line.c:135 -msgid "find hough line transform" +#: libvips/arithmetic/deviate.c:229 +msgid "find image standard deviation" msgstr "" -#: ../libvips/arithmetic/hough_line.c:142 ../libvips/arithmetic/measure.c:244 -#: ../libvips/conversion/embed.c:583 ../libvips/conversion/copy.c:284 -#: ../libvips/conversion/extract.c:219 ../libvips/create/xyz.c:193 -#: ../libvips/create/logmat.c:208 ../libvips/create/worley.c:310 -#: ../libvips/create/gaussnoise.c:172 ../libvips/create/perlin.c:297 -#: ../libvips/create/point.c:143 ../libvips/create/fractsurf.c:102 -#: ../libvips/create/text.c:297 ../libvips/create/black.c:129 -#: ../libvips/draw/draw_flood.c:593 ../libvips/foreign/rawload.c:123 -#: ../libvips/histogram/stdif.c:308 ../libvips/histogram/hist_local.c:370 -#: ../libvips/iofuncs/image.c:1130 ../libvips/morphology/rank.c:419 -msgid "Width" +#: libvips/arithmetic/divide.c:210 +msgid "divide two images" msgstr "" -#: ../libvips/arithmetic/hough_line.c:143 -msgid "horizontal size of parameter space" +#: libvips/arithmetic/find_trim.c:183 +msgid "search an image for non-edge areas" +msgstr "" + +#: libvips/arithmetic/find_trim.c:189 libvips/arithmetic/getpoint.c:153 +#: libvips/arithmetic/measure.c:195 libvips/arithmetic/nary.c:87 +#: libvips/arithmetic/statistic.c:167 libvips/arithmetic/unary.c:88 +#: libvips/colour/CMYK2XYZ.c:120 libvips/colour/colour.c:480 +#: libvips/colour/colour.c:573 libvips/colour/colourspace.c:557 +#: libvips/colour/scRGB2BW.c:237 libvips/colour/scRGB2sRGB.c:270 +#: libvips/colour/scRGB2XYZ.c:191 libvips/colour/sRGB2scRGB.c:288 +#: libvips/colour/XYZ2CMYK.c:119 libvips/colour/XYZ2scRGB.c:200 +#: libvips/conversion/addalpha.c:90 libvips/conversion/arrayjoin.c:394 +#: libvips/conversion/autorot.c:207 libvips/conversion/bandbool.c:232 +#: libvips/conversion/bandfold.c:161 libvips/conversion/bandjoin.c:201 +#: libvips/conversion/bandjoin.c:436 libvips/conversion/bandmean.c:212 +#: libvips/conversion/bandrank.c:254 libvips/conversion/bandunfold.c:164 +#: libvips/conversion/byteswap.c:238 libvips/conversion/cache.c:108 +#: libvips/conversion/cast.c:530 libvips/conversion/copy.c:271 +#: libvips/conversion/embed.c:568 libvips/conversion/extract.c:194 +#: libvips/conversion/extract.c:432 libvips/conversion/falsecolour.c:380 +#: libvips/conversion/flatten.c:419 libvips/conversion/flip.c:240 +#: libvips/conversion/gamma.c:142 libvips/conversion/grid.c:199 +#: libvips/conversion/msb.c:247 libvips/conversion/premultiply.c:261 +#: libvips/conversion/recomb.c:224 libvips/conversion/replicate.c:196 +#: libvips/conversion/rot45.c:268 libvips/conversion/rot.c:365 +#: libvips/conversion/scale.c:155 libvips/conversion/sequential.c:243 +#: libvips/conversion/smartcrop.c:433 libvips/conversion/subsample.c:267 +#: libvips/conversion/tilecache.c:398 libvips/conversion/transpose3d.c:167 +#: libvips/conversion/unpremultiply.c:323 libvips/conversion/wrap.c:119 +#: libvips/conversion/zoom.c:373 libvips/convolution/canny.c:442 +#: libvips/convolution/convolution.c:128 libvips/convolution/correlation.c:150 +#: libvips/convolution/edge.c:217 libvips/convolution/gaussblur.c:132 +#: libvips/convolution/sharpen.c:322 libvips/create/buildlut.c:263 +#: libvips/create/invertlut.c:288 libvips/foreign/foreign.c:1894 +#: libvips/freqfilt/freqfilt.c:98 libvips/histogram/hist_entropy.c:111 +#: libvips/histogram/hist_equal.c:114 libvips/histogram/hist_ismonotonic.c:118 +#: libvips/histogram/hist_local.c:361 libvips/histogram/hist_match.c:161 +#: libvips/histogram/hist_norm.c:141 libvips/histogram/hist_plot.c:333 +#: libvips/histogram/hist_unary.c:88 libvips/histogram/maplut.c:744 +#: libvips/histogram/percent.c:109 libvips/histogram/stdif.c:294 +#: libvips/iofuncs/ginputsource.c:274 libvips/iofuncs/sbuf.c:88 +#: libvips/iofuncs/system.c:277 libvips/morphology/morphology.c:121 +#: libvips/mosaicing/global_balance.c:1924 libvips/mosaicing/matrixinvert.c:443 +#: libvips/mosaicing/remosaic.c:164 libvips/resample/resample.c:140 +#: libvips/resample/thumbnail.c:1782 +msgid "Input" msgstr "" -#: ../libvips/arithmetic/hough_line.c:149 ../libvips/arithmetic/measure.c:251 -#: ../libvips/conversion/embed.c:590 ../libvips/conversion/copy.c:291 -#: ../libvips/conversion/extract.c:226 ../libvips/create/xyz.c:200 -#: ../libvips/create/worley.c:317 ../libvips/create/gaussnoise.c:179 -#: ../libvips/create/perlin.c:304 ../libvips/create/point.c:150 -#: ../libvips/create/fractsurf.c:109 ../libvips/create/black.c:136 -#: ../libvips/draw/draw_flood.c:600 ../libvips/foreign/rawload.c:130 -#: ../libvips/histogram/stdif.c:315 ../libvips/histogram/hist_local.c:377 -#: ../libvips/iofuncs/image.c:1137 ../libvips/morphology/rank.c:426 -msgid "Height" +#: libvips/arithmetic/find_trim.c:190 +msgid "Image to find_trim" msgstr "" -#: ../libvips/arithmetic/hough_line.c:150 -msgid "Vertical size of parameter space" +#: libvips/arithmetic/find_trim.c:195 libvips/histogram/percent.c:122 +msgid "Threshold" msgstr "" -#: ../libvips/arithmetic/binary.c:89 -msgid "binary operations" +#: libvips/arithmetic/find_trim.c:196 +msgid "Object threshold" msgstr "" -#: ../libvips/arithmetic/binary.c:96 ../libvips/arithmetic/measure.c:230 -#: ../libvips/colour/colour.c:699 ../libvips/conversion/extract.c:205 -#: ../libvips/draw/draw_smudge.c:197 ../libvips/draw/draw_flood.c:579 -#: ../libvips/draw/draw_rect.c:173 -msgid "Left" +#: libvips/arithmetic/find_trim.c:202 libvips/conversion/arrayjoin.c:415 +#: libvips/conversion/embed.c:595 libvips/conversion/flatten.c:425 +#: libvips/conversion/insert.c:499 libvips/conversion/join.c:270 +#: libvips/foreign/foreign.c:1908 libvips/foreign/pdfiumload.c:723 +#: libvips/foreign/popplerload.c:573 libvips/resample/affine.c:699 +#: libvips/resample/mapim.c:574 libvips/resample/similarity.c:133 +msgid "Background" msgstr "" -#: ../libvips/arithmetic/binary.c:97 -msgid "Left-hand image argument" +#: libvips/arithmetic/find_trim.c:203 libvips/conversion/embed.c:596 +msgid "Color for background pixels" msgstr "" -#: ../libvips/arithmetic/binary.c:102 ../libvips/colour/colour.c:705 -msgid "Right" +#: libvips/arithmetic/find_trim.c:209 +msgid "Line art mode" msgstr "" -#: ../libvips/arithmetic/binary.c:103 -msgid "Right-hand image argument" +#: libvips/arithmetic/find_trim.c:210 +msgid "Enable line art mode" msgstr "" -#: ../libvips/arithmetic/deviate.c:213 -msgid "find image standard deviation" +#: libvips/arithmetic/find_trim.c:217 +msgid "Left edge of image" msgstr "" -#: ../libvips/arithmetic/max.c:430 -msgid "find image maximum" +#: libvips/arithmetic/find_trim.c:223 libvips/arithmetic/measure.c:228 +#: libvips/conversion/extract.c:207 libvips/draw/draw_flood.c:600 +#: libvips/draw/draw_rect.c:180 libvips/draw/draw_smudge.c:222 +msgid "Top" msgstr "" -#: ../libvips/arithmetic/max.c:446 -msgid "Horizontal position of maximum" +#: libvips/arithmetic/find_trim.c:224 libvips/arithmetic/measure.c:229 +#: libvips/conversion/extract.c:208 +msgid "Top edge of extract area" msgstr "" -#: ../libvips/arithmetic/max.c:453 -msgid "Vertical position of maximum" +#: libvips/arithmetic/find_trim.c:230 libvips/arithmetic/hough_line.c:147 +#: libvips/arithmetic/measure.c:235 libvips/conversion/copy.c:284 +#: libvips/conversion/embed.c:574 libvips/conversion/extract.c:214 +#: libvips/conversion/smartcrop.c:439 libvips/create/black.c:140 +#: libvips/create/fractsurf.c:104 libvips/create/gaussnoise.c:167 +#: libvips/create/logmat.c:208 libvips/create/perlin.c:294 +#: libvips/create/point.c:141 libvips/create/sdf.c:304 +#: libvips/create/text.c:567 libvips/create/worley.c:307 +#: libvips/create/xyz.c:191 libvips/draw/draw_flood.c:607 +#: libvips/draw/draw_rect.c:187 libvips/draw/draw_smudge.c:229 +#: libvips/foreign/rawload.c:146 libvips/histogram/hist_local.c:373 +#: libvips/histogram/stdif.c:308 libvips/iofuncs/image.c:1102 +#: libvips/morphology/rank.c:570 +msgid "Width" msgstr "" -#: ../libvips/arithmetic/max.c:460 -msgid "Number of maximum values to find" +#: libvips/arithmetic/find_trim.c:231 libvips/arithmetic/measure.c:236 +#: libvips/conversion/extract.c:215 libvips/conversion/smartcrop.c:440 +msgid "Width of extract area" msgstr "" -#: ../libvips/arithmetic/statistic.c:161 -msgid "VIPS statistic operations" +#: libvips/arithmetic/find_trim.c:237 libvips/arithmetic/hough_line.c:154 +#: libvips/arithmetic/measure.c:242 libvips/conversion/copy.c:291 +#: libvips/conversion/embed.c:581 libvips/conversion/extract.c:221 +#: libvips/conversion/smartcrop.c:446 libvips/create/black.c:147 +#: libvips/create/fractsurf.c:111 libvips/create/gaussnoise.c:174 +#: libvips/create/perlin.c:301 libvips/create/point.c:148 +#: libvips/create/sdf.c:311 libvips/create/text.c:574 +#: libvips/create/worley.c:314 libvips/create/xyz.c:198 +#: libvips/draw/draw_flood.c:614 libvips/draw/draw_rect.c:194 +#: libvips/draw/draw_smudge.c:236 libvips/foreign/rawload.c:153 +#: libvips/histogram/hist_local.c:380 libvips/histogram/stdif.c:315 +#: libvips/iofuncs/image.c:1109 libvips/morphology/rank.c:577 +msgid "Height" msgstr "" -#: ../libvips/arithmetic/statistic.c:167 ../libvips/arithmetic/nary.c:87 -#: ../libvips/arithmetic/unary.c:88 ../libvips/colour/colour.c:493 -#: ../libvips/colour/colour.c:587 ../libvips/colour/sRGB2scRGB.c:243 -#: ../libvips/colour/scRGB2BW.c:237 ../libvips/colour/scRGB2sRGB.c:265 -#: ../libvips/colour/colourspace.c:586 ../libvips/conversion/embed.c:563 -#: ../libvips/conversion/zoom.c:383 ../libvips/conversion/replicate.c:196 -#: ../libvips/conversion/bandfold.c:160 ../libvips/conversion/wrap.c:119 -#: ../libvips/conversion/arrayjoin.c:304 -#: ../libvips/conversion/unpremultiply.c:268 ../libvips/conversion/flip.c:240 -#: ../libvips/conversion/flatten.c:386 ../libvips/conversion/copy.c:271 -#: ../libvips/conversion/bandjoin.c:176 ../libvips/conversion/bandjoin.c:395 -#: ../libvips/conversion/rot45.c:267 ../libvips/conversion/msb.c:244 -#: ../libvips/conversion/extract.c:199 ../libvips/conversion/extract.c:422 -#: ../libvips/conversion/cast.c:548 ../libvips/conversion/bandunfold.c:163 -#: ../libvips/conversion/tilecache.c:416 ../libvips/conversion/sequential.c:327 -#: ../libvips/conversion/premultiply.c:259 ../libvips/conversion/bandmean.c:198 -#: ../libvips/conversion/byteswap.c:206 ../libvips/conversion/subsample.c:274 -#: ../libvips/conversion/bandbool.c:214 ../libvips/conversion/recomb.c:207 -#: ../libvips/conversion/cache.c:101 ../libvips/conversion/grid.c:199 -#: ../libvips/conversion/scale.c:151 ../libvips/conversion/autorot.c:178 -#: ../libvips/conversion/rot.c:359 ../libvips/conversion/bandrank.c:244 -#: ../libvips/convolution/convolution.c:129 -#: ../libvips/convolution/gaussblur.c:119 ../libvips/convolution/sharpen.c:313 -#: ../libvips/convolution/correlation.c:151 ../libvips/create/invertlut.c:289 -#: ../libvips/create/buildlut.c:261 ../libvips/foreign/foreign.c:1522 -#: ../libvips/histogram/hist_match.c:161 ../libvips/histogram/hist_equal.c:108 -#: ../libvips/histogram/stdif.c:294 ../libvips/histogram/hist_entropy.c:113 -#: ../libvips/histogram/hist_ismonotonic.c:117 -#: ../libvips/histogram/hist_norm.c:141 ../libvips/histogram/hist_plot.c:342 -#: ../libvips/histogram/hist_unary.c:89 ../libvips/histogram/hist_local.c:358 -#: ../libvips/histogram/percent.c:110 ../libvips/histogram/maplut.c:694 -#: ../libvips/iofuncs/system.c:277 ../libvips/morphology/morphology.c:117 -#: ../libvips/mosaicing/im_remosaic.c:164 -#: ../libvips/mosaicing/global_balance.c:1771 -#: ../libvips/resample/resample.c:132 -msgid "Input" +#: libvips/arithmetic/find_trim.c:238 libvips/arithmetic/measure.c:243 +#: libvips/conversion/extract.c:222 libvips/conversion/smartcrop.c:447 +msgid "Height of extract area" msgstr "" -#: ../libvips/arithmetic/statistic.c:168 ../libvips/arithmetic/getpoint.c:141 -#: ../libvips/arithmetic/unary.c:89 ../libvips/colour/colour.c:494 -#: ../libvips/colour/colour.c:588 ../libvips/colour/sRGB2scRGB.c:244 -#: ../libvips/colour/scRGB2BW.c:238 ../libvips/colour/scRGB2sRGB.c:266 -#: ../libvips/colour/colourspace.c:587 ../libvips/conversion/embed.c:564 -#: ../libvips/conversion/zoom.c:384 ../libvips/conversion/replicate.c:197 -#: ../libvips/conversion/bandfold.c:161 ../libvips/conversion/wrap.c:120 -#: ../libvips/conversion/unpremultiply.c:269 ../libvips/conversion/flip.c:241 -#: ../libvips/conversion/flatten.c:387 ../libvips/conversion/copy.c:272 -#: ../libvips/conversion/bandjoin.c:396 ../libvips/conversion/rot45.c:268 -#: ../libvips/conversion/msb.c:245 ../libvips/conversion/extract.c:200 -#: ../libvips/conversion/extract.c:423 ../libvips/conversion/cast.c:549 -#: ../libvips/conversion/bandunfold.c:164 ../libvips/conversion/tilecache.c:417 -#: ../libvips/conversion/sequential.c:328 -#: ../libvips/conversion/premultiply.c:260 -#: ../libvips/conversion/falsecolour.c:382 ../libvips/conversion/byteswap.c:207 -#: ../libvips/conversion/subsample.c:275 ../libvips/conversion/gamma.c:144 -#: ../libvips/conversion/cache.c:102 ../libvips/conversion/grid.c:200 -#: ../libvips/conversion/scale.c:152 ../libvips/conversion/autorot.c:179 -#: ../libvips/conversion/rot.c:360 ../libvips/convolution/gaussblur.c:120 -#: ../libvips/convolution/sharpen.c:314 ../libvips/freqfilt/freqfilt.c:99 -#: ../libvips/histogram/hist_equal.c:109 ../libvips/histogram/stdif.c:295 -#: ../libvips/histogram/hist_norm.c:142 ../libvips/histogram/hist_plot.c:343 -#: ../libvips/histogram/hist_unary.c:90 ../libvips/histogram/hist_local.c:359 -#: ../libvips/histogram/percent.c:111 ../libvips/histogram/maplut.c:695 -#: ../libvips/mosaicing/im_remosaic.c:165 -#: ../libvips/mosaicing/global_balance.c:1772 +#: libvips/arithmetic/getpoint.c:149 +msgid "read a point from an image" +msgstr "" + +#: libvips/arithmetic/getpoint.c:154 libvips/arithmetic/statistic.c:168 +#: libvips/arithmetic/unary.c:89 libvips/colour/CMYK2XYZ.c:121 +#: libvips/colour/colour.c:481 libvips/colour/colour.c:574 +#: libvips/colour/colourspace.c:558 libvips/colour/scRGB2BW.c:238 +#: libvips/colour/scRGB2sRGB.c:271 libvips/colour/scRGB2XYZ.c:192 +#: libvips/colour/sRGB2scRGB.c:289 libvips/colour/XYZ2CMYK.c:120 +#: libvips/colour/XYZ2scRGB.c:201 libvips/conversion/addalpha.c:91 +#: libvips/conversion/autorot.c:208 libvips/conversion/bandfold.c:162 +#: libvips/conversion/bandjoin.c:437 libvips/conversion/bandunfold.c:165 +#: libvips/conversion/byteswap.c:239 libvips/conversion/cache.c:109 +#: libvips/conversion/cast.c:531 libvips/conversion/copy.c:272 +#: libvips/conversion/embed.c:569 libvips/conversion/extract.c:195 +#: libvips/conversion/extract.c:433 libvips/conversion/falsecolour.c:381 +#: libvips/conversion/flatten.c:420 libvips/conversion/flip.c:241 +#: libvips/conversion/gamma.c:143 libvips/conversion/grid.c:200 +#: libvips/conversion/msb.c:248 libvips/conversion/premultiply.c:262 +#: libvips/conversion/replicate.c:197 libvips/conversion/rot45.c:269 +#: libvips/conversion/rot.c:366 libvips/conversion/scale.c:156 +#: libvips/conversion/sequential.c:244 libvips/conversion/smartcrop.c:434 +#: libvips/conversion/subsample.c:268 libvips/conversion/tilecache.c:399 +#: libvips/conversion/transpose3d.c:168 libvips/conversion/unpremultiply.c:324 +#: libvips/conversion/wrap.c:120 libvips/conversion/zoom.c:374 +#: libvips/convolution/canny.c:443 libvips/convolution/edge.c:218 +#: libvips/convolution/gaussblur.c:133 libvips/convolution/sharpen.c:323 +#: libvips/freqfilt/freqfilt.c:99 libvips/histogram/hist_equal.c:115 +#: libvips/histogram/hist_local.c:362 libvips/histogram/hist_norm.c:142 +#: libvips/histogram/hist_plot.c:334 libvips/histogram/hist_unary.c:89 +#: libvips/histogram/maplut.c:745 libvips/histogram/percent.c:110 +#: libvips/histogram/stdif.c:295 libvips/mosaicing/global_balance.c:1925 +#: libvips/mosaicing/remosaic.c:165 msgid "Input image" msgstr "" -#: ../libvips/arithmetic/nary.c:80 -msgid "nary operations" +#: libvips/arithmetic/getpoint.c:159 libvips/arithmetic/max.c:480 +#: libvips/arithmetic/min.c:480 +msgid "Output array" msgstr "" -#: ../libvips/arithmetic/nary.c:88 ../libvips/conversion/arrayjoin.c:305 -#: ../libvips/conversion/bandjoin.c:177 ../libvips/conversion/bandrank.c:245 -#: ../libvips/iofuncs/system.c:278 -msgid "Array of input images" +#: libvips/arithmetic/getpoint.c:160 libvips/arithmetic/max.c:481 +#: libvips/arithmetic/min.c:481 +msgid "Array of output values" msgstr "" -#: ../libvips/arithmetic/invert.c:165 -msgid "invert an image" +#: libvips/arithmetic/getpoint.c:166 libvips/arithmetic/max.c:459 +#: libvips/arithmetic/min.c:459 libvips/conversion/composite.cpp:1733 +#: libvips/conversion/embed.c:656 libvips/conversion/wrap.c:125 +#: libvips/draw/draw_flood.c:566 libvips/draw/draw_image.c:275 +#: libvips/draw/draw_mask.c:338 +msgid "x" msgstr "" -#: ../libvips/arithmetic/remainder.c:174 -msgid "remainder after integer division of two images" +#: libvips/arithmetic/getpoint.c:167 libvips/arithmetic/getpoint.c:174 +msgid "Point to read" msgstr "" -#: ../libvips/arithmetic/remainder.c:324 -msgid "remainder after integer division of an image and a constant" +#: libvips/arithmetic/getpoint.c:173 libvips/arithmetic/max.c:466 +#: libvips/arithmetic/min.c:466 libvips/conversion/composite.cpp:1740 +#: libvips/conversion/embed.c:663 libvips/conversion/wrap.c:132 +#: libvips/draw/draw_flood.c:573 libvips/draw/draw_image.c:282 +#: libvips/draw/draw_mask.c:345 +msgid "y" msgstr "" -#: ../libvips/arithmetic/boolean.c:210 -msgid "boolean operation on two images" +#: libvips/arithmetic/getpoint.c:180 +msgid "unpack_complex" msgstr "" -#: ../libvips/arithmetic/boolean.c:218 ../libvips/arithmetic/boolean.c:521 -#: ../libvips/arithmetic/relational.c:224 -#: ../libvips/arithmetic/relational.c:562 ../libvips/arithmetic/math2.c:205 -#: ../libvips/arithmetic/math2.c:404 ../libvips/arithmetic/complex.c:255 -#: ../libvips/arithmetic/complex.c:548 ../libvips/arithmetic/complex.c:763 -#: ../libvips/arithmetic/math.c:214 ../libvips/conversion/bandbool.c:220 -#: ../tools/vips.c:1070 -msgid "Operation" +#: libvips/arithmetic/getpoint.c:181 +msgid "Complex pixels should be unpacked" msgstr "" -#: ../libvips/arithmetic/boolean.c:219 ../libvips/arithmetic/boolean.c:522 -#: ../libvips/conversion/bandbool.c:221 -msgid "boolean to perform" +#: libvips/arithmetic/hist_find.c:422 +msgid "find image histogram" msgstr "" -#: ../libvips/arithmetic/boolean.c:513 -msgid "boolean operations against a constant" +#: libvips/arithmetic/hist_find.c:432 +#: libvips/arithmetic/hist_find_indexed.c:476 +#: libvips/arithmetic/hist_find_ndim.c:314 +msgid "Output histogram" msgstr "" -#: ../libvips/arithmetic/sign.c:152 -msgid "unit vector of pixel" +#: libvips/arithmetic/hist_find.c:437 libvips/conversion/extract.c:438 +#: libvips/conversion/msb.c:253 libvips/histogram/hist_equal.c:126 +#: libvips/histogram/maplut.c:762 +msgid "Band" +msgstr "" + +#: libvips/arithmetic/hist_find.c:438 +msgid "Find histogram of band" +msgstr "" + +#: libvips/arithmetic/hist_find_indexed.c:461 +msgid "find indexed image histogram" +msgstr "" + +#: libvips/arithmetic/hist_find_indexed.c:469 libvips/conversion/bandrank.c:261 +#: libvips/histogram/case.c:239 libvips/morphology/rank.c:584 +#: libvips/resample/mapim.c:555 +msgid "Index" +msgstr "" + +#: libvips/arithmetic/hist_find_indexed.c:470 libvips/histogram/case.c:240 +msgid "Index image" +msgstr "" + +#: libvips/arithmetic/hist_find_indexed.c:481 libvips/convolution/compass.c:177 +msgid "Combine" +msgstr "" + +#: libvips/arithmetic/hist_find_indexed.c:482 +msgid "Combine bins like this" +msgstr "" + +#: libvips/arithmetic/hist_find_ndim.c:150 +msgid "image is not 1 - 3 bands" msgstr "" -#: ../libvips/arithmetic/hist_find_ndim.c:112 +#: libvips/arithmetic/hist_find_ndim.c:159 #, c-format msgid "bins out of range [1,%d]" msgstr "" -#: ../libvips/arithmetic/hist_find_ndim.c:289 +#: libvips/arithmetic/hist_find_ndim.c:304 msgid "find n-dimensional image histogram" msgstr "" -#: ../libvips/arithmetic/hist_find_ndim.c:299 -#: ../libvips/arithmetic/hist_find.c:451 -#: ../libvips/arithmetic/hist_find_indexed.c:392 -msgid "Output histogram" -msgstr "" - -#: ../libvips/arithmetic/hist_find_ndim.c:304 +#: libvips/arithmetic/hist_find_ndim.c:319 msgid "Bins" msgstr "" -#: ../libvips/arithmetic/hist_find_ndim.c:305 +#: libvips/arithmetic/hist_find_ndim.c:320 msgid "Number of bins in each dimension" msgstr "" -#: ../libvips/arithmetic/multiply.c:173 -msgid "multiply two images" +#: libvips/arithmetic/hough.c:170 +msgid "find hough transform" msgstr "" -#: ../libvips/arithmetic/hough_circle.c:113 +#: libvips/arithmetic/hough_circle.c:115 msgid "parameters out of range" msgstr "" -#: ../libvips/arithmetic/hough_circle.c:233 +#: libvips/arithmetic/hough_circle.c:226 msgid "find hough circle transform" msgstr "" -#: ../libvips/arithmetic/hough_circle.c:240 ../libvips/foreign/pdfload.c:489 -#: ../libvips/foreign/svgload.c:290 ../libvips/mosaicing/mosaic.c:275 -#: ../libvips/resample/similarity.c:171 +#: libvips/arithmetic/hough_circle.c:233 libvips/foreign/pdfiumload.c:716 +#: libvips/foreign/popplerload.c:566 libvips/foreign/svgload.c:724 +#: libvips/foreign/webpload.c:192 libvips/mosaicing/mosaic.c:274 +#: libvips/resample/similarity.c:200 msgid "Scale" msgstr "" -#: ../libvips/arithmetic/hough_circle.c:241 +#: libvips/arithmetic/hough_circle.c:234 msgid "Scale down dimensions by this factor" msgstr "" -#: ../libvips/arithmetic/hough_circle.c:247 +#: libvips/arithmetic/hough_circle.c:240 msgid "Min radius" msgstr "" -#: ../libvips/arithmetic/hough_circle.c:248 +#: libvips/arithmetic/hough_circle.c:241 msgid "Smallest radius to search for" msgstr "" -#: ../libvips/arithmetic/hough_circle.c:254 +#: libvips/arithmetic/hough_circle.c:247 msgid "Max radius" msgstr "" -#: ../libvips/arithmetic/hough_circle.c:255 +#: libvips/arithmetic/hough_circle.c:248 msgid "Largest radius to search for" msgstr "" -#: ../libvips/arithmetic/measure.c:168 -#, c-format -msgid "%s: patch %d x %d, band %d: avg = %g, sdev = %g" +#: libvips/arithmetic/hough_line.c:140 +msgid "find hough line transform" msgstr "" -#: ../libvips/arithmetic/measure.c:200 -msgid "measure a set of patches on a color chart" -msgstr "measure a set of patches on a colour chart" +#: libvips/arithmetic/hough_line.c:148 +msgid "Horizontal size of parameter space" +msgstr "" -#: ../libvips/arithmetic/measure.c:204 ../libvips/arithmetic/getpoint.c:140 -#: ../libvips/conversion/falsecolour.c:381 ../libvips/conversion/gamma.c:143 -#: ../libvips/freqfilt/freqfilt.c:98 -msgid "in" +#: libvips/arithmetic/hough_line.c:155 +msgid "Vertical size of parameter space" msgstr "" -#: ../libvips/arithmetic/measure.c:205 -msgid "Image to measure" +#: libvips/arithmetic/invert.c:178 +msgid "invert an image" msgstr "" -#: ../libvips/arithmetic/measure.c:216 ../libvips/conversion/replicate.c:202 -#: ../libvips/conversion/arrayjoin.c:311 ../libvips/conversion/grid.c:212 -msgid "Across" +#: libvips/arithmetic/linear.c:446 +msgid "calculate (a * in + b)" msgstr "" -#: ../libvips/arithmetic/measure.c:217 -msgid "Number of patches across chart" +#: libvips/arithmetic/linear.c:454 libvips/create/sdf.c:332 +msgid "a" msgstr "" -#: ../libvips/arithmetic/measure.c:223 ../libvips/conversion/replicate.c:209 -#: ../libvips/conversion/grid.c:219 -msgid "Down" +#: libvips/arithmetic/linear.c:455 +msgid "Multiply by this" msgstr "" -#: ../libvips/arithmetic/measure.c:224 -msgid "Number of patches down chart" +#: libvips/arithmetic/linear.c:461 libvips/create/sdf.c:339 +msgid "b" msgstr "" -#: ../libvips/arithmetic/measure.c:231 ../libvips/conversion/extract.c:206 -msgid "Left edge of extract area" +#: libvips/arithmetic/linear.c:462 +msgid "Add this" msgstr "" -#: ../libvips/arithmetic/measure.c:237 ../libvips/conversion/extract.c:212 -#: ../libvips/draw/draw_flood.c:586 -msgid "Top" +#: libvips/arithmetic/linear.c:468 +msgid "uchar" msgstr "" -#: ../libvips/arithmetic/measure.c:238 ../libvips/conversion/extract.c:213 -msgid "Top edge of extract area" +#: libvips/arithmetic/linear.c:469 +msgid "Output should be uchar" msgstr "" -#: ../libvips/arithmetic/measure.c:245 ../libvips/conversion/extract.c:220 -msgid "Width of extract area" +#: libvips/arithmetic/math2.c:233 +msgid "binary math operations" msgstr "" -#: ../libvips/arithmetic/measure.c:252 ../libvips/conversion/extract.c:227 -msgid "Height of extract area" +#: libvips/arithmetic/math2.c:242 libvips/arithmetic/math2.c:472 +#: libvips/arithmetic/math.c:262 +msgid "Math to perform" msgstr "" -#: ../libvips/arithmetic/hist_find.c:441 -msgid "find image histogram" +#: libvips/arithmetic/math2.c:463 +msgid "binary math operations with a constant" msgstr "" -#: ../libvips/arithmetic/hist_find.c:456 ../libvips/conversion/msb.c:250 -#: ../libvips/conversion/extract.c:428 ../libvips/histogram/hist_equal.c:120 -msgid "Band" +#: libvips/arithmetic/math.c:253 +msgid "apply a math operation to an image" msgstr "" -#: ../libvips/arithmetic/hist_find.c:457 -msgid "Find histogram of band" +#: libvips/arithmetic/max.c:444 +msgid "find image maximum" msgstr "" -#: ../libvips/arithmetic/getpoint.c:136 -msgid "read a point from an image" +#: libvips/arithmetic/max.c:460 +msgid "Horizontal position of maximum" msgstr "" -#: ../libvips/arithmetic/getpoint.c:154 ../libvips/arithmetic/getpoint.c:161 -msgid "Point to read" +#: libvips/arithmetic/max.c:467 +msgid "Vertical position of maximum" msgstr "" -#: ../libvips/arithmetic/add.c:172 -msgid "add two images" +#: libvips/arithmetic/max.c:473 libvips/arithmetic/min.c:473 +#: libvips/create/identity.c:157 libvips/create/invertlut.c:294 +#: libvips/resample/thumbnail.c:988 +msgid "Size" msgstr "" -#: ../libvips/arithmetic/divide.c:225 -msgid "divide two images" +#: libvips/arithmetic/max.c:474 +msgid "Number of maximum values to find" msgstr "" -#: ../libvips/arithmetic/relational.c:216 -msgid "relational operation on two images" +#: libvips/arithmetic/max.c:487 libvips/arithmetic/min.c:487 +msgid "x array" msgstr "" -#: ../libvips/arithmetic/relational.c:225 -#: ../libvips/arithmetic/relational.c:563 -msgid "relational to perform" +#: libvips/arithmetic/max.c:488 libvips/arithmetic/min.c:488 +msgid "Array of horizontal positions" msgstr "" -#: ../libvips/arithmetic/relational.c:553 -msgid "relational operations against a constant" +#: libvips/arithmetic/max.c:494 libvips/arithmetic/min.c:494 +msgid "y array" msgstr "" -#: ../libvips/arithmetic/hough.c:176 -msgid "find hough transform" +#: libvips/arithmetic/max.c:495 libvips/arithmetic/min.c:495 +msgid "Array of vertical positions" msgstr "" -#: ../libvips/arithmetic/hough.c:186 ../libvips/arithmetic/arithmetic.c:640 -#: ../libvips/colour/colour.c:428 ../libvips/colour/sRGB2scRGB.c:250 -#: ../libvips/colour/scRGB2BW.c:244 ../libvips/colour/scRGB2sRGB.c:272 -#: ../libvips/colour/colourspace.c:593 ../libvips/conversion/conversion.c:201 -#: ../libvips/convolution/convolution.c:136 -#: ../libvips/convolution/gaussblur.c:126 ../libvips/convolution/sharpen.c:320 -#: ../libvips/convolution/correlation.c:164 ../libvips/create/create.c:102 -#: ../libvips/foreign/foreign.c:985 ../libvips/freqfilt/freqfilt.c:105 -#: ../libvips/histogram/hist_equal.c:115 ../libvips/histogram/stdif.c:301 -#: ../libvips/histogram/histogram.c:233 ../libvips/histogram/hist_norm.c:148 -#: ../libvips/histogram/hist_plot.c:349 ../libvips/histogram/hist_local.c:365 -#: ../libvips/histogram/maplut.c:701 ../libvips/iofuncs/system.c:285 -#: ../libvips/morphology/morph.c:144 ../libvips/morphology/rank.c:414 -#: ../libvips/mosaicing/merge.c:122 ../libvips/mosaicing/im_remosaic.c:171 -#: ../libvips/mosaicing/global_balance.c:1778 ../libvips/mosaicing/mosaic.c:193 -#: ../libvips/mosaicing/match.c:217 ../libvips/mosaicing/mosaic1.c:502 -#: ../libvips/resample/resample.c:139 ../libvips/resample/thumbnail.c:521 -msgid "Output image" +#: libvips/arithmetic/maxpair.c:151 +msgid "maximum of a pair of images" msgstr "" -#: ../libvips/arithmetic/arithmetic.c:378 +#: libvips/arithmetic/measure.c:164 #, c-format -msgid "not one band or %d bands" +msgid "%s: patch %d x %d, band %d: avg = %g, sdev = %g" msgstr "" -#: ../libvips/arithmetic/arithmetic.c:382 -msgid "bad bands" +#: libvips/arithmetic/measure.c:191 +msgid "measure a set of patches on a color chart" +msgstr "measure a set of patches on a colour chart" + +#: libvips/arithmetic/measure.c:196 +msgid "Image to measure" msgstr "" -#: ../libvips/arithmetic/arithmetic.c:572 ../libvips/colour/colour.c:297 -#: ../libvips/conversion/bandary.c:140 ../libvips/conversion/bandrank.c:204 -msgid "too many input images" +#: libvips/arithmetic/measure.c:202 libvips/arithmetic/stats.c:443 +msgid "Output array of statistics" msgstr "" -#: ../libvips/arithmetic/arithmetic.c:633 -msgid "arithmetic operations" +#: libvips/arithmetic/measure.c:207 libvips/conversion/arrayjoin.c:401 +#: libvips/conversion/grid.c:212 libvips/conversion/replicate.c:202 +msgid "Across" msgstr "" -#: ../libvips/arithmetic/abs.c:230 -msgid "absolute value of an image" +#: libvips/arithmetic/measure.c:208 +msgid "Number of patches across chart" msgstr "" -#: ../libvips/arithmetic/linear.c:386 -msgid "calculate (a * in + b)" +#: libvips/arithmetic/measure.c:214 libvips/conversion/grid.c:219 +#: libvips/conversion/replicate.c:209 +msgid "Down" msgstr "" -#: ../libvips/arithmetic/linear.c:394 -msgid "a" +#: libvips/arithmetic/measure.c:215 +msgid "Number of patches down chart" msgstr "" -#: ../libvips/arithmetic/linear.c:395 -msgid "Multiply by this" +#: libvips/arithmetic/measure.c:222 libvips/conversion/extract.c:201 +msgid "Left edge of extract area" msgstr "" -#: ../libvips/arithmetic/linear.c:401 -msgid "b" +#: libvips/arithmetic/min.c:444 +msgid "find image minimum" msgstr "" -#: ../libvips/arithmetic/linear.c:402 -msgid "Add this" +#: libvips/arithmetic/min.c:460 +msgid "Horizontal position of minimum" msgstr "" -#: ../libvips/arithmetic/linear.c:408 -msgid "uchar" +#: libvips/arithmetic/min.c:467 +msgid "Vertical position of minimum" msgstr "" -#: ../libvips/arithmetic/linear.c:409 -msgid "Output should be uchar" +#: libvips/arithmetic/min.c:474 +msgid "Number of minimum values to find" msgstr "" -#: ../libvips/arithmetic/round.c:161 -msgid "perform a round function on an image" +#: libvips/arithmetic/minpair.c:151 +msgid "minimum of a pair of images" msgstr "" -#: ../libvips/arithmetic/round.c:169 -msgid "Round operation" +#: libvips/arithmetic/multiply.c:195 +msgid "multiply two images" msgstr "" -#: ../libvips/arithmetic/round.c:170 -msgid "rounding operation to perform" +#: libvips/arithmetic/nary.c:80 +msgid "nary operations" msgstr "" -#: ../libvips/arithmetic/math2.c:197 -msgid "binary math operations" +#: libvips/arithmetic/nary.c:88 libvips/conversion/arrayjoin.c:395 +#: libvips/conversion/bandjoin.c:202 libvips/conversion/bandrank.c:255 +#: libvips/conversion/composite.cpp:1581 libvips/iofuncs/system.c:278 +msgid "Array of input images" msgstr "" -#: ../libvips/arithmetic/math2.c:206 ../libvips/arithmetic/math2.c:405 -#: ../libvips/arithmetic/math.c:215 -msgid "math to perform" +#: libvips/arithmetic/profile.c:293 +msgid "find image profiles" msgstr "" -#: ../libvips/arithmetic/math2.c:396 -msgid "binary math operations with a constant" +#: libvips/arithmetic/profile.c:301 libvips/arithmetic/project.c:332 +msgid "Columns" msgstr "" -#: ../libvips/arithmetic/unaryconst.c:203 -msgid "unary operations with a constant" +#: libvips/arithmetic/profile.c:302 +msgid "First non-zero pixel in column" msgstr "" -#: ../libvips/arithmetic/unaryconst.c:207 -msgid "c" +#: libvips/arithmetic/profile.c:307 libvips/arithmetic/project.c:338 +msgid "Rows" msgstr "" -#: ../libvips/arithmetic/unaryconst.c:208 -msgid "Array of constants" +#: libvips/arithmetic/profile.c:308 +msgid "First non-zero pixel in row" msgstr "" -#: ../libvips/arithmetic/complex.c:248 -msgid "perform a complex operation on an image" +#: libvips/arithmetic/project.c:324 +msgid "find image projections" msgstr "" -#: ../libvips/arithmetic/complex.c:256 ../libvips/arithmetic/complex.c:764 -msgid "complex to perform" +#: libvips/arithmetic/project.c:333 +msgid "Sums of columns" msgstr "" -#: ../libvips/arithmetic/complex.c:541 -msgid "complex binary operations on two images" +#: libvips/arithmetic/project.c:339 +msgid "Sums of rows" msgstr "" -#: ../libvips/arithmetic/complex.c:549 -msgid "binary complex operation to perform" +#: libvips/arithmetic/relational.c:238 +msgid "relational operation on two images" msgstr "" -#: ../libvips/arithmetic/complex.c:754 -msgid "get a component from a complex image" +#: libvips/arithmetic/relational.c:247 libvips/arithmetic/relational.c:612 +msgid "Relational to perform" msgstr "" -#: ../libvips/arithmetic/complex.c:962 -msgid "form a complex image from two real images" +#: libvips/arithmetic/relational.c:603 +msgid "relational operations against a constant" msgstr "" -#: ../libvips/arithmetic/profile.c:292 -msgid "find image profiles" +#: libvips/arithmetic/remainder.c:192 +msgid "remainder after integer division of two images" msgstr "" -#: ../libvips/arithmetic/profile.c:301 -msgid "First non-zero pixel in column" +#: libvips/arithmetic/remainder.c:353 +msgid "remainder after integer division of an image and a constant" msgstr "" -#: ../libvips/arithmetic/profile.c:307 -msgid "First non-zero pixel in row" +#: libvips/arithmetic/round.c:173 +msgid "perform a round function on an image" msgstr "" -#: ../libvips/arithmetic/unary.c:81 -msgid "unary operations" +#: libvips/arithmetic/round.c:181 +msgid "Round operation" msgstr "" -#: ../libvips/arithmetic/subtract.c:162 -msgid "subtract two images" +#: libvips/arithmetic/round.c:182 +msgid "Rounding operation to perform" msgstr "" -#: ../libvips/arithmetic/hist_find_indexed.c:377 -msgid "find indexed image histogram" +#: libvips/arithmetic/sign.c:174 +msgid "unit vector of pixel" msgstr "" -#: ../libvips/arithmetic/hist_find_indexed.c:385 -#: ../libvips/conversion/bandrank.c:251 ../libvips/resample/mapim.c:412 -msgid "Index" +#: libvips/arithmetic/statistic.c:161 +msgid "VIPS statistic operations" msgstr "" -#: ../libvips/arithmetic/hist_find_indexed.c:386 -msgid "Index image" +#: libvips/arithmetic/stats.c:434 +msgid "find many image stats" msgstr "" -#: ../libvips/arithmetic/math.c:206 -msgid "apply a math operation to an image" +#: libvips/arithmetic/subtract.c:174 +msgid "subtract two images" msgstr "" -#: ../libvips/colour/LabQ2LabS.c:104 -msgid "unpack a LabQ image to short Lab" +#: libvips/arithmetic/sum.c:149 +msgid "sum an array of images" msgstr "" -#: ../libvips/colour/rad2float.c:188 -msgid "unpack Radiance coding to float RGB" +#: libvips/arithmetic/unary.c:81 +msgid "unary operations" msgstr "" -#: ../libvips/colour/XYZ2scRGB.c:105 -msgid "transform XYZ to scRGB" +#: libvips/arithmetic/unaryconst.c:138 +msgid "unary operations with a constant" msgstr "" -#: ../libvips/colour/Lab2LabS.c:80 -msgid "transform float Lab to signed short" +#: libvips/arithmetic/unaryconst.c:142 +msgid "c" msgstr "" -#: ../libvips/colour/LabS2LabQ.c:127 -msgid "transform short Lab to LabQ coding" +#: libvips/arithmetic/unaryconst.c:143 +msgid "Array of constants" msgstr "" -#: ../libvips/colour/float2rad.c:201 -msgid "transform float RGB to Radiance coding" +#: libvips/colour/CMYK2XYZ.c:114 libvips/colour/CMYK2XYZ.c:182 +msgid "transform CMYK to XYZ" msgstr "" -#: ../libvips/colour/scRGB2XYZ.c:90 -msgid "transform scRGB to XYZ" +#: libvips/colour/colour.c:288 +msgid "too many input images" msgstr "" -#: ../libvips/colour/LabQ2Lab.c:124 -msgid "unpack a LabQ image to float Lab" -msgstr "" - -#: ../libvips/colour/HSV2sRGB.c:113 -msgid "transform HSV to sRGB" -msgstr "" - -#: ../libvips/colour/XYZ2Lab.c:222 -msgid "transform XYZ to Lab" -msgstr "" - -#: ../libvips/colour/XYZ2Lab.c:228 ../libvips/colour/Lab2XYZ.c:175 -msgid "Temperature" -msgstr "" - -#: ../libvips/colour/XYZ2Lab.c:229 -msgid "Colour temperature" -msgstr "" - -#: ../libvips/colour/UCS2LCh.c:272 ../libvips/colour/LCh2UCS.c:206 -msgid "transform LCh to CMC" -msgstr "" - -#: ../libvips/colour/dE76.c:113 -msgid "calculate dE76" -msgstr "" - -#: ../libvips/colour/colour.c:421 +#: libvips/colour/colour.c:409 msgid "color operations" msgstr "colour operations" -#: ../libvips/colour/colour.c:489 +#: libvips/colour/colour.c:476 msgid "color space transformations" msgstr "colour space transformations" -#: ../libvips/colour/colour.c:583 +#: libvips/colour/colour.c:569 msgid "change color coding" msgstr "change colour coding" -#: ../libvips/colour/colour.c:695 +#: libvips/colour/colour.c:680 msgid "calculate color difference" msgstr "calculate colour difference" -#: ../libvips/colour/colour.c:700 +#: libvips/colour/colour.c:685 msgid "Left-hand input image" msgstr "" -#: ../libvips/colour/colour.c:706 +#: libvips/colour/colour.c:691 msgid "Right-hand input image" msgstr "" -#: ../libvips/colour/sRGB2HSV.c:134 -msgid "transform sRGB to HSV" +#: libvips/colour/colourspace.c:145 +msgid "too few bands for operation" msgstr "" -#: ../libvips/colour/Lab2LabQ.c:137 -msgid "transform float Lab to LabQ coding" +#: libvips/colour/colourspace.c:519 +#, c-format +msgid "no known route from '%s' to '%s'" msgstr "" -#: ../libvips/colour/sRGB2scRGB.c:237 -msgid "convert an sRGB image to scRGB" -msgstr "" +#: libvips/colour/colourspace.c:551 +msgid "convert to a new colorspace" +msgstr "convert to a new colourspace" -#: ../libvips/colour/dECMC.c:61 -msgid "calculate dECMC" +#: libvips/colour/colourspace.c:569 +msgid "Space" msgstr "" -#: ../libvips/colour/LCh2Lab.c:120 -msgid "transform LCh to Lab" -msgstr "" +#: libvips/colour/colourspace.c:570 +msgid "Destination color space" +msgstr "Destination colour space" -#: ../libvips/colour/Yxy2XYZ.c:93 -msgid "transform Yxy to XYZ" +#: libvips/colour/colourspace.c:576 +msgid "Source space" msgstr "" -#: ../libvips/colour/LabS2Lab.c:78 -msgid "transform signed short Lab to float" -msgstr "" +#: libvips/colour/colourspace.c:577 +msgid "Source color space" +msgstr "Source colour space" -#: ../libvips/colour/LabQ2sRGB.c:514 -msgid "convert a LabQ image to sRGB" +#: libvips/colour/dE00.c:236 +msgid "calculate dE00" msgstr "" -#: ../libvips/colour/scRGB2BW.c:190 ../libvips/colour/icc_transform.c:237 -#: ../libvips/colour/scRGB2sRGB.c:219 -msgid "depth must be 8 or 16" +#: libvips/colour/dE76.c:113 +msgid "calculate dE76" msgstr "" -#: ../libvips/colour/scRGB2BW.c:231 -msgid "convert scRGB to BW" +#: libvips/colour/dECMC.c:61 +msgid "calculate dECMC" msgstr "" -#: ../libvips/colour/scRGB2BW.c:249 ../libvips/colour/icc_transform.c:980 -#: ../libvips/colour/icc_transform.c:1121 ../libvips/colour/scRGB2sRGB.c:277 -#: ../libvips/foreign/dzsave.c:2163 -msgid "Depth" +#: libvips/colour/float2rad.c:206 +msgid "transform float RGB to Radiance coding" msgstr "" -#: ../libvips/colour/scRGB2BW.c:250 ../libvips/colour/icc_transform.c:981 -#: ../libvips/colour/icc_transform.c:1122 ../libvips/colour/scRGB2sRGB.c:278 -msgid "Output device space depth in bits" +#: libvips/colour/HSV2sRGB.c:112 +msgid "transform HSV to sRGB" msgstr "" -#: ../libvips/colour/Lab2LCh.c:149 -msgid "transform Lab to LCh" +#: libvips/colour/icc_transform.c:272 libvips/colour/scRGB2BW.c:190 +#: libvips/colour/scRGB2sRGB.c:224 +msgid "depth must be 8 or 16" msgstr "" -#: ../libvips/colour/icc_transform.c:292 +#: libvips/colour/icc_transform.c:284 #, c-format msgid "unimplemented input color space 0x%x" msgstr "unimplemented input colour space 0x%x" -#: ../libvips/colour/icc_transform.c:357 +#: libvips/colour/icc_transform.c:360 #, c-format msgid "unimplemented output color space 0x%x" msgstr "unimplemented output colour space 0x%x" -#: ../libvips/colour/icc_transform.c:369 +#: libvips/colour/icc_transform.c:437 msgid "no device profile" msgstr "" -#: ../libvips/colour/icc_transform.c:400 -msgid "transform using ICC profiles" -msgstr "" - -#: ../libvips/colour/icc_transform.c:404 -msgid "Intent" +#: libvips/colour/icc_transform.c:612 libvips/colour/icc_transform.c:635 +#: libvips/colour/icc_transform.c:658 libvips/iofuncs/operation.c:442 +msgid "input" msgstr "" -#: ../libvips/colour/icc_transform.c:405 -msgid "Rendering intent" +#: libvips/colour/icc_transform.c:612 libvips/colour/icc_transform.c:635 +#: libvips/colour/icc_transform.c:658 libvips/iofuncs/operation.c:443 +msgid "output" msgstr "" -#: ../libvips/colour/icc_transform.c:411 -msgid "PCS" +#: libvips/colour/icc_transform.c:631 +#, c-format +msgid "" +"fallback to suggested %s intent, as profile does not support %s %s intent" msgstr "" -#: ../libvips/colour/icc_transform.c:412 -msgid "Set Profile Connection Space" +#: libvips/colour/icc_transform.c:656 +#, c-format +msgid "profile does not support %s %s intent" msgstr "" -#: ../libvips/colour/icc_transform.c:455 -#, c-format -msgid "" -"%s: intent %d (%s) not supported by %s profile; falling back to default " -"intent" +#: libvips/colour/icc_transform.c:757 +msgid "unable to load or find any compatible input profile" msgstr "" -#: ../libvips/colour/icc_transform.c:460 ../libvips/iofuncs/operation.c:377 -msgid "input" +#: libvips/colour/icc_transform.c:775 +msgid "transform using ICC profiles" msgstr "" -#: ../libvips/colour/icc_transform.c:460 ../libvips/iofuncs/operation.c:377 -msgid "output" +#: libvips/colour/icc_transform.c:779 libvips/resample/thumbnail.c:1030 +msgid "Intent" msgstr "" -#: ../libvips/colour/icc_transform.c:557 -msgid "corrupt embedded profile" +#: libvips/colour/icc_transform.c:780 libvips/resample/thumbnail.c:1031 +msgid "Rendering intent" msgstr "" -#: ../libvips/colour/icc_transform.c:565 -msgid "embedded profile incompatible with image" +#: libvips/colour/icc_transform.c:786 +msgid "PCS" msgstr "" -#: ../libvips/colour/icc_transform.c:580 ../libvips/colour/icc_transform.c:822 -#: ../libvips/colour/icc_transform.c:1045 -#, c-format -msgid "unable to open profile \"%s\"" +#: libvips/colour/icc_transform.c:787 +msgid "Set Profile Connection Space" msgstr "" -#: ../libvips/colour/icc_transform.c:587 -#, c-format -msgid "profile \"%s\" incompatible with image" +#: libvips/colour/icc_transform.c:793 +msgid "Black point compensation" msgstr "" -#: ../libvips/colour/icc_transform.c:626 ../libvips/colour/icc_transform.c:1037 -msgid "no input profile" +#: libvips/colour/icc_transform.c:794 +msgid "Enable black point compensation" msgstr "" -#: ../libvips/colour/icc_transform.c:736 +#: libvips/colour/icc_transform.c:969 msgid "import from device with ICC profile" msgstr "" -#: ../libvips/colour/icc_transform.c:742 ../libvips/colour/icc_transform.c:1107 +#: libvips/colour/icc_transform.c:975 libvips/colour/icc_transform.c:1258 msgid "Embedded" msgstr "" -#: ../libvips/colour/icc_transform.c:743 ../libvips/colour/icc_transform.c:1108 +#: libvips/colour/icc_transform.c:976 libvips/colour/icc_transform.c:1259 msgid "Use embedded input profile, if available" msgstr "" -#: ../libvips/colour/icc_transform.c:749 ../libvips/colour/icc_transform.c:1114 +#: libvips/colour/icc_transform.c:982 libvips/colour/icc_transform.c:1265 msgid "Input profile" msgstr "" -#: ../libvips/colour/icc_transform.c:750 ../libvips/colour/icc_transform.c:1115 +#: libvips/colour/icc_transform.c:983 libvips/colour/icc_transform.c:1266 msgid "Filename to load input profile from" msgstr "" -#: ../libvips/colour/icc_transform.c:814 -msgid "unable to load embedded profile" -msgstr "" - -#: ../libvips/colour/icc_transform.c:830 +#: libvips/colour/icc_transform.c:1046 libvips/colour/icc_transform.c:1212 msgid "no output profile" msgstr "" -#: ../libvips/colour/icc_transform.c:967 +#: libvips/colour/icc_transform.c:1141 msgid "output to device with ICC profile" msgstr "" -#: ../libvips/colour/icc_transform.c:973 ../libvips/colour/icc_transform.c:1100 +#: libvips/colour/icc_transform.c:1147 libvips/colour/icc_transform.c:1251 msgid "Output profile" msgstr "" -#: ../libvips/colour/icc_transform.c:974 ../libvips/colour/icc_transform.c:1101 +#: libvips/colour/icc_transform.c:1148 libvips/colour/icc_transform.c:1252 msgid "Filename to load output profile from" msgstr "" -#: ../libvips/colour/icc_transform.c:1094 -msgid "transform between devices with ICC profiles" +#: libvips/colour/icc_transform.c:1154 libvips/colour/icc_transform.c:1272 +#: libvips/colour/scRGB2BW.c:249 libvips/colour/scRGB2sRGB.c:282 +#: libvips/foreign/dzsave.c:2364 libvips/foreign/tiffsave.c:378 +msgid "Depth" msgstr "" -#: ../libvips/colour/icc_transform.c:1166 -#: ../libvips/colour/icc_transform.c:1180 -msgid "unable to get media white point" +#: libvips/colour/icc_transform.c:1155 libvips/colour/icc_transform.c:1273 +#: libvips/colour/scRGB2BW.c:250 libvips/colour/scRGB2sRGB.c:283 +msgid "Output device space depth in bits" msgstr "" -#: ../libvips/colour/icc_transform.c:1240 -msgid "libvips configured without lcms support" +#: libvips/colour/icc_transform.c:1245 +msgid "transform between devices with ICC profiles" msgstr "" -#: ../libvips/colour/scRGB2sRGB.c:259 -msgid "convert an scRGB image to sRGB" +#: libvips/colour/icc_transform.c:1321 +msgid "unable to get media white point" msgstr "" -#: ../libvips/colour/dE00.c:235 -msgid "calculate dE00" +#: libvips/colour/icc_transform.c:1416 +msgid "libvips configured without lcms support" msgstr "" -#: ../libvips/colour/Lab2XYZ.c:169 -msgid "transform CIELAB to XYZ" +#: libvips/colour/Lab2LabQ.c:137 +msgid "transform float Lab to LabQ coding" msgstr "" -#: ../libvips/colour/Lab2XYZ.c:176 -msgid "Color temperature" +#: libvips/colour/Lab2LabS.c:82 +msgid "transform float Lab to signed short" msgstr "" -#: ../libvips/colour/XYZ2Yxy.c:92 -msgid "transform XYZ to Yxy" +#: libvips/colour/Lab2LCh.c:132 +msgid "transform Lab to LCh" msgstr "" -#: ../libvips/colour/colourspace.c:145 -msgid "too few bands for operation" +#: libvips/colour/Lab2XYZ.c:177 +msgid "transform CIELAB to XYZ" msgstr "" -#: ../libvips/colour/colourspace.c:548 -#, c-format -msgid "no known route from '%s' to '%s'" +#: libvips/colour/Lab2XYZ.c:183 libvips/colour/XYZ2Lab.c:236 +msgid "Temperature" msgstr "" -#: ../libvips/colour/colourspace.c:580 -msgid "convert to a new colorspace" -msgstr "convert to a new colourspace" - -#: ../libvips/colour/colourspace.c:598 -msgid "Space" +#: libvips/colour/Lab2XYZ.c:184 +msgid "Color temperature" msgstr "" -#: ../libvips/colour/colourspace.c:599 -msgid "Destination color space" -msgstr "Destination colour space" - -#: ../libvips/colour/colourspace.c:605 -msgid "Source space" +#: libvips/colour/LabQ2Lab.c:125 +msgid "unpack a LabQ image to float Lab" msgstr "" -#: ../libvips/colour/colourspace.c:606 -msgid "Source color space" -msgstr "Source colour space" - -#: ../libvips/conversion/conversion.c:196 -msgid "conversion operations" +#: libvips/colour/LabQ2LabS.c:104 +msgid "unpack a LabQ image to short Lab" msgstr "" -#: ../libvips/conversion/embed.c:474 ../libvips/iofuncs/image.c:2818 -msgid "bad dimensions" +#: libvips/colour/LabQ2sRGB.c:549 +msgid "convert a LabQ image to sRGB" msgstr "" -#: ../libvips/conversion/embed.c:557 -msgid "embed an image in a larger image" +#: libvips/colour/LabS2Lab.c:78 +msgid "transform signed short Lab to float" msgstr "" -#: ../libvips/conversion/embed.c:570 ../libvips/conversion/wrap.c:126 -msgid "Left edge of input in output" +#: libvips/colour/LabS2LabQ.c:127 +msgid "transform short Lab to LabQ coding" msgstr "" -#: ../libvips/conversion/embed.c:577 ../libvips/conversion/wrap.c:133 -msgid "Top edge of input in output" +#: libvips/colour/LCh2Lab.c:111 +msgid "transform LCh to Lab" msgstr "" -#: ../libvips/conversion/embed.c:584 ../libvips/conversion/copy.c:285 -#: ../libvips/create/xyz.c:194 ../libvips/create/worley.c:311 -#: ../libvips/create/gaussnoise.c:173 ../libvips/create/perlin.c:298 -#: ../libvips/create/point.c:144 ../libvips/create/fractsurf.c:103 -#: ../libvips/create/black.c:130 ../libvips/foreign/rawload.c:124 -#: ../libvips/iofuncs/image.c:1131 -msgid "Image width in pixels" +#: libvips/colour/LCh2UCS.c:206 libvips/colour/UCS2LCh.c:273 +msgid "transform LCh to CMC" msgstr "" -#: ../libvips/conversion/embed.c:591 ../libvips/conversion/copy.c:292 -#: ../libvips/create/xyz.c:201 ../libvips/create/worley.c:318 -#: ../libvips/create/gaussnoise.c:180 ../libvips/create/perlin.c:305 -#: ../libvips/create/point.c:151 ../libvips/create/fractsurf.c:110 -#: ../libvips/create/black.c:137 ../libvips/foreign/rawload.c:131 -#: ../libvips/iofuncs/image.c:1138 -msgid "Image height in pixels" +#: libvips/colour/profile_load.c:123 +#, c-format +msgid "unable to load profile \"%s\"" msgstr "" -#: ../libvips/conversion/embed.c:597 -msgid "Extend" +#: libvips/colour/profile_load.c:147 +msgid "load named ICC profile" msgstr "" -#: ../libvips/conversion/embed.c:598 -msgid "How to generate the extra pixels" +#: libvips/colour/profile_load.c:151 +msgid "Name" msgstr "" -#: ../libvips/conversion/embed.c:604 ../libvips/conversion/arrayjoin.c:325 -#: ../libvips/conversion/flatten.c:392 ../libvips/conversion/join.c:265 -#: ../libvips/conversion/insert.c:550 ../libvips/foreign/foreign.c:1535 -msgid "Background" +#: libvips/colour/profile_load.c:152 +msgid "Profile name" msgstr "" -#: ../libvips/conversion/embed.c:605 -msgid "Color for background pixels" +#: libvips/colour/profile_load.c:158 libvips/foreign/foreign.c:1922 +msgid "Profile" msgstr "" -#: ../libvips/conversion/zoom.c:333 -msgid "zoom factors too large" +#: libvips/colour/profile_load.c:159 +msgid "Loaded profile" msgstr "" -#: ../libvips/conversion/zoom.c:377 -msgid "zoom an image" +#: libvips/colour/rad2float.c:184 +msgid "unpack Radiance coding to float RGB" msgstr "" -#: ../libvips/conversion/zoom.c:389 ../libvips/conversion/subsample.c:280 -msgid "Xfac" +#: libvips/colour/scRGB2BW.c:231 +msgid "convert scRGB to BW" msgstr "" -#: ../libvips/conversion/zoom.c:390 -msgid "Horizontal zoom factor" +#: libvips/colour/scRGB2sRGB.c:264 +msgid "convert an scRGB image to sRGB" msgstr "" -#: ../libvips/conversion/zoom.c:396 ../libvips/conversion/subsample.c:287 -msgid "Yfac" +#: libvips/colour/scRGB2XYZ.c:185 +msgid "transform scRGB to XYZ" msgstr "" -#: ../libvips/conversion/zoom.c:397 -msgid "Vertical zoom factor" +#: libvips/colour/sRGB2HSV.c:133 +msgid "transform sRGB to HSV" msgstr "" -#: ../libvips/conversion/replicate.c:192 -msgid "replicate an image" +#: libvips/colour/sRGB2scRGB.c:282 +msgid "convert an sRGB image to scRGB" msgstr "" -#: ../libvips/conversion/replicate.c:203 -msgid "Repeat this many times horizontally" +#: libvips/colour/XYZ2CMYK.c:113 libvips/colour/XYZ2CMYK.c:193 +msgid "transform XYZ to CMYK" msgstr "" -#: ../libvips/conversion/replicate.c:210 -msgid "Repeat this many times vertically" +#: libvips/colour/XYZ2Lab.c:230 +msgid "transform XYZ to Lab" msgstr "" -#: ../libvips/conversion/bandfold.c:122 -msgid "@factor must be a factor of image width" +#: libvips/colour/XYZ2Lab.c:237 +msgid "Colour temperature" msgstr "" -#: ../libvips/conversion/bandfold.c:154 -msgid "fold up x axis into bands" +#: libvips/colour/XYZ2scRGB.c:194 +msgid "transform XYZ to scRGB" msgstr "" -#: ../libvips/conversion/bandfold.c:166 ../libvips/conversion/bandunfold.c:169 -#: ../libvips/create/eye.c:103 -msgid "Factor" +#: libvips/colour/XYZ2Yxy.c:98 +msgid "transform XYZ to Yxy" msgstr "" -#: ../libvips/conversion/bandfold.c:167 -msgid "Fold by this factor" +#: libvips/colour/Yxy2XYZ.c:103 +msgid "transform Yxy to XYZ" msgstr "" -#: ../libvips/conversion/wrap.c:115 -msgid "wrap image origin" +#: libvips/conversion/addalpha.c:84 +msgid "append an alpha channel" msgstr "" -#: ../libvips/conversion/arrayjoin.c:298 +#: libvips/conversion/arrayjoin.c:388 msgid "join an array of images" msgstr "" -#: ../libvips/conversion/arrayjoin.c:312 +#: libvips/conversion/arrayjoin.c:402 msgid "Number of images across grid" msgstr "" -#: ../libvips/conversion/arrayjoin.c:318 ../libvips/conversion/join.c:258 +#: libvips/conversion/arrayjoin.c:408 libvips/conversion/join.c:263 msgid "Shim" msgstr "" -#: ../libvips/conversion/arrayjoin.c:319 ../libvips/conversion/join.c:259 +#: libvips/conversion/arrayjoin.c:409 libvips/conversion/join.c:264 msgid "Pixels between images" msgstr "" -#: ../libvips/conversion/arrayjoin.c:326 ../libvips/conversion/join.c:266 +#: libvips/conversion/arrayjoin.c:416 libvips/conversion/join.c:271 msgid "Colour for new pixels" msgstr "" -#: ../libvips/conversion/arrayjoin.c:332 +#: libvips/conversion/arrayjoin.c:422 msgid "Horizontal align" msgstr "" -#: ../libvips/conversion/arrayjoin.c:333 +#: libvips/conversion/arrayjoin.c:423 msgid "Align on the left, centre or right" msgstr "" -#: ../libvips/conversion/arrayjoin.c:339 +#: libvips/conversion/arrayjoin.c:429 msgid "Vertical align" msgstr "" -#: ../libvips/conversion/arrayjoin.c:340 +#: libvips/conversion/arrayjoin.c:430 msgid "Align on the top, centre or bottom" msgstr "" -#: ../libvips/conversion/arrayjoin.c:346 +#: libvips/conversion/arrayjoin.c:436 msgid "Horizontal spacing" msgstr "" -#: ../libvips/conversion/arrayjoin.c:347 +#: libvips/conversion/arrayjoin.c:437 msgid "Horizontal spacing between images" msgstr "" -#: ../libvips/conversion/arrayjoin.c:353 +#: libvips/conversion/arrayjoin.c:443 msgid "Vertical spacing" msgstr "" -#: ../libvips/conversion/arrayjoin.c:354 +#: libvips/conversion/arrayjoin.c:444 msgid "Vertical spacing between images" msgstr "" -#: ../libvips/conversion/unpremultiply.c:262 -msgid "unpremultiply image alpha" +#: libvips/conversion/autorot.c:203 +msgid "autorotate image by exif tag" msgstr "" -#: ../libvips/conversion/unpremultiply.c:274 -#: ../libvips/conversion/flatten.c:399 ../libvips/conversion/premultiply.c:265 -msgid "Maximum alpha" +#: libvips/conversion/autorot.c:213 libvips/conversion/rot45.c:274 +#: libvips/conversion/rot.c:371 libvips/convolution/compass.c:170 +#: libvips/foreign/dzsave.c:2378 libvips/mosaicing/mosaic.c:281 +#: libvips/resample/similarity.c:207 libvips/resample/similarity.c:276 +msgid "Angle" msgstr "" -#: ../libvips/conversion/unpremultiply.c:275 -#: ../libvips/conversion/flatten.c:400 ../libvips/conversion/premultiply.c:266 -msgid "Maximum value of alpha channel" +#: libvips/conversion/autorot.c:214 +msgid "Angle image was rotated by" msgstr "" -#: ../libvips/conversion/flip.c:236 -msgid "flip an image" +#: libvips/conversion/autorot.c:220 +msgid "Flip" msgstr "" -#: ../libvips/conversion/flip.c:246 ../libvips/mosaicing/merge.c:127 -#: ../libvips/mosaicing/mosaic.c:198 ../libvips/mosaicing/mosaic1.c:507 -msgid "Direction" +#: libvips/conversion/autorot.c:221 +msgid "Whether the image was flipped or not" msgstr "" -#: ../libvips/conversion/flip.c:247 -msgid "Direction to flip image" +#: libvips/conversion/bandary.c:211 libvips/conversion/bandary.c:280 +#: libvips/conversion/composite.cpp:1299 +msgid "no input images" msgstr "" -#: ../libvips/conversion/flatten.c:380 -msgid "flatten alpha out of an image" +#: libvips/conversion/bandary.c:257 +msgid "operations on image bands" msgstr "" -#: ../libvips/conversion/flatten.c:393 ../libvips/foreign/foreign.c:1536 -msgid "Background value" +#: libvips/conversion/bandbool.c:75 +#, c-format +msgid "operator %s not supported across image bands" msgstr "" -#: ../libvips/conversion/copy.c:181 -msgid "copy swap is deprecated, use byteswap instead" +#: libvips/conversion/bandbool.c:225 +msgid "boolean operation across image bands" msgstr "" -#: ../libvips/conversion/copy.c:235 -msgid "must not change pel size" +#: libvips/conversion/bandbool.c:233 libvips/conversion/bandmean.c:213 +#: libvips/conversion/recomb.c:225 libvips/convolution/convolution.c:129 +#: libvips/convolution/correlation.c:151 libvips/morphology/morphology.c:122 +#: libvips/resample/resample.c:141 libvips/resample/thumbnail.c:1783 +msgid "Input image argument" msgstr "" -#: ../libvips/conversion/copy.c:260 -msgid "copy an image" +#: libvips/conversion/bandfold.c:123 +msgid "@factor must be a factor of image width" msgstr "" -#: ../libvips/conversion/copy.c:277 -msgid "Swap" +#: libvips/conversion/bandfold.c:155 +msgid "fold up x axis into bands" msgstr "" -#: ../libvips/conversion/copy.c:278 -msgid "Swap bytes in image between little and big-endian" +#: libvips/conversion/bandfold.c:167 libvips/conversion/bandunfold.c:170 +#: libvips/create/eye.c:108 +msgid "Factor" msgstr "" -#: ../libvips/conversion/copy.c:298 ../libvips/create/identity.c:144 -#: ../libvips/create/black.c:143 ../libvips/foreign/rawload.c:137 -#: ../libvips/iofuncs/image.c:1144 -msgid "Bands" +#: libvips/conversion/bandfold.c:168 +msgid "Fold by this factor" msgstr "" -#: ../libvips/conversion/copy.c:299 ../libvips/create/black.c:144 -#: ../libvips/foreign/rawload.c:138 ../libvips/iofuncs/image.c:1145 -msgid "Number of bands in image" +#: libvips/conversion/bandjoin.c:195 +msgid "bandwise join a set of images" msgstr "" -#: ../libvips/conversion/copy.c:305 ../libvips/conversion/cast.c:554 -#: ../libvips/iofuncs/image.c:1151 -msgid "Format" +#: libvips/conversion/bandjoin.c:430 +msgid "append a constant band to an image" msgstr "" -#: ../libvips/conversion/copy.c:306 ../libvips/iofuncs/image.c:1152 -msgid "Pixel format in image" +#: libvips/conversion/bandjoin.c:442 +msgid "Constants" msgstr "" -#: ../libvips/conversion/copy.c:312 ../libvips/iofuncs/image.c:1158 -msgid "Coding" +#: libvips/conversion/bandjoin.c:443 +msgid "Array of constants to add" msgstr "" -#: ../libvips/conversion/copy.c:313 ../libvips/iofuncs/image.c:1159 -msgid "Pixel coding" +#: libvips/conversion/bandmean.c:206 +msgid "band-wise average" msgstr "" -#: ../libvips/conversion/copy.c:319 ../libvips/iofuncs/image.c:1165 -msgid "Interpretation" +#: libvips/conversion/bandrank.c:248 +msgid "band-wise rank of a set of images" msgstr "" -#: ../libvips/conversion/copy.c:320 ../libvips/iofuncs/image.c:1166 -msgid "Pixel interpretation" +#: libvips/conversion/bandrank.c:262 +msgid "Select this band element from sorted list" msgstr "" -#: ../libvips/conversion/copy.c:326 ../libvips/foreign/tiffsave.c:260 -#: ../libvips/iofuncs/image.c:1172 -msgid "Xres" +#: libvips/conversion/bandunfold.c:126 +msgid "@factor must be a factor of image bands" msgstr "" -#: ../libvips/conversion/copy.c:327 ../libvips/foreign/tiffsave.c:261 -#: ../libvips/iofuncs/image.c:1173 -msgid "Horizontal resolution in pixels/mm" +#: libvips/conversion/bandunfold.c:158 +msgid "unfold image bands into x axis" msgstr "" -#: ../libvips/conversion/copy.c:333 ../libvips/foreign/tiffsave.c:267 -#: ../libvips/iofuncs/image.c:1179 -msgid "Yres" +#: libvips/conversion/bandunfold.c:171 +msgid "Unfold by this factor" msgstr "" -#: ../libvips/conversion/copy.c:334 ../libvips/foreign/tiffsave.c:268 -#: ../libvips/iofuncs/image.c:1180 -msgid "Vertical resolution in pixels/mm" +#: libvips/conversion/byteswap.c:232 +msgid "byteswap an image" msgstr "" -#: ../libvips/conversion/copy.c:340 ../libvips/iofuncs/image.c:1186 -msgid "Xoffset" +#: libvips/conversion/cache.c:98 libvips/conversion/tilecache.c:392 +msgid "cache an image" msgstr "" -#: ../libvips/conversion/copy.c:341 ../libvips/iofuncs/image.c:1187 -msgid "Horizontal offset of origin" +#: libvips/conversion/cache.c:114 libvips/conversion/tilecache.c:800 +#: libvips/foreign/dzsave.c:2451 libvips/foreign/jp2ksave.c:971 +#: libvips/foreign/tiffsave.c:287 +msgid "Tile width" msgstr "" -#: ../libvips/conversion/copy.c:347 ../libvips/iofuncs/image.c:1193 -msgid "Yoffset" +#: libvips/conversion/cache.c:115 libvips/conversion/tilecache.c:801 +#: libvips/foreign/dzsave.c:2452 libvips/foreign/jp2ksave.c:972 +#: libvips/foreign/tiffsave.c:288 +msgid "Tile width in pixels" msgstr "" -#: ../libvips/conversion/copy.c:348 ../libvips/iofuncs/image.c:1194 -msgid "Vertical offset of origin" +#: libvips/conversion/cache.c:121 libvips/conversion/grid.c:205 +#: libvips/conversion/sequential.c:249 libvips/conversion/tilecache.c:404 +#: libvips/foreign/dzsave.c:2458 libvips/foreign/jp2ksave.c:978 +#: libvips/foreign/tiffsave.c:294 +msgid "Tile height" msgstr "" -#: ../libvips/conversion/bandjoin.c:170 -msgid "bandwise join a set of images" +#: libvips/conversion/cache.c:122 libvips/conversion/sequential.c:250 +#: libvips/conversion/tilecache.c:405 libvips/foreign/dzsave.c:2459 +#: libvips/foreign/jp2ksave.c:979 libvips/foreign/tiffsave.c:295 +msgid "Tile height in pixels" msgstr "" -#: ../libvips/conversion/bandjoin.c:389 -msgid "append a constant band to an image" +#: libvips/conversion/cache.c:128 libvips/conversion/tilecache.c:807 +msgid "Max tiles" +msgstr "" + +#: libvips/conversion/cache.c:129 libvips/conversion/tilecache.c:808 +msgid "Maximum number of tiles to cache" +msgstr "" + +#: libvips/conversion/cast.c:524 +msgid "cast an image" +msgstr "" + +#: libvips/conversion/cast.c:536 libvips/conversion/copy.c:305 +#: libvips/foreign/ppmsave.c:506 libvips/foreign/rawload.c:174 +#: libvips/foreign/vips2magick.c:482 libvips/iofuncs/image.c:1123 +msgid "Format" +msgstr "" + +#: libvips/conversion/cast.c:537 +msgid "Format to cast to" +msgstr "" + +#: libvips/conversion/cast.c:543 +msgid "Shift" +msgstr "" + +#: libvips/conversion/cast.c:544 +msgid "Shift integer values up and down" +msgstr "" + +#: libvips/conversion/composite.cpp:1304 +#, c-format +msgid "must be 1 or %d blend modes" +msgstr "" + +#: libvips/conversion/composite.cpp:1314 +#, c-format +msgid "blend mode index %d (%d) invalid" +msgstr "" + +#: libvips/conversion/composite.cpp:1413 +msgid "images do not have same numbers of bands" +msgstr "" + +#: libvips/conversion/composite.cpp:1420 +msgid "too many input bands" +msgstr "" + +#: libvips/conversion/composite.cpp:1430 +#, fuzzy +msgid "unsupported compositing space" +msgstr "unsupported colourspace %d" + +#: libvips/conversion/composite.cpp:1478 +msgid "blend images together" +msgstr "" + +#: libvips/conversion/composite.cpp:1484 +msgid "Compositing space" +msgstr "" + +#: libvips/conversion/composite.cpp:1485 +#, fuzzy +msgid "Composite images in this colour space" +msgstr "Destination colour space" + +#: libvips/conversion/composite.cpp:1491 libvips/conversion/smartcrop.c:474 +#: libvips/resample/affine.c:706 libvips/resample/mapim.c:581 +msgid "Premultiplied" +msgstr "" + +#: libvips/conversion/composite.cpp:1492 libvips/resample/affine.c:707 +#: libvips/resample/mapim.c:582 +msgid "Images have premultiplied alpha" +msgstr "" + +#: libvips/conversion/composite.cpp:1540 +#, c-format +msgid "must be %d x coordinates" +msgstr "" + +#: libvips/conversion/composite.cpp:1548 +#, c-format +msgid "must be %d y coordinates" +msgstr "" + +#: libvips/conversion/composite.cpp:1574 +msgid "blend an array of images with an array of blend modes" +msgstr "" + +#: libvips/conversion/composite.cpp:1580 +msgid "Inputs" +msgstr "" + +#: libvips/conversion/composite.cpp:1587 +msgid "Blend modes" +msgstr "" + +#: libvips/conversion/composite.cpp:1588 +msgid "Array of VipsBlendMode to join with" +msgstr "" + +#: libvips/conversion/composite.cpp:1594 +msgid "x coordinates" +msgstr "" + +#: libvips/conversion/composite.cpp:1595 +msgid "Array of x coordinates to join at" +msgstr "" + +#: libvips/conversion/composite.cpp:1601 +msgid "y coordinates" +msgstr "" + +#: libvips/conversion/composite.cpp:1602 +msgid "Array of y coordinates to join at" +msgstr "" + +#: libvips/conversion/composite.cpp:1708 +msgid "blend a pair of images with a blend mode" +msgstr "" + +#: libvips/conversion/composite.cpp:1714 +msgid "Base" +msgstr "" + +#: libvips/conversion/composite.cpp:1715 +#, fuzzy +msgid "Base image" +msgstr "false-colour an image" + +#: libvips/conversion/composite.cpp:1720 +msgid "Overlay" +msgstr "" + +#: libvips/conversion/composite.cpp:1721 +msgid "Overlay image" +msgstr "" + +#: libvips/conversion/composite.cpp:1726 +msgid "Blend mode" +msgstr "" + +#: libvips/conversion/composite.cpp:1727 +msgid "VipsBlendMode to join with" +msgstr "" + +#: libvips/conversion/composite.cpp:1734 +msgid "x position of overlay" +msgstr "" + +#: libvips/conversion/composite.cpp:1741 +msgid "y position of overlay" +msgstr "" + +#: libvips/conversion/conversion.c:342 +msgid "conversion operations" +msgstr "" + +#: libvips/conversion/copy.c:235 +msgid "must not change pel size" +msgstr "" + +#: libvips/conversion/copy.c:260 +msgid "copy an image" +msgstr "" + +#: libvips/conversion/copy.c:277 +msgid "Swap" +msgstr "" + +#: libvips/conversion/copy.c:278 +msgid "Swap bytes in image between little and big-endian" +msgstr "" + +#: libvips/conversion/copy.c:285 libvips/conversion/embed.c:575 +#: libvips/create/black.c:141 libvips/create/fractsurf.c:105 +#: libvips/create/gaussnoise.c:168 libvips/create/perlin.c:295 +#: libvips/create/point.c:142 libvips/create/sdf.c:305 +#: libvips/create/worley.c:308 libvips/create/xyz.c:192 +#: libvips/foreign/rawload.c:147 libvips/iofuncs/image.c:1103 +msgid "Image width in pixels" +msgstr "" + +#: libvips/conversion/copy.c:292 libvips/conversion/embed.c:582 +#: libvips/create/black.c:148 libvips/create/fractsurf.c:112 +#: libvips/create/gaussnoise.c:175 libvips/create/perlin.c:302 +#: libvips/create/point.c:149 libvips/create/sdf.c:312 +#: libvips/create/worley.c:315 libvips/create/xyz.c:199 +#: libvips/foreign/rawload.c:154 libvips/iofuncs/image.c:1110 +msgid "Image height in pixels" +msgstr "" + +#: libvips/conversion/copy.c:298 libvips/create/black.c:154 +#: libvips/create/identity.c:143 libvips/foreign/rawload.c:160 +#: libvips/iofuncs/image.c:1116 +msgid "Bands" +msgstr "" + +#: libvips/conversion/copy.c:299 libvips/create/black.c:155 +#: libvips/foreign/rawload.c:161 libvips/iofuncs/image.c:1117 +msgid "Number of bands in image" +msgstr "" + +#: libvips/conversion/copy.c:306 libvips/foreign/rawload.c:175 +#: libvips/iofuncs/image.c:1124 +msgid "Pixel format in image" +msgstr "" + +#: libvips/conversion/copy.c:312 libvips/iofuncs/image.c:1130 +msgid "Coding" +msgstr "" + +#: libvips/conversion/copy.c:313 libvips/iofuncs/image.c:1131 +msgid "Pixel coding" +msgstr "" + +#: libvips/conversion/copy.c:319 libvips/foreign/rawload.c:181 +#: libvips/iofuncs/image.c:1137 +msgid "Interpretation" +msgstr "" + +#: libvips/conversion/copy.c:320 libvips/foreign/rawload.c:182 +#: libvips/iofuncs/image.c:1138 +msgid "Pixel interpretation" +msgstr "" + +#: libvips/conversion/copy.c:326 libvips/foreign/tiffsave.c:329 +#: libvips/iofuncs/image.c:1144 +msgid "Xres" +msgstr "" + +#: libvips/conversion/copy.c:327 libvips/foreign/tiffsave.c:330 +#: libvips/iofuncs/image.c:1145 +msgid "Horizontal resolution in pixels/mm" +msgstr "" + +#: libvips/conversion/copy.c:333 libvips/foreign/tiffsave.c:336 +#: libvips/iofuncs/image.c:1151 +msgid "Yres" +msgstr "" + +#: libvips/conversion/copy.c:334 libvips/foreign/tiffsave.c:337 +#: libvips/iofuncs/image.c:1152 +msgid "Vertical resolution in pixels/mm" +msgstr "" + +#: libvips/conversion/copy.c:340 libvips/iofuncs/image.c:1158 +msgid "Xoffset" +msgstr "" + +#: libvips/conversion/copy.c:341 libvips/iofuncs/image.c:1159 +msgid "Horizontal offset of origin" +msgstr "" + +#: libvips/conversion/copy.c:347 libvips/iofuncs/image.c:1165 +msgid "Yoffset" +msgstr "" + +#: libvips/conversion/copy.c:348 libvips/iofuncs/image.c:1166 +msgid "Vertical offset of origin" +msgstr "" + +#: libvips/conversion/embed.c:479 libvips/foreign/heifload.c:571 +#: libvips/foreign/svgload.c:502 libvips/iofuncs/image.c:3143 +msgid "bad dimensions" +msgstr "" + +#: libvips/conversion/embed.c:561 libvips/conversion/embed.c:652 +msgid "embed an image in a larger image" +msgstr "" + +#: libvips/conversion/embed.c:588 libvips/resample/affine.c:692 +#: libvips/resample/mapim.c:567 +msgid "Extend" +msgstr "" + +#: libvips/conversion/embed.c:589 libvips/resample/affine.c:693 +#: libvips/resample/mapim.c:568 +msgid "How to generate the extra pixels" +msgstr "" + +#: libvips/conversion/embed.c:657 libvips/conversion/wrap.c:126 +msgid "Left edge of input in output" +msgstr "" + +#: libvips/conversion/embed.c:664 libvips/conversion/wrap.c:133 +msgid "Top edge of input in output" +msgstr "" + +#: libvips/conversion/embed.c:806 +msgid "place an image within a larger image with a certain gravity" +msgstr "" + +#: libvips/conversion/embed.c:811 libvips/conversion/flip.c:246 +#: libvips/conversion/join.c:249 libvips/morphology/countlines.c:146 +#: libvips/mosaicing/merge.c:140 libvips/mosaicing/mosaic1.c:516 +#: libvips/mosaicing/mosaic.c:197 +msgid "Direction" +msgstr "" + +#: libvips/conversion/embed.c:812 +msgid "Direction to place image within width/height" +msgstr "" + +#: libvips/conversion/extract.c:150 libvips/conversion/smartcrop.c:341 +msgid "bad extract area" +msgstr "" + +#: libvips/conversion/extract.c:188 libvips/conversion/smartcrop.c:429 +msgid "extract an area from an image" +msgstr "" + +#: libvips/conversion/extract.c:398 +msgid "bad extract band" +msgstr "" + +#: libvips/conversion/extract.c:426 +msgid "extract band from an image" +msgstr "" + +#: libvips/conversion/extract.c:439 +msgid "Band to extract" +msgstr "" + +#: libvips/conversion/extract.c:445 libvips/foreign/heifload.c:1090 +#: libvips/foreign/jxlload.c:1139 libvips/foreign/magick6load.c:148 +#: libvips/foreign/magick7load.c:389 libvips/foreign/nsgifload.c:627 +#: libvips/foreign/pdfiumload.c:702 libvips/foreign/popplerload.c:552 +#: libvips/foreign/tiffload.c:203 libvips/foreign/webpload.c:185 +msgid "n" +msgstr "" + +#: libvips/conversion/extract.c:446 +msgid "Number of bands to extract" +msgstr "" + +#: libvips/conversion/falsecolour.c:374 +msgid "false-color an image" +msgstr "false-colour an image" + +#: libvips/conversion/flatten.c:413 +msgid "flatten alpha out of an image" +msgstr "" + +#: libvips/conversion/flatten.c:426 libvips/foreign/foreign.c:1909 +#: libvips/resample/affine.c:700 libvips/resample/mapim.c:575 +#: libvips/resample/similarity.c:134 +msgid "Background value" +msgstr "" + +#: libvips/conversion/flatten.c:432 libvips/conversion/premultiply.c:267 +#: libvips/conversion/unpremultiply.c:329 +msgid "Maximum alpha" +msgstr "" + +#: libvips/conversion/flatten.c:433 libvips/conversion/premultiply.c:268 +#: libvips/conversion/unpremultiply.c:330 +msgid "Maximum value of alpha channel" +msgstr "" + +#: libvips/conversion/flip.c:236 +msgid "flip an image" +msgstr "" + +#: libvips/conversion/flip.c:247 +msgid "Direction to flip image" +msgstr "" + +#: libvips/conversion/gamma.c:136 +msgid "gamma an image" +msgstr "" + +#: libvips/conversion/gamma.c:148 libvips/conversion/scale.c:168 +msgid "Exponent" +msgstr "" + +#: libvips/conversion/gamma.c:149 +msgid "Gamma factor" +msgstr "" + +#: libvips/conversion/grid.c:165 +msgid "bad grid geometry" +msgstr "" + +#: libvips/conversion/grid.c:195 +msgid "grid an image" +msgstr "" + +#: libvips/conversion/grid.c:206 +msgid "Chop into tiles this high" +msgstr "" + +#: libvips/conversion/grid.c:213 +msgid "Number of tiles across" +msgstr "" + +#: libvips/conversion/grid.c:220 +msgid "Number of tiles down" +msgstr "" + +#: libvips/conversion/ifthenelse.c:525 +msgid "ifthenelse an image" +msgstr "" + +#: libvips/conversion/ifthenelse.c:529 +msgid "Condition" +msgstr "" + +#: libvips/conversion/ifthenelse.c:530 +msgid "Condition input image" +msgstr "" + +#: libvips/conversion/ifthenelse.c:535 +msgid "Then image" +msgstr "" + +#: libvips/conversion/ifthenelse.c:536 +msgid "Source for TRUE pixels" +msgstr "" + +#: libvips/conversion/ifthenelse.c:541 +msgid "Else image" +msgstr "" + +#: libvips/conversion/ifthenelse.c:542 +msgid "Source for FALSE pixels" +msgstr "" + +#: libvips/conversion/ifthenelse.c:547 +msgid "Blend" +msgstr "" + +#: libvips/conversion/ifthenelse.c:548 +msgid "Blend smoothly between then and else parts" +msgstr "" + +#: libvips/conversion/insert.c:460 +msgid "insert image @sub into @main at @x, @y" +msgstr "" + +#: libvips/conversion/insert.c:466 +msgid "Main" +msgstr "" + +#: libvips/conversion/insert.c:467 +msgid "Main input image" +msgstr "" + +#: libvips/conversion/insert.c:472 libvips/draw/draw_image.c:269 +msgid "Sub-image" +msgstr "" + +#: libvips/conversion/insert.c:473 libvips/draw/draw_image.c:270 +msgid "Sub-image to insert into main image" +msgstr "" + +#: libvips/conversion/insert.c:478 +msgid "X" +msgstr "" + +#: libvips/conversion/insert.c:479 +msgid "Left edge of sub in main" +msgstr "" + +#: libvips/conversion/insert.c:485 +msgid "Y" +msgstr "" + +#: libvips/conversion/insert.c:486 +msgid "Top edge of sub in main" +msgstr "" + +#: libvips/conversion/insert.c:492 libvips/conversion/join.c:256 +msgid "Expand" +msgstr "" + +#: libvips/conversion/insert.c:493 libvips/conversion/join.c:257 +msgid "Expand output to hold all of both inputs" +msgstr "" + +#: libvips/conversion/insert.c:500 +msgid "Color for new pixels" +msgstr "" + +#: libvips/conversion/join.c:231 +msgid "join a pair of images" +msgstr "" + +#: libvips/conversion/join.c:237 +msgid "in1" +msgstr "" + +#: libvips/conversion/join.c:238 +msgid "First input image" +msgstr "" + +#: libvips/conversion/join.c:243 libvips/freqfilt/phasecor.c:111 +msgid "in2" +msgstr "" + +#: libvips/conversion/join.c:244 libvips/freqfilt/phasecor.c:112 +msgid "Second input image" +msgstr "" + +#: libvips/conversion/join.c:250 +msgid "Join left-right or up-down" +msgstr "" + +#: libvips/conversion/join.c:277 libvips/create/text.c:581 +msgid "Align" +msgstr "" + +#: libvips/conversion/join.c:278 +msgid "Align on the low, centre or high coordinate edge" +msgstr "" + +#: libvips/conversion/msb.c:168 +msgid "bad band" +msgstr "" + +#: libvips/conversion/msb.c:241 +msgid "pick most-significant byte from an image" +msgstr "" + +#: libvips/conversion/msb.c:254 +msgid "Band to msb" +msgstr "" + +#: libvips/conversion/premultiply.c:255 +msgid "premultiply image alpha" +msgstr "" + +#: libvips/conversion/recomb.c:183 +msgid "bands in must equal matrix width" +msgstr "" + +#: libvips/conversion/recomb.c:218 +msgid "linear recombination with matrix" +msgstr "" + +#: libvips/conversion/recomb.c:230 +msgid "M" +msgstr "" + +#: libvips/conversion/recomb.c:231 +msgid "Matrix of coefficients" +msgstr "" + +#: libvips/conversion/replicate.c:192 +msgid "replicate an image" +msgstr "" + +#: libvips/conversion/replicate.c:203 +msgid "Repeat this many times horizontally" +msgstr "" + +#: libvips/conversion/replicate.c:210 +msgid "Repeat this many times vertically" +msgstr "" + +#: libvips/conversion/rot45.c:264 libvips/conversion/rot.c:361 +msgid "rotate an image" +msgstr "" + +#: libvips/conversion/rot45.c:275 libvips/conversion/rot.c:372 +msgid "Angle to rotate image" +msgstr "" + +#: libvips/conversion/scale.c:151 +msgid "scale an image to uchar" +msgstr "" + +#: libvips/conversion/scale.c:161 libvips/iofuncs/system.c:311 +msgid "Log" +msgstr "" + +#: libvips/conversion/scale.c:162 +msgid "Log scale" +msgstr "" + +#: libvips/conversion/scale.c:169 +msgid "Exponent for log scale" +msgstr "" + +#: libvips/conversion/sequential.c:239 +msgid "check sequential access" +msgstr "" + +#: libvips/conversion/sequential.c:256 +msgid "Strategy" +msgstr "" + +#: libvips/conversion/sequential.c:257 libvips/conversion/tilecache.c:412 +msgid "Expected access pattern" +msgstr "" + +#: libvips/conversion/sequential.c:263 +msgid "Trace" +msgstr "" + +#: libvips/conversion/sequential.c:264 +msgid "Trace pixel requests" +msgstr "" + +#: libvips/conversion/smartcrop.c:453 +msgid "Interesting" +msgstr "" + +#: libvips/conversion/smartcrop.c:454 +msgid "How to measure interestingness" +msgstr "" + +#: libvips/conversion/smartcrop.c:460 +msgid "Attention x" +msgstr "" + +#: libvips/conversion/smartcrop.c:461 +msgid "Horizontal position of attention centre" +msgstr "" + +#: libvips/conversion/smartcrop.c:467 +msgid "Attention y" +msgstr "" + +#: libvips/conversion/smartcrop.c:468 +msgid "Vertical position of attention centre" +msgstr "" + +#: libvips/conversion/smartcrop.c:475 +msgid "Input image already has premultiplied alpha" +msgstr "" + +#: libvips/conversion/subsample.c:228 libvips/resample/reduceh.cpp:546 +#: libvips/resample/reducev.cpp:1001 libvips/resample/shrinkh.c:316 +#: libvips/resample/shrinkv.c:364 +msgid "image has shrunk to nothing" +msgstr "" + +#: libvips/conversion/subsample.c:259 +msgid "subsample an image" +msgstr "" + +#: libvips/conversion/subsample.c:273 libvips/conversion/zoom.c:379 +msgid "Xfac" +msgstr "" + +#: libvips/conversion/subsample.c:274 +msgid "Horizontal subsample factor" +msgstr "" + +#: libvips/conversion/subsample.c:280 libvips/conversion/zoom.c:386 +msgid "Yfac" +msgstr "" + +#: libvips/conversion/subsample.c:281 +msgid "Vertical subsample factor" +msgstr "" + +#: libvips/conversion/subsample.c:287 +msgid "Point" +msgstr "" + +#: libvips/conversion/subsample.c:288 +msgid "Point sample" +msgstr "" + +#: libvips/conversion/switch.c:129 +msgid "bad number of tests" +msgstr "" + +#: libvips/conversion/switch.c:161 +msgid "test images not 1-band" +msgstr "" + +#: libvips/conversion/switch.c:189 +msgid "find the index of the first non-zero pixel in tests" +msgstr "" + +#: libvips/conversion/switch.c:195 +msgid "Tests" +msgstr "" + +#: libvips/conversion/switch.c:196 +msgid "Table of images to test" +msgstr "" + +#: libvips/conversion/tilecache.c:411 libvips/foreign/foreign.c:1235 +msgid "Access" +msgstr "" + +#: libvips/conversion/tilecache.c:418 +msgid "Threaded" +msgstr "" + +#: libvips/conversion/tilecache.c:419 +msgid "Allow threaded access" +msgstr "" + +#: libvips/conversion/tilecache.c:425 +msgid "Persistent" +msgstr "" + +#: libvips/conversion/tilecache.c:426 +msgid "Keep cache between evaluations" +msgstr "" + +#: libvips/conversion/tilecache.c:708 +#, c-format +msgid "error in tile %d x %d" +msgstr "" + +#: libvips/conversion/tilecache.c:796 +msgid "cache an image as a set of tiles" +msgstr "" + +#: libvips/conversion/tilecache.c:983 +msgid "cache an image as a set of lines" +msgstr "" + +#: libvips/conversion/transpose3d.c:135 +msgid "bad page_height" +msgstr "" + +#: libvips/conversion/transpose3d.c:163 +#, fuzzy +msgid "transpose3d an image" +msgstr "false-colour an image" + +#: libvips/conversion/transpose3d.c:173 libvips/foreign/foreign.c:1915 +msgid "Page height" +msgstr "" + +#: libvips/conversion/transpose3d.c:174 +msgid "Height of each input page" +msgstr "" + +#: libvips/conversion/unpremultiply.c:317 +msgid "unpremultiply image alpha" +msgstr "" + +#: libvips/conversion/unpremultiply.c:336 +msgid "Alpha band" +msgstr "" + +#: libvips/conversion/unpremultiply.c:337 +msgid "Unpremultiply with this alpha" +msgstr "" + +#: libvips/conversion/wrap.c:115 +msgid "wrap image origin" +msgstr "" + +#: libvips/conversion/zoom.c:328 +msgid "zoom factors too large" +msgstr "" + +#: libvips/conversion/zoom.c:367 +msgid "zoom an image" +msgstr "" + +#: libvips/conversion/zoom.c:380 +msgid "Horizontal zoom factor" +msgstr "" + +#: libvips/conversion/zoom.c:387 +msgid "Vertical zoom factor" +msgstr "" + +#: libvips/convolution/canny.c:436 +msgid "Canny edge detector" +msgstr "" + +#: libvips/convolution/canny.c:454 libvips/convolution/gaussblur.c:144 +#: libvips/convolution/sharpen.c:334 libvips/create/gaussmat.c:185 +#: libvips/create/gaussnoise.c:188 +msgid "Sigma" +msgstr "" + +#: libvips/convolution/canny.c:455 libvips/convolution/gaussblur.c:145 +#: libvips/convolution/sharpen.c:335 libvips/create/gaussmat.c:186 +msgid "Sigma of Gaussian" +msgstr "" + +#: libvips/convolution/canny.c:461 libvips/convolution/compass.c:184 +#: libvips/convolution/conv.c:134 libvips/convolution/convsep.c:130 +#: libvips/convolution/gaussblur.c:158 libvips/create/gaussmat.c:213 +#: libvips/create/logmat.c:229 +msgid "Precision" +msgstr "" + +#: libvips/convolution/canny.c:462 libvips/convolution/compass.c:185 +#: libvips/convolution/conv.c:135 libvips/convolution/convsep.c:131 +#: libvips/convolution/gaussblur.c:159 +msgid "Convolve with this precision" +msgstr "" + +#: libvips/convolution/compass.c:159 +msgid "convolve with rotating mask" +msgstr "" + +#: libvips/convolution/compass.c:163 +msgid "Times" +msgstr "" + +#: libvips/convolution/compass.c:164 +msgid "Rotate and convolve this many times" +msgstr "" + +#: libvips/convolution/compass.c:171 +msgid "Rotate mask by this much between convolutions" +msgstr "" + +#: libvips/convolution/compass.c:178 +msgid "Combine convolution results like this" +msgstr "" + +#: libvips/convolution/compass.c:191 libvips/convolution/conva.c:1323 +#: libvips/convolution/convasep.c:918 libvips/convolution/conv.c:141 +#: libvips/convolution/convsep.c:137 +msgid "Layers" +msgstr "" + +#: libvips/convolution/compass.c:192 libvips/convolution/conva.c:1324 +#: libvips/convolution/convasep.c:919 libvips/convolution/conv.c:142 +#: libvips/convolution/convsep.c:138 +msgid "Use this many layers in approximation" +msgstr "" + +#: libvips/convolution/compass.c:198 libvips/convolution/conva.c:1330 +#: libvips/convolution/conv.c:148 libvips/convolution/convsep.c:144 +msgid "Cluster" +msgstr "" + +#: libvips/convolution/compass.c:199 libvips/convolution/conva.c:1331 +#: libvips/convolution/conv.c:149 libvips/convolution/convsep.c:145 +msgid "Cluster lines closer than this in approximation" +msgstr "" + +#: libvips/convolution/conva.c:236 libvips/convolution/conva.c:242 +#: libvips/convolution/conva.c:760 libvips/convolution/convasep.c:151 +msgid "mask too complex" +msgstr "" + +#: libvips/convolution/conva.c:997 libvips/convolution/conva.c:1247 +#: libvips/convolution/convasep.c:840 +msgid "image too small for mask" +msgstr "" + +#: libvips/convolution/conva.c:1319 +msgid "approximate integer convolution" +msgstr "" + +#: libvips/convolution/convasep.c:914 +msgid "approximate separable integer convolution" +msgstr "" + +#: libvips/convolution/conv.c:130 +msgid "convolution operation" +msgstr "" + +#: libvips/convolution/convf.c:374 +msgid "float convolution operation" +msgstr "" + +#: libvips/convolution/convi.c:1245 +msgid "int convolution operation" +msgstr "" + +#: libvips/convolution/convolution.c:119 +msgid "convolution operations" +msgstr "" + +#: libvips/convolution/convolution.c:140 libvips/convolution/correlation.c:156 +#: libvips/draw/draw_mask.c:332 libvips/freqfilt/freqmult.c:130 +#: libvips/morphology/labelregions.c:124 libvips/morphology/morph.c:965 +msgid "Mask" +msgstr "" + +#: libvips/convolution/convolution.c:141 libvips/morphology/morph.c:966 +msgid "Input matrix image" +msgstr "" + +#: libvips/convolution/convsep.c:126 +msgid "separable convolution operation" +msgstr "" + +#: libvips/convolution/correlation.c:144 +msgid "correlation operation" +msgstr "" + +#: libvips/convolution/correlation.c:157 +msgid "Input reference image" +msgstr "" + +#: libvips/convolution/edge.c:213 +msgid "Edge detector" +msgstr "" + +#: libvips/convolution/edge.c:258 +msgid "Sobel edge detector" +msgstr "" + +#: libvips/convolution/edge.c:291 +msgid "Scharr edge detector" +msgstr "" + +#: libvips/convolution/edge.c:324 +msgid "Prewitt edge detector" +msgstr "" + +#: libvips/convolution/fastcor.c:218 +msgid "fast correlation" +msgstr "" + +#: libvips/convolution/gaussblur.c:126 +msgid "gaussian blur" +msgstr "" + +#: libvips/convolution/gaussblur.c:151 libvips/create/gaussmat.c:192 +msgid "Minimum amplitude" +msgstr "" + +#: libvips/convolution/gaussblur.c:152 libvips/create/gaussmat.c:193 +#: libvips/create/logmat.c:209 +msgid "Minimum amplitude of Gaussian" +msgstr "" + +#: libvips/convolution/sharpen.c:316 +msgid "unsharp masking for print" +msgstr "" + +#: libvips/convolution/sharpen.c:341 libvips/draw/draw_line.c:284 +msgid "x1" +msgstr "" + +#: libvips/convolution/sharpen.c:342 +msgid "Flat/jaggy threshold" +msgstr "" + +#: libvips/convolution/sharpen.c:348 libvips/draw/draw_line.c:305 +msgid "y2" +msgstr "" + +#: libvips/convolution/sharpen.c:349 +msgid "Maximum brightening" +msgstr "" + +#: libvips/convolution/sharpen.c:355 +msgid "y3" +msgstr "" + +#: libvips/convolution/sharpen.c:356 +msgid "Maximum darkening" +msgstr "" + +#: libvips/convolution/sharpen.c:362 +msgid "m1" +msgstr "" + +#: libvips/convolution/sharpen.c:363 +msgid "Slope for flat areas" +msgstr "" + +#: libvips/convolution/sharpen.c:369 +msgid "m2" +msgstr "" + +#: libvips/convolution/sharpen.c:370 +msgid "Slope for jaggy areas" +msgstr "" + +#: libvips/convolution/sharpen.c:378 libvips/create/logmat.c:201 +#: libvips/create/mask_butterworth_band.c:136 +#: libvips/create/mask_gaussian_band.c:121 libvips/create/mask_ideal_band.c:112 +#: libvips/create/sdf.c:326 libvips/draw/draw_circle.c:248 +msgid "Radius" +msgstr "" + +#: libvips/convolution/sharpen.c:379 libvips/create/logmat.c:202 +msgid "Radius of Gaussian" +msgstr "" + +#: libvips/convolution/spcor.c:317 +msgid "spatial correlation" +msgstr "" + +#: libvips/create/black.c:136 +msgid "make a black image" +msgstr "" + +#: libvips/create/buildlut.c:134 +#, c-format +msgid "x value row %d not an int" +msgstr "" + +#: libvips/create/buildlut.c:149 +msgid "x range too small" +msgstr "" + +#: libvips/create/buildlut.c:259 libvips/create/tonelut.c:221 +msgid "build a look-up table" +msgstr "" + +#: libvips/create/buildlut.c:264 libvips/create/invertlut.c:289 +msgid "Matrix of XY coordinates" +msgstr "" + +#: libvips/create/create.c:120 +msgid "create operations" +msgstr "" + +#: libvips/create/eye.c:103 +msgid "make an image showing the eye's spatial response" +msgstr "" + +#: libvips/create/eye.c:109 +msgid "Maximum spatial frequency" +msgstr "" + +#: libvips/create/fractsurf.c:100 +msgid "make a fractal surface" +msgstr "" + +#: libvips/create/fractsurf.c:118 libvips/create/fractsurf.c:119 +#: libvips/create/mask_fractal.c:93 libvips/create/mask_fractal.c:94 +msgid "Fractal dimension" +msgstr "" + +#: libvips/create/gaussmat.c:129 libvips/create/logmat.c:147 +msgid "mask too large" +msgstr "" + +#: libvips/create/gaussmat.c:181 +msgid "make a gaussian image" +msgstr "" + +#: libvips/create/gaussmat.c:199 libvips/create/logmat.c:215 +msgid "Separable" +msgstr "" + +#: libvips/create/gaussmat.c:200 libvips/create/logmat.c:216 +msgid "Generate separable Gaussian" +msgstr "" + +#: libvips/create/gaussmat.c:206 libvips/create/logmat.c:222 +msgid "Integer" +msgstr "" + +#: libvips/create/gaussmat.c:207 libvips/create/logmat.c:223 +msgid "Generate integer Gaussian" +msgstr "" + +#: libvips/create/gaussmat.c:214 libvips/create/logmat.c:230 +msgid "Generate with this precision" +msgstr "" + +#: libvips/create/gaussnoise.c:159 +msgid "make a gaussnoise image" +msgstr "" + +#: libvips/create/gaussnoise.c:181 libvips/histogram/stdif.c:329 +msgid "Mean" +msgstr "" + +#: libvips/create/gaussnoise.c:182 +msgid "Mean of pixels in generated image" +msgstr "" + +#: libvips/create/gaussnoise.c:189 +msgid "Standard deviation of pixels in generated image" +msgstr "" + +#: libvips/create/gaussnoise.c:195 libvips/create/perlin.c:322 +#: libvips/create/worley.c:328 +msgid "Seed" +msgstr "" + +#: libvips/create/gaussnoise.c:196 libvips/create/perlin.c:323 +#: libvips/create/worley.c:329 +msgid "Random number seed" +msgstr "" + +#: libvips/create/grey.c:89 +msgid "make a grey ramp image" +msgstr "" + +#: libvips/create/identity.c:139 +msgid "make a 1D image where pixel values are indexes" +msgstr "" + +#: libvips/create/identity.c:144 +msgid "Number of bands in LUT" +msgstr "" + +#: libvips/create/identity.c:150 +msgid "Ushort" +msgstr "" + +#: libvips/create/identity.c:151 +msgid "Create a 16-bit LUT" +msgstr "" + +#: libvips/create/identity.c:158 +msgid "Size of 16-bit LUT" +msgstr "" + +#: libvips/create/invertlut.c:124 +msgid "bad input matrix" +msgstr "" + +#: libvips/create/invertlut.c:129 +msgid "bad size" +msgstr "" + +#: libvips/create/invertlut.c:149 +#, c-format +msgid "element (%d, %d) is %g, outside range [0,1]" +msgstr "" + +#: libvips/create/invertlut.c:284 +msgid "build an inverted look-up table" +msgstr "" + +#: libvips/create/invertlut.c:295 +msgid "LUT size to generate" +msgstr "" + +#: libvips/create/logmat.c:197 +msgid "make a Laplacian of Gaussian image" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:110 +msgid "make a butterworth_band filter" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:115 +#: libvips/create/mask_butterworth.c:91 +msgid "Order" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:116 +#: libvips/create/mask_butterworth.c:92 +msgid "Filter order" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:122 +#: libvips/create/mask_butterworth_band.c:123 +#: libvips/create/mask_gaussian_band.c:107 +#: libvips/create/mask_gaussian_band.c:108 libvips/create/mask_ideal_band.c:98 +#: libvips/create/mask_ideal_band.c:99 +msgid "Frequency cutoff x" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:129 +#: libvips/create/mask_butterworth_band.c:130 +#: libvips/create/mask_gaussian_band.c:114 +#: libvips/create/mask_gaussian_band.c:115 libvips/create/mask_ideal_band.c:105 +#: libvips/create/mask_ideal_band.c:106 +msgid "Frequency cutoff y" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:137 +#: libvips/create/mask_gaussian_band.c:122 libvips/create/mask_ideal_band.c:113 +msgid "Radius of circle" +msgstr "" + +#: libvips/create/mask_butterworth_band.c:143 +#: libvips/create/mask_butterworth_band.c:144 +#: libvips/create/mask_butterworth.c:105 libvips/create/mask_butterworth.c:106 +#: libvips/create/mask_gaussian_band.c:128 +#: libvips/create/mask_gaussian_band.c:129 libvips/create/mask_gaussian.c:93 +#: libvips/create/mask_gaussian.c:94 +msgid "Amplitude cutoff" +msgstr "" + +#: libvips/create/mask_butterworth.c:86 +msgid "make a butterworth filter" +msgstr "" + +#: libvips/create/mask_butterworth.c:98 libvips/create/mask_butterworth.c:99 +#: libvips/create/mask_gaussian.c:86 libvips/create/mask_gaussian.c:87 +#: libvips/create/mask_ideal.c:84 libvips/create/mask_ideal.c:85 +msgid "Frequency cutoff" +msgstr "" + +#: libvips/create/mask_butterworth_ring.c:101 +msgid "make a butterworth ring filter" +msgstr "" + +#: libvips/create/mask_butterworth_ring.c:106 +#: libvips/create/mask_butterworth_ring.c:107 +#: libvips/create/mask_gaussian_ring.c:101 +#: libvips/create/mask_gaussian_ring.c:102 libvips/create/mask_ideal_ring.c:98 +#: libvips/create/mask_ideal_ring.c:99 +msgid "Ringwidth" +msgstr "" + +#: libvips/create/mask.c:114 +msgid "base class for frequency filters" +msgstr "" + +#: libvips/create/mask.c:122 +msgid "Optical" +msgstr "" + +#: libvips/create/mask.c:123 +msgid "Rotate quadrants to optical space" +msgstr "" + +#: libvips/create/mask.c:129 +msgid "Reject" +msgstr "" + +#: libvips/create/mask.c:130 +msgid "Invert the sense of the filter" +msgstr "" + +#: libvips/create/mask.c:136 +msgid "Nodc" +msgstr "" + +#: libvips/create/mask.c:137 +msgid "Remove DC component" +msgstr "" + +#: libvips/create/mask_fractal.c:88 +msgid "make fractal filter" +msgstr "" + +#: libvips/create/mask_gaussian_band.c:102 libvips/create/mask_gaussian.c:81 +msgid "make a gaussian filter" +msgstr "" + +#: libvips/create/mask_gaussian_ring.c:96 +msgid "make a gaussian ring filter" +msgstr "" + +#: libvips/create/mask_ideal_band.c:93 +msgid "make an ideal band filter" +msgstr "" + +#: libvips/create/mask_ideal.c:79 +msgid "make an ideal filter" +msgstr "" + +#: libvips/create/mask_ideal_ring.c:93 +msgid "make an ideal ring filter" +msgstr "" + +#: libvips/create/perlin.c:290 +msgid "make a perlin noise image" +msgstr "" + +#: libvips/create/perlin.c:308 libvips/create/worley.c:321 +msgid "Cell size" +msgstr "" + +#: libvips/create/perlin.c:309 +msgid "Size of Perlin cells" +msgstr "" + +#: libvips/create/perlin.c:315 libvips/create/point.c:155 +msgid "Uchar" +msgstr "" + +#: libvips/create/perlin.c:316 libvips/create/point.c:156 +msgid "Output an unsigned char image" +msgstr "" + +#: libvips/create/point.c:132 +msgid "make a point image" +msgstr "" + +#: libvips/create/sdf.c:178 +msgid "circle needs a, r to be set" +msgstr "" + +#: libvips/create/sdf.c:183 +msgid "rounded-box needs 2 values for a" +msgstr "" + +#: libvips/create/sdf.c:196 +msgid "box needs a, b to be set" +msgstr "" + +#: libvips/create/sdf.c:202 +msgid "box needs 2 values for a, b" +msgstr "" + +#: libvips/create/sdf.c:216 +msgid "rounded-box needs a, b to be set" +msgstr "" + +#: libvips/create/sdf.c:222 +msgid "rounded-box needs 2 values for a, b" +msgstr "" + +#: libvips/create/sdf.c:227 +msgid "rounded-box needs 4 values for corners" +msgstr "" + +#: libvips/create/sdf.c:242 +msgid "line needs sx, sy to be set" +msgstr "" + +#: libvips/create/sdf.c:248 +msgid "line needs 2 values for a, b" +msgstr "" + +#: libvips/create/sdf.c:259 +#, c-format +msgid "unknown SDF %d" +msgstr "" + +#: libvips/create/sdf.c:300 +msgid "create an SDF image" +msgstr "" + +#: libvips/create/sdf.c:318 +msgid "Shape" +msgstr "" + +#: libvips/create/sdf.c:319 +msgid "SDF shape to create" +msgstr "" + +#: libvips/create/sdf.c:325 +msgid "r" +msgstr "" + +#: libvips/create/sdf.c:333 +msgid "Point a" +msgstr "" + +#: libvips/create/sdf.c:340 +msgid "Point b" +msgstr "" + +#: libvips/create/sdf.c:346 +msgid "corners" +msgstr "" + +#: libvips/create/sdf.c:347 +msgid "Corner radii" +msgstr "" + +#: libvips/create/sines.c:122 +msgid "make a 2D sine wave" +msgstr "" + +#: libvips/create/sines.c:128 +msgid "hfreq" +msgstr "" + +#: libvips/create/sines.c:129 +msgid "Horizontal spatial frequency" +msgstr "" + +#: libvips/create/sines.c:135 +msgid "vfreq" +msgstr "" + +#: libvips/create/sines.c:136 +msgid "Vertical spatial frequency" +msgstr "" + +#: libvips/create/text.c:406 +msgid "invalid markup in text" +msgstr "" + +#: libvips/create/text.c:428 +#, c-format +msgid "unable to load fontfile \"%s\"" +msgstr "" + +#: libvips/create/text.c:467 +msgid "no text to render" +msgstr "" + +#: libvips/create/text.c:549 +msgid "make a text image" msgstr "" -#: ../libvips/conversion/bandjoin.c:401 -msgid "Constants" +#: libvips/create/text.c:553 +msgid "Text" msgstr "" -#: ../libvips/conversion/bandjoin.c:402 -msgid "Array of constants to add" +#: libvips/create/text.c:554 +msgid "Text to render" msgstr "" -#: ../libvips/conversion/rot45.c:263 ../libvips/conversion/rot.c:355 -msgid "rotate an image" +#: libvips/create/text.c:560 +msgid "Font" msgstr "" -#: ../libvips/conversion/rot45.c:273 ../libvips/conversion/autorot.c:184 -#: ../libvips/conversion/rot.c:365 ../libvips/convolution/compass.c:157 -#: ../libvips/foreign/dzsave.c:2178 ../libvips/mosaicing/mosaic.c:282 -#: ../libvips/resample/similarity.c:178 -msgid "Angle" +#: libvips/create/text.c:561 +msgid "Font to render with" msgstr "" -#: ../libvips/conversion/rot45.c:274 ../libvips/conversion/rot.c:366 -msgid "Angle to rotate image" +#: libvips/create/text.c:568 +msgid "Maximum image width in pixels" msgstr "" -#: ../libvips/conversion/msb.c:166 -msgid "bad band" +#: libvips/create/text.c:575 +msgid "Maximum image height in pixels" msgstr "" -#: ../libvips/conversion/msb.c:238 -msgid "pick most-significant byte from an image" +#: libvips/create/text.c:582 +msgid "Align on the low, centre or high edge" msgstr "" -#: ../libvips/conversion/msb.c:251 -msgid "Band to msb" +#: libvips/create/text.c:588 +msgid "Justify" msgstr "" -#: ../libvips/conversion/extract.c:150 -msgid "bad extract area" +#: libvips/create/text.c:589 +msgid "Justify lines" msgstr "" -#: ../libvips/conversion/extract.c:193 -msgid "extract an area from an image" +#: libvips/create/text.c:595 libvips/foreign/pdfiumload.c:709 +#: libvips/foreign/popplerload.c:559 libvips/foreign/svgload.c:717 +msgid "DPI" msgstr "" -#: ../libvips/conversion/extract.c:387 -msgid "bad extract band" +#: libvips/create/text.c:596 libvips/foreign/pdfiumload.c:710 +#: libvips/foreign/popplerload.c:560 +msgid "DPI to render at" msgstr "" -#: ../libvips/conversion/extract.c:416 -msgid "extract band from an image" +#: libvips/create/text.c:602 +msgid "Autofit DPI" msgstr "" -#: ../libvips/conversion/extract.c:429 -msgid "Band to extract" +#: libvips/create/text.c:603 +msgid "DPI selected by autofit" msgstr "" -#: ../libvips/conversion/extract.c:435 ../libvips/foreign/magickload.c:138 -#: ../libvips/foreign/gifload.c:823 ../libvips/foreign/magick7load.c:400 -#: ../libvips/foreign/pdfload.c:475 ../libvips/foreign/tiffload.c:106 -msgid "n" +#: libvips/create/text.c:609 +msgid "Spacing" msgstr "" -#: ../libvips/conversion/extract.c:436 -msgid "Number of bands to extract" +#: libvips/create/text.c:610 +msgid "Line spacing" msgstr "" -#: ../libvips/conversion/cast.c:131 -#, c-format -msgid "%d underflows and %d overflows detected" +#: libvips/create/text.c:616 +msgid "Font file" msgstr "" -#: ../libvips/conversion/cast.c:542 -msgid "cast an image" +#: libvips/create/text.c:617 +msgid "Load this font file" msgstr "" -#: ../libvips/conversion/cast.c:555 -msgid "Format to cast to" +#: libvips/create/text.c:623 +msgid "RGBA" msgstr "" -#: ../libvips/conversion/cast.c:561 -msgid "Shift" +#: libvips/create/text.c:624 +msgid "Enable RGBA output" msgstr "" -#: ../libvips/conversion/cast.c:562 -msgid "Shift integer values up and down" +#: libvips/create/text.c:630 +msgid "Wrap" msgstr "" -#: ../libvips/conversion/bandunfold.c:125 -msgid "@factor must be a factor of image bands" +#: libvips/create/text.c:631 +msgid "Wrap lines on word or character boundaries" msgstr "" -#: ../libvips/conversion/bandunfold.c:157 -msgid "unfold image bands into x axis" +#: libvips/create/tonelut.c:225 +msgid "In-max" msgstr "" -#: ../libvips/conversion/bandunfold.c:170 -msgid "Unfold by this factor" +#: libvips/create/tonelut.c:226 +msgid "Size of LUT to build" msgstr "" -#: ../libvips/conversion/tilecache.c:410 ../libvips/conversion/cache.c:97 -msgid "cache an image" +#: libvips/create/tonelut.c:232 +msgid "Out-max" msgstr "" -#: ../libvips/conversion/tilecache.c:422 ../libvips/conversion/sequential.c:340 -#: ../libvips/conversion/cache.c:114 ../libvips/conversion/grid.c:205 -#: ../libvips/foreign/tiffsave.c:225 ../libvips/foreign/dzsave.c:2224 -msgid "Tile height" +#: libvips/create/tonelut.c:233 +msgid "Maximum value in output LUT" msgstr "" -#: ../libvips/conversion/tilecache.c:423 ../libvips/conversion/sequential.c:341 -#: ../libvips/conversion/cache.c:115 ../libvips/foreign/tiffsave.c:226 -#: ../libvips/foreign/dzsave.c:2225 -msgid "Tile height in pixels" +#: libvips/create/tonelut.c:239 +msgid "Black point" msgstr "" -#: ../libvips/conversion/tilecache.c:429 ../libvips/conversion/tilecache.c:999 -#: ../libvips/foreign/foreign.c:1004 -msgid "Access" +#: libvips/create/tonelut.c:240 +msgid "Lowest value in output" msgstr "" -#: ../libvips/conversion/tilecache.c:430 ../libvips/conversion/tilecache.c:1000 -#: ../libvips/conversion/sequential.c:348 -msgid "Expected access pattern" +#: libvips/create/tonelut.c:246 +msgid "White point" msgstr "" -#: ../libvips/conversion/tilecache.c:436 -msgid "Threaded" +#: libvips/create/tonelut.c:247 +msgid "Highest value in output" msgstr "" -#: ../libvips/conversion/tilecache.c:437 -msgid "Allow threaded access" +#: libvips/create/tonelut.c:253 +msgid "Shadow point" msgstr "" -#: ../libvips/conversion/tilecache.c:443 -msgid "Persistent" +#: libvips/create/tonelut.c:254 +msgid "Position of shadow" msgstr "" -#: ../libvips/conversion/tilecache.c:444 -msgid "Keep cache between evaluations" +#: libvips/create/tonelut.c:260 +msgid "Mid-tone point" msgstr "" -#: ../libvips/conversion/tilecache.c:704 -#, c-format -msgid "error in tile %d x %d" +#: libvips/create/tonelut.c:261 +msgid "Position of mid-tones" msgstr "" -#: ../libvips/conversion/tilecache.c:795 -msgid "cache an image as a set of tiles" +#: libvips/create/tonelut.c:267 +msgid "Highlight point" msgstr "" -#: ../libvips/conversion/tilecache.c:799 ../libvips/conversion/cache.c:107 -#: ../libvips/foreign/tiffsave.c:218 ../libvips/foreign/dzsave.c:2217 -msgid "Tile width" +#: libvips/create/tonelut.c:268 +msgid "Position of highlights" msgstr "" -#: ../libvips/conversion/tilecache.c:800 ../libvips/conversion/cache.c:108 -#: ../libvips/foreign/tiffsave.c:219 ../libvips/foreign/dzsave.c:2218 -msgid "Tile width in pixels" +#: libvips/create/tonelut.c:274 +msgid "Shadow adjust" msgstr "" -#: ../libvips/conversion/tilecache.c:806 ../libvips/conversion/cache.c:121 -msgid "Max tiles" +#: libvips/create/tonelut.c:275 +msgid "Adjust shadows by this much" msgstr "" -#: ../libvips/conversion/tilecache.c:807 ../libvips/conversion/cache.c:122 -msgid "Maximum number of tiles to cache" +#: libvips/create/tonelut.c:281 +msgid "Mid-tone adjust" msgstr "" -#: ../libvips/conversion/tilecache.c:995 -msgid "cache an image as a set of lines" +#: libvips/create/tonelut.c:282 +msgid "Adjust mid-tones by this much" msgstr "" -#: ../libvips/conversion/sequential.c:323 -msgid "check sequential access" +#: libvips/create/tonelut.c:288 +msgid "Highlight adjust" msgstr "" -#: ../libvips/conversion/sequential.c:333 -msgid "trace" +#: libvips/create/tonelut.c:289 +msgid "Adjust highlights by this much" msgstr "" -#: ../libvips/conversion/sequential.c:334 -msgid "trace pixel requests" +#: libvips/create/worley.c:303 +msgid "make a worley noise image" msgstr "" -#: ../libvips/conversion/sequential.c:347 -msgid "Strategy" +#: libvips/create/worley.c:322 +msgid "Size of Worley cells" msgstr "" -#: ../libvips/conversion/premultiply.c:253 -msgid "premultiply image alpha" +#: libvips/create/xyz.c:139 +msgid "lower dimensions not set" msgstr "" -#: ../libvips/conversion/bandmean.c:192 -msgid "band-wise average" +#: libvips/create/xyz.c:156 libvips/foreign/heifsave.c:682 +#: libvips/foreign/webpsave.c:734 +msgid "image too large" msgstr "" -#: ../libvips/conversion/bandmean.c:199 ../libvips/conversion/bandbool.c:215 -#: ../libvips/conversion/recomb.c:208 ../libvips/convolution/convolution.c:130 -#: ../libvips/convolution/correlation.c:152 -#: ../libvips/morphology/morphology.c:118 ../libvips/resample/resample.c:133 -msgid "Input image argument" +#: libvips/create/xyz.c:187 +msgid "make an image where pixel values are coordinates" msgstr "" -#: ../libvips/conversion/falsecolour.c:375 -msgid "false-color an image" -msgstr "false-colour an image" - -#: ../libvips/conversion/byteswap.c:200 -msgid "byteswap an image" +#: libvips/create/xyz.c:205 +msgid "csize" msgstr "" -#: ../libvips/conversion/subsample.c:230 ../libvips/resample/shrinkv.c:393 -#: ../libvips/resample/shrinkh.c:289 ../libvips/resample/reduceh.cpp:528 -#: ../libvips/resample/reducev.cpp:801 -msgid "image has shrunk to nothing" +#: libvips/create/xyz.c:206 +msgid "Size of third dimension" msgstr "" -#: ../libvips/conversion/subsample.c:266 -msgid "subsample an image" +#: libvips/create/xyz.c:212 +msgid "dsize" msgstr "" -#: ../libvips/conversion/subsample.c:281 -msgid "Horizontal subsample factor" +#: libvips/create/xyz.c:213 +msgid "Size of fourth dimension" msgstr "" -#: ../libvips/conversion/subsample.c:288 -msgid "Vertical subsample factor" +#: libvips/create/xyz.c:219 +msgid "esize" msgstr "" -#: ../libvips/conversion/subsample.c:294 -msgid "Point" +#: libvips/create/xyz.c:220 +msgid "Size of fifth dimension" msgstr "" -#: ../libvips/conversion/subsample.c:295 -msgid "Point sample" +#: libvips/create/zone.c:90 +msgid "make a zone plate" msgstr "" -#: ../libvips/conversion/bandbool.c:75 -#, c-format -msgid "operator %s not supported across image bands" +#: libvips/draw/draw.c:131 +msgid "draw operations" msgstr "" -#: ../libvips/conversion/bandbool.c:207 -msgid "boolean operation across image bands" +#: libvips/draw/draw.c:138 +msgid "Image" msgstr "" -#: ../libvips/conversion/recomb.c:166 -msgid "bands in must equal matrix width" +#: libvips/draw/draw.c:139 +msgid "Image to draw on" msgstr "" -#: ../libvips/conversion/recomb.c:201 -msgid "linear recombination with matrix" +#: libvips/draw/draw_circle.c:230 +msgid "draw a circle on an image" msgstr "" -#: ../libvips/conversion/recomb.c:213 -msgid "M" +#: libvips/draw/draw_circle.c:234 +msgid "cx" msgstr "" -#: ../libvips/conversion/recomb.c:214 -msgid "matrix of coefficients" +#: libvips/draw/draw_circle.c:235 libvips/draw/draw_circle.c:242 +msgid "Centre of draw_circle" msgstr "" -#: ../libvips/conversion/bandary.c:135 -msgid "no input images" +#: libvips/draw/draw_circle.c:241 +msgid "cy" msgstr "" -#: ../libvips/conversion/bandary.c:186 -msgid "operations on image bands" +#: libvips/draw/draw_circle.c:249 +msgid "Radius in pixels" msgstr "" -#: ../libvips/conversion/ifthenelse.c:479 -msgid "ifthenelse an image" +#: libvips/draw/draw_circle.c:255 libvips/draw/draw_rect.c:201 +msgid "Fill" msgstr "" -#: ../libvips/conversion/ifthenelse.c:483 -msgid "Condition" +#: libvips/draw/draw_circle.c:256 libvips/draw/draw_rect.c:202 +msgid "Draw a solid object" msgstr "" -#: ../libvips/conversion/ifthenelse.c:484 -msgid "Condition input image" +#: libvips/draw/draw_flood.c:562 +msgid "flood-fill an area" msgstr "" -#: ../libvips/conversion/ifthenelse.c:489 -msgid "Then image" +#: libvips/draw/draw_flood.c:567 libvips/draw/draw_flood.c:574 +msgid "DrawFlood start point" msgstr "" -#: ../libvips/conversion/ifthenelse.c:490 -msgid "Source for TRUE pixels" +#: libvips/draw/draw_flood.c:580 +msgid "Test" msgstr "" -#: ../libvips/conversion/ifthenelse.c:495 -msgid "Else image" +#: libvips/draw/draw_flood.c:581 +msgid "Test pixels in this image" msgstr "" -#: ../libvips/conversion/ifthenelse.c:496 -msgid "Source for FALSE pixels" +#: libvips/draw/draw_flood.c:586 +msgid "Equal" msgstr "" -#: ../libvips/conversion/ifthenelse.c:501 -msgid "blend" +#: libvips/draw/draw_flood.c:587 +msgid "DrawFlood while equal to edge" msgstr "" -#: ../libvips/conversion/ifthenelse.c:502 -msgid "Blend smoothly between then and else parts" +#: libvips/draw/draw_flood.c:594 +msgid "Left edge of modified area" msgstr "" -#: ../libvips/conversion/gamma.c:137 -msgid "gamma an image" +#: libvips/draw/draw_flood.c:601 +msgid "Top edge of modified area" msgstr "" -#: ../libvips/conversion/gamma.c:149 -msgid "exponent" +#: libvips/draw/draw_flood.c:608 +msgid "Width of modified area" msgstr "" -#: ../libvips/conversion/gamma.c:150 -msgid "Gamma factor" +#: libvips/draw/draw_flood.c:615 +msgid "Height of modified area" msgstr "" -#: ../libvips/conversion/join.c:228 -msgid "join a pair of images" +#: libvips/draw/draw_image.c:265 +msgid "paint an image into another image" msgstr "" -#: ../libvips/conversion/join.c:232 -msgid "in1" +#: libvips/draw/draw_image.c:276 libvips/draw/draw_image.c:283 +msgid "Draw image here" msgstr "" -#: ../libvips/conversion/join.c:233 -msgid "First input image" +#: libvips/draw/draw_image.c:289 libvips/iofuncs/image.c:1179 +msgid "Mode" msgstr "" -#: ../libvips/conversion/join.c:238 ../libvips/freqfilt/phasecor.c:112 -msgid "in2" +#: libvips/draw/draw_image.c:290 +msgid "Combining mode" msgstr "" -#: ../libvips/conversion/join.c:239 ../libvips/freqfilt/phasecor.c:113 -msgid "Second input image" +#: libvips/draw/drawink.c:86 +msgid "draw with ink operations" msgstr "" -#: ../libvips/conversion/join.c:244 ../libvips/morphology/countlines.c:142 -msgid "direction" +#: libvips/draw/drawink.c:90 +msgid "Ink" msgstr "" -#: ../libvips/conversion/join.c:245 -msgid "Join left-right or up-down" +#: libvips/draw/drawink.c:91 +msgid "Color for pixels" msgstr "" -#: ../libvips/conversion/join.c:251 ../libvips/conversion/insert.c:543 -msgid "Expand" +#: libvips/draw/draw_line.c:280 +msgid "draw a line on an image" msgstr "" -#: ../libvips/conversion/join.c:252 ../libvips/conversion/insert.c:544 -msgid "Expand output to hold all of both inputs" +#: libvips/draw/draw_line.c:285 libvips/draw/draw_line.c:292 +msgid "Start of draw_line" msgstr "" -#: ../libvips/conversion/join.c:272 ../libvips/create/text.c:304 -msgid "Align" +#: libvips/draw/draw_line.c:291 +msgid "y1" msgstr "" -#: ../libvips/conversion/join.c:273 -msgid "Align on the low, centre or high coordinate edge" +#: libvips/draw/draw_line.c:298 +msgid "x2" msgstr "" -#: ../libvips/conversion/grid.c:165 -msgid "bad grid geometry" +#: libvips/draw/draw_line.c:299 libvips/draw/draw_line.c:306 +msgid "End of draw_line" msgstr "" -#: ../libvips/conversion/grid.c:195 -msgid "grid an image" +#: libvips/draw/draw_mask.c:328 +msgid "draw a mask on an image" msgstr "" -#: ../libvips/conversion/grid.c:206 -msgid "chop into tiles this high" +#: libvips/draw/draw_mask.c:333 +msgid "Mask of pixels to draw" msgstr "" -#: ../libvips/conversion/grid.c:213 -msgid "number of tiles across" +#: libvips/draw/draw_mask.c:339 libvips/draw/draw_mask.c:346 +msgid "Draw mask here" msgstr "" -#: ../libvips/conversion/grid.c:220 -msgid "number of tiles down" +#: libvips/draw/draw_rect.c:169 +msgid "paint a rectangle on an image" msgstr "" -#: ../libvips/conversion/scale.c:147 -msgid "scale an image to uchar" +#: libvips/draw/draw_rect.c:174 libvips/draw/draw_rect.c:181 +#: libvips/draw/draw_rect.c:188 libvips/draw/draw_rect.c:195 +#: libvips/draw/draw_smudge.c:216 libvips/draw/draw_smudge.c:223 +#: libvips/draw/draw_smudge.c:230 libvips/draw/draw_smudge.c:237 +msgid "Rect to fill" msgstr "" -#: ../libvips/conversion/scale.c:157 ../libvips/iofuncs/system.c:311 -msgid "Log" +#: libvips/draw/draw_smudge.c:211 +msgid "blur a rectangle on an image" msgstr "" -#: ../libvips/conversion/scale.c:158 -msgid "Log scale" +#: libvips/foreign/analyze2vips.c:308 +msgid "header file size incorrect" msgstr "" -#: ../libvips/conversion/scale.c:164 -msgid "Exponent" +#: libvips/foreign/analyze2vips.c:352 +msgid "header size incorrect" msgstr "" -#: ../libvips/conversion/scale.c:165 -msgid "Exponent for log scale" +#: libvips/foreign/analyze2vips.c:370 libvips/foreign/niftiload.c:399 +#, c-format +msgid "%d-dimensional images not supported" msgstr "" -#: ../libvips/conversion/insert.c:509 -msgid "insert image @sub into @main at @x, @y" +#: libvips/foreign/analyze2vips.c:423 libvips/foreign/niftiload.c:442 +#, c-format +msgid "datatype %d not supported" msgstr "" -#: ../libvips/conversion/insert.c:517 -msgid "Main" +#: libvips/foreign/analyzeload.c:120 +msgid "load an Analyze6 image" msgstr "" -#: ../libvips/conversion/insert.c:518 -msgid "Main input image" +#: libvips/foreign/analyzeload.c:141 libvips/foreign/cgifsave.c:1058 +#: libvips/foreign/csvload.c:590 libvips/foreign/csvsave.c:274 +#: libvips/foreign/dzsave.c:2597 libvips/foreign/fitsload.c:259 +#: libvips/foreign/fitssave.c:143 libvips/foreign/heifload.c:1271 +#: libvips/foreign/heifsave.c:897 libvips/foreign/jp2kload.c:1309 +#: libvips/foreign/jp2ksave.c:1063 libvips/foreign/jpegload.c:354 +#: libvips/foreign/jpegsave.c:361 libvips/foreign/jxlload.c:1218 +#: libvips/foreign/jxlsave.c:897 libvips/foreign/magick6load.c:238 +#: libvips/foreign/magick7load.c:851 libvips/foreign/matload.c:138 +#: libvips/foreign/matrixload.c:374 libvips/foreign/matrixsave.c:228 +#: libvips/foreign/niftiload.c:713 libvips/foreign/niftisave.c:441 +#: libvips/foreign/nsgifload.c:765 libvips/foreign/openexrload.c:149 +#: libvips/foreign/openslideload.c:1152 libvips/foreign/pdfiumload.c:812 +#: libvips/foreign/pngload.c:318 libvips/foreign/pngsave.c:378 +#: libvips/foreign/popplerload.c:689 libvips/foreign/ppmload.c:829 +#: libvips/foreign/ppmsave.c:592 libvips/foreign/radload.c:281 +#: libvips/foreign/radsave.c:154 libvips/foreign/rawload.c:139 +#: libvips/foreign/rawsave.c:196 libvips/foreign/spngload.c:835 +#: libvips/foreign/spngsave.c:858 libvips/foreign/svgload.c:929 +#: libvips/foreign/tiffload.c:382 libvips/foreign/tiffsave.c:527 +#: libvips/foreign/vips2magick.c:578 libvips/foreign/vipsload.c:236 +#: libvips/foreign/vipssave.c:197 libvips/foreign/webpload.c:346 +#: libvips/foreign/webpsave.c:1038 libvips/iofuncs/connection.c:133 +#: libvips/iofuncs/image.c:1172 libvips/resample/thumbnail.c:1198 +msgid "Filename" msgstr "" -#: ../libvips/conversion/insert.c:523 ../libvips/draw/draw_image.c:259 -msgid "Sub-image" +#: libvips/foreign/analyzeload.c:142 libvips/foreign/csvload.c:591 +#: libvips/foreign/fitsload.c:260 libvips/foreign/heifload.c:1272 +#: libvips/foreign/jp2kload.c:1310 libvips/foreign/jpegload.c:355 +#: libvips/foreign/jxlload.c:1219 libvips/foreign/magick6load.c:239 +#: libvips/foreign/magick7load.c:852 libvips/foreign/matload.c:139 +#: libvips/foreign/matrixload.c:375 libvips/foreign/niftiload.c:714 +#: libvips/foreign/nsgifload.c:766 libvips/foreign/openexrload.c:150 +#: libvips/foreign/openslideload.c:1153 libvips/foreign/pdfiumload.c:813 +#: libvips/foreign/pngload.c:319 libvips/foreign/popplerload.c:690 +#: libvips/foreign/ppmload.c:830 libvips/foreign/radload.c:282 +#: libvips/foreign/rawload.c:140 libvips/foreign/spngload.c:836 +#: libvips/foreign/svgload.c:930 libvips/foreign/tiffload.c:383 +#: libvips/foreign/vipsload.c:237 libvips/foreign/webpload.c:347 +msgid "Filename to load from" msgstr "" -#: ../libvips/conversion/insert.c:524 ../libvips/draw/draw_image.c:260 -msgid "Sub-image to insert into main image" +#: libvips/foreign/archive.c:138 +msgid "unable to create archive" msgstr "" -#: ../libvips/conversion/insert.c:529 -msgid "X" +#: libvips/foreign/archive.c:146 +msgid "unable to set zip format" msgstr "" -#: ../libvips/conversion/insert.c:530 -msgid "Left edge of sub in main" +#: libvips/foreign/archive.c:163 +msgid "unable to set compression" msgstr "" -#: ../libvips/conversion/insert.c:536 -msgid "Y" +#: libvips/foreign/archive.c:175 +msgid "unable to set padding" msgstr "" -#: ../libvips/conversion/insert.c:537 -msgid "Top edge of sub in main" +#: libvips/foreign/archive.c:184 libvips/iofuncs/target.c:129 +msgid "unable to open for write" msgstr "" -#: ../libvips/conversion/insert.c:551 -msgid "Color for new pixels" +#: libvips/foreign/archive.c:205 libvips/iofuncs/util.c:1097 +#, c-format +msgid "unable to create directory \"%s\", %s" msgstr "" -#: ../libvips/conversion/autorot.c:174 -msgid "autorotate image by exif tag" +#: libvips/foreign/archive.c:240 +msgid "unable to create entry" msgstr "" -#: ../libvips/conversion/autorot.c:185 -msgid "Angle image was rotated by" +#: libvips/foreign/archive.c:256 +msgid "unable to write header" msgstr "" -#: ../libvips/conversion/bandrank.c:238 -msgid "band-wise rank of a set of images" +#: libvips/foreign/archive.c:265 +msgid "unable to write data" msgstr "" -#: ../libvips/conversion/bandrank.c:252 -msgid "Select this band element from sorted list" +#: libvips/foreign/cgifsave.c:407 libvips/foreign/cgifsave.c:833 +#: libvips/foreign/quantise.c:403 libvips/foreign/quantise.c:423 +msgid "quantisation failed" msgstr "" -#: ../libvips/convolution/spcor.c:315 -msgid "spatial correlation" +#: libvips/foreign/cgifsave.c:587 +msgid "dither failed" msgstr "" -#: ../libvips/convolution/conva.c:237 ../libvips/convolution/conva.c:243 -#: ../libvips/convolution/conva.c:760 ../libvips/convolution/convasep.c:152 -msgid "mask too complex" +#: libvips/foreign/cgifsave.c:772 +msgid "frame too large" msgstr "" -#: ../libvips/convolution/conva.c:988 ../libvips/convolution/conva.c:1216 -#: ../libvips/convolution/convasep.c:823 ../libvips/morphology/hitmiss.c:732 -msgid "image too small for mask" +#: libvips/foreign/cgifsave.c:811 +msgid "gif-palette too large" msgstr "" -#: ../libvips/convolution/conva.c:1288 -msgid "approximate integer convolution" +#: libvips/foreign/cgifsave.c:884 +msgid "save as gif" msgstr "" -#: ../libvips/convolution/conva.c:1292 ../libvips/convolution/compass.c:178 -#: ../libvips/convolution/convasep.c:901 ../libvips/convolution/convsep.c:134 -#: ../libvips/convolution/conv.c:143 -msgid "Layers" +#: libvips/foreign/cgifsave.c:893 libvips/foreign/pngsave.c:247 +#: libvips/foreign/spngsave.c:725 +msgid "Dithering" msgstr "" -#: ../libvips/convolution/conva.c:1293 ../libvips/convolution/compass.c:179 -#: ../libvips/convolution/convasep.c:902 ../libvips/convolution/convsep.c:135 -#: ../libvips/convolution/conv.c:144 -msgid "Use this many layers in approximation" +#: libvips/foreign/cgifsave.c:894 libvips/foreign/pngsave.c:248 +#: libvips/foreign/spngsave.c:726 +msgid "Amount of dithering" msgstr "" -#: ../libvips/convolution/conva.c:1299 ../libvips/convolution/compass.c:185 -#: ../libvips/convolution/convsep.c:141 ../libvips/convolution/conv.c:150 -msgid "Cluster" +#: libvips/foreign/cgifsave.c:900 libvips/foreign/heifsave.c:803 +#: libvips/foreign/jxlsave.c:824 libvips/foreign/pngsave.c:261 +#: libvips/foreign/spngsave.c:739 libvips/foreign/webpsave.c:890 +msgid "Effort" msgstr "" -#: ../libvips/convolution/conva.c:1300 ../libvips/convolution/compass.c:186 -#: ../libvips/convolution/convsep.c:142 ../libvips/convolution/conv.c:151 -msgid "Cluster lines closer than this in approximation" +#: libvips/foreign/cgifsave.c:901 +msgid "Quantisation effort" msgstr "" -#: ../libvips/convolution/fastcor.c:215 -msgid "fast correlation" +#: libvips/foreign/cgifsave.c:907 libvips/foreign/heifsave.c:781 +#: libvips/foreign/pngsave.c:254 libvips/foreign/ppmsave.c:521 +#: libvips/foreign/spngsave.c:732 libvips/foreign/tiffsave.c:315 +#: libvips/foreign/vips2magick.c:510 +msgid "Bit depth" msgstr "" -#: ../libvips/convolution/convi.c:1012 -msgid "int convolution operation" +#: libvips/foreign/cgifsave.c:908 libvips/foreign/heifsave.c:782 +#: libvips/foreign/vips2magick.c:511 +msgid "Number of bits per pixel" msgstr "" -#: ../libvips/convolution/compass.c:146 -msgid "convolve with rotating mask" +#: libvips/foreign/cgifsave.c:914 +msgid "Maximum inter-frame error" msgstr "" -#: ../libvips/convolution/compass.c:150 -msgid "Times" +#: libvips/foreign/cgifsave.c:915 +msgid "Maximum inter-frame error for transparency" msgstr "" -#: ../libvips/convolution/compass.c:151 -msgid "Rotate and convolve this many times" +#: libvips/foreign/cgifsave.c:921 +msgid "Reuse palette" msgstr "" -#: ../libvips/convolution/compass.c:158 -msgid "Rotate mask by this much between convolutions" +#: libvips/foreign/cgifsave.c:922 +msgid "Reuse palette from input" msgstr "" -#: ../libvips/convolution/compass.c:164 -msgid "Combine" +#: libvips/foreign/cgifsave.c:928 +msgid "Maximum inter-palette error" msgstr "" -#: ../libvips/convolution/compass.c:165 -msgid "Combine convolution results like this" +#: libvips/foreign/cgifsave.c:929 +msgid "Maximum inter-palette error for palette reusage" msgstr "" -#: ../libvips/convolution/compass.c:171 ../libvips/convolution/gaussblur.c:145 -#: ../libvips/convolution/convsep.c:127 ../libvips/convolution/conv.c:136 -#: ../libvips/create/logmat.c:229 ../libvips/create/gaussmat.c:212 -msgid "Precision" +#: libvips/foreign/cgifsave.c:935 +msgid "Interlaced" msgstr "" -#: ../libvips/convolution/compass.c:172 ../libvips/convolution/gaussblur.c:146 -#: ../libvips/convolution/convsep.c:128 ../libvips/convolution/conv.c:137 -msgid "Convolve with this precision" +#: libvips/foreign/cgifsave.c:936 +msgid "Generate an interlaced (progressive) GIF" msgstr "" -#: ../libvips/convolution/convolution.c:120 -msgid "convolution operations" +#: libvips/foreign/cgifsave.c:945 +msgid "Reoptimise palettes" msgstr "" -#: ../libvips/convolution/convolution.c:141 -#: ../libvips/convolution/correlation.c:157 ../libvips/draw/draw_mask.c:323 -#: ../libvips/morphology/morph.c:149 ../libvips/morphology/labelregions.c:125 -msgid "Mask" +#: libvips/foreign/cgifsave.c:946 +msgid "Reoptimise colour palettes" msgstr "" -#: ../libvips/convolution/convolution.c:142 ../libvips/morphology/morph.c:150 -msgid "Input matrix image" +#: libvips/foreign/cgifsave.c:952 +msgid "Keep duplicate frames" msgstr "" -#: ../libvips/convolution/convf.c:365 -msgid "float convolution operation" +#: libvips/foreign/cgifsave.c:953 +msgid "Keep duplicate frames in the output instead of combining them" msgstr "" -#: ../libvips/convolution/gaussblur.c:113 -msgid "gaussian blur" +#: libvips/foreign/cgifsave.c:1010 libvips/foreign/csvsave.c:325 +#: libvips/foreign/dzsave.c:2537 libvips/foreign/heifsave.c:1020 +#: libvips/foreign/jp2ksave.c:1182 libvips/foreign/jpegsave.c:292 +#: libvips/foreign/jxlsave.c:1016 libvips/foreign/matrixsave.c:281 +#: libvips/foreign/pngsave.c:326 libvips/foreign/ppmsave.c:648 +#: libvips/foreign/radsave.c:207 libvips/foreign/rawsave.c:252 +#: libvips/foreign/spngsave.c:805 libvips/foreign/tiffsave.c:474 +#: libvips/foreign/vipssave.c:253 libvips/foreign/webpsave.c:987 +#: libvips/iofuncs/target.c:283 +msgid "Target" msgstr "" -#: ../libvips/convolution/gaussblur.c:131 ../libvips/convolution/sharpen.c:325 -#: ../libvips/create/gaussmat.c:184 ../libvips/create/gaussnoise.c:193 -msgid "Sigma" +#: libvips/foreign/cgifsave.c:1011 libvips/foreign/csvsave.c:326 +#: libvips/foreign/dzsave.c:2538 libvips/foreign/heifsave.c:1021 +#: libvips/foreign/jp2ksave.c:1183 libvips/foreign/jpegsave.c:293 +#: libvips/foreign/jxlsave.c:1017 libvips/foreign/matrixsave.c:282 +#: libvips/foreign/pngsave.c:327 libvips/foreign/ppmsave.c:649 +#: libvips/foreign/radsave.c:208 libvips/foreign/rawsave.c:253 +#: libvips/foreign/spngsave.c:806 libvips/foreign/tiffsave.c:475 +#: libvips/foreign/vipssave.c:254 libvips/foreign/webpsave.c:988 +msgid "Target to save to" msgstr "" -#: ../libvips/convolution/gaussblur.c:132 ../libvips/convolution/sharpen.c:326 -#: ../libvips/create/gaussmat.c:185 -msgid "Sigma of Gaussian" +#: libvips/foreign/cgifsave.c:1059 libvips/foreign/csvsave.c:275 +#: libvips/foreign/dzsave.c:2598 libvips/foreign/fitssave.c:144 +#: libvips/foreign/heifsave.c:898 libvips/foreign/jp2ksave.c:1064 +#: libvips/foreign/jpegsave.c:362 libvips/foreign/jxlsave.c:898 +#: libvips/foreign/matrixsave.c:229 libvips/foreign/niftisave.c:442 +#: libvips/foreign/pngsave.c:379 libvips/foreign/ppmsave.c:593 +#: libvips/foreign/radsave.c:155 libvips/foreign/rawsave.c:197 +#: libvips/foreign/spngsave.c:859 libvips/foreign/tiffsave.c:528 +#: libvips/foreign/vips2magick.c:579 libvips/foreign/vipssave.c:198 +#: libvips/foreign/webpsave.c:1039 +msgid "Filename to save to" msgstr "" -#: ../libvips/convolution/gaussblur.c:138 ../libvips/create/gaussmat.c:191 -msgid "Minimum amplitude" +#: libvips/foreign/cgifsave.c:1117 libvips/foreign/dzsave.c:2656 +#: libvips/foreign/heifload.c:1340 libvips/foreign/heifsave.c:962 +#: libvips/foreign/jp2kload.c:1385 libvips/foreign/jp2ksave.c:1126 +#: libvips/foreign/jpegload.c:430 libvips/foreign/jpegsave.c:439 +#: libvips/foreign/jxlload.c:1293 libvips/foreign/jxlsave.c:960 +#: libvips/foreign/magick6load.c:313 libvips/foreign/magick7load.c:932 +#: libvips/foreign/nsgifload.c:843 libvips/foreign/pdfiumload.c:872 +#: libvips/foreign/pngload.c:394 libvips/foreign/pngsave.c:437 +#: libvips/foreign/popplerload.c:749 libvips/foreign/radload.c:356 +#: libvips/foreign/radsave.c:273 libvips/foreign/rawsave.c:314 +#: libvips/foreign/spngload.c:911 libvips/foreign/spngsave.c:918 +#: libvips/foreign/svgload.c:997 libvips/foreign/tiffload.c:460 +#: libvips/foreign/tiffsave.c:588 libvips/foreign/vips2magick.c:650 +#: libvips/foreign/webpload.c:424 libvips/foreign/webpsave.c:1096 +#: libvips/resample/thumbnail.c:1445 +msgid "Buffer" msgstr "" -#: ../libvips/convolution/gaussblur.c:139 ../libvips/create/gaussmat.c:192 -msgid "Minimum amplitude of Gaussian" +#: libvips/foreign/cgifsave.c:1118 libvips/foreign/dzsave.c:2657 +#: libvips/foreign/heifsave.c:963 libvips/foreign/jp2ksave.c:1127 +#: libvips/foreign/jpegsave.c:440 libvips/foreign/jxlsave.c:961 +#: libvips/foreign/pngsave.c:438 libvips/foreign/radsave.c:274 +#: libvips/foreign/rawsave.c:315 libvips/foreign/spngsave.c:919 +#: libvips/foreign/tiffsave.c:589 libvips/foreign/vips2magick.c:651 +#: libvips/foreign/webpsave.c:1097 +msgid "Buffer to save to" msgstr "" -#: ../libvips/convolution/convasep.c:897 -msgid "approximate separable integer convolution" +#: libvips/foreign/csvload.c:301 +#, c-format +msgid "bad number, line %d, column %d" msgstr "" -#: ../libvips/convolution/convsep.c:123 -msgid "seperable convolution operation" +#: libvips/foreign/csvload.c:341 libvips/foreign/csvload.c:402 +#: libvips/foreign/csvload.c:434 +msgid "unexpected end of file" msgstr "" -#: ../libvips/convolution/sharpen.c:307 -msgid "unsharp masking for print" +#: libvips/foreign/csvload.c:440 +#, c-format +msgid "line %d has only %d columns" msgstr "" -#: ../libvips/convolution/sharpen.c:332 ../libvips/draw/draw_line.c:284 -msgid "x1" +#: libvips/foreign/csvload.c:479 +msgid "load csv" msgstr "" -#: ../libvips/convolution/sharpen.c:333 -msgid "Flat/jaggy threshold" +#: libvips/foreign/csvload.c:492 +msgid "Skip" msgstr "" -#: ../libvips/convolution/sharpen.c:339 ../libvips/draw/draw_line.c:305 -msgid "y2" +#: libvips/foreign/csvload.c:493 +msgid "Skip this many lines at the start of the file" msgstr "" -#: ../libvips/convolution/sharpen.c:340 -msgid "Maximum brightening" +#: libvips/foreign/csvload.c:499 +msgid "Lines" msgstr "" -#: ../libvips/convolution/sharpen.c:346 -msgid "y3" +#: libvips/foreign/csvload.c:500 +msgid "Read this many lines from the file" msgstr "" -#: ../libvips/convolution/sharpen.c:347 -msgid "Maximum darkening" +#: libvips/foreign/csvload.c:506 +msgid "Whitespace" msgstr "" -#: ../libvips/convolution/sharpen.c:353 -msgid "m1" +#: libvips/foreign/csvload.c:507 +msgid "Set of whitespace characters" msgstr "" -#: ../libvips/convolution/sharpen.c:354 -msgid "Slope for flat areas" +#: libvips/foreign/csvload.c:513 libvips/foreign/csvsave.c:223 +msgid "Separator" msgstr "" -#: ../libvips/convolution/sharpen.c:360 -msgid "m2" +#: libvips/foreign/csvload.c:514 +msgid "Set of separator characters" msgstr "" -#: ../libvips/convolution/sharpen.c:361 -msgid "Slope for jaggy areas" +#: libvips/foreign/csvload.c:661 libvips/foreign/fitsload.c:338 +#: libvips/foreign/heifload.c:1414 libvips/foreign/jp2kload.c:1448 +#: libvips/foreign/jpegload.c:278 libvips/foreign/jxlload.c:1357 +#: libvips/foreign/matrixload.c:462 libvips/foreign/niftiload.c:792 +#: libvips/foreign/nsgifload.c:909 libvips/foreign/openslideload.c:1230 +#: libvips/foreign/pdfiumload.c:932 libvips/foreign/pngload.c:242 +#: libvips/foreign/popplerload.c:809 libvips/foreign/ppmload.c:890 +#: libvips/foreign/radload.c:205 libvips/foreign/spngload.c:757 +#: libvips/foreign/svgload.c:836 libvips/foreign/tiffload.c:302 +#: libvips/foreign/vipsload.c:312 libvips/foreign/webpload.c:266 +#: libvips/resample/thumbnail.c:1658 +msgid "Source" msgstr "" -#: ../libvips/convolution/sharpen.c:369 ../libvips/create/logmat.c:201 -#: ../libvips/draw/draw_circle.c:249 -msgid "Radius" +#: libvips/foreign/csvload.c:662 libvips/foreign/fitsload.c:339 +#: libvips/foreign/heifload.c:1415 libvips/foreign/jp2kload.c:1449 +#: libvips/foreign/jpegload.c:279 libvips/foreign/jxlload.c:1358 +#: libvips/foreign/matrixload.c:463 libvips/foreign/niftiload.c:793 +#: libvips/foreign/nsgifload.c:910 libvips/foreign/openslideload.c:1231 +#: libvips/foreign/pdfiumload.c:933 libvips/foreign/pngload.c:243 +#: libvips/foreign/popplerload.c:810 libvips/foreign/ppmload.c:891 +#: libvips/foreign/radload.c:206 libvips/foreign/spngload.c:758 +#: libvips/foreign/svgload.c:837 libvips/foreign/tiffload.c:303 +#: libvips/foreign/vipsload.c:313 libvips/foreign/webpload.c:267 +#: libvips/iofuncs/sbuf.c:89 libvips/resample/thumbnail.c:1659 +msgid "Source to load from" msgstr "" -#: ../libvips/convolution/sharpen.c:370 -msgid "radius of Gaussian" +#: libvips/foreign/csvsave.c:215 +msgid "save image to csv" msgstr "" -#: ../libvips/convolution/conv.c:132 -msgid "convolution operation" +#: libvips/foreign/csvsave.c:224 +msgid "Separator characters" msgstr "" -#: ../libvips/convolution/correlation.c:145 -msgid "correlation operation" +#: libvips/foreign/dzsave.c:2008 +msgid "overlap too large" msgstr "" -#: ../libvips/convolution/correlation.c:158 -msgid "Input reference image" +#: libvips/foreign/dzsave.c:2319 +msgid "save image to deep zoom format" msgstr "" -#: ../libvips/create/sines.c:121 -msgid "make a 2D sine wave" +#: libvips/foreign/dzsave.c:2329 libvips/foreign/dzsave.c:2330 +msgid "Image name" msgstr "" -#: ../libvips/create/sines.c:127 -msgid "hfreq" +#: libvips/foreign/dzsave.c:2336 +msgid "Layout" msgstr "" -#: ../libvips/create/sines.c:128 -msgid "Horizontal spatial frequency" +#: libvips/foreign/dzsave.c:2337 +msgid "Directory layout" msgstr "" -#: ../libvips/create/sines.c:134 -msgid "vfreq" +#: libvips/foreign/dzsave.c:2343 +msgid "Suffix" msgstr "" -#: ../libvips/create/sines.c:135 -msgid "Vertical spatial frequency" +#: libvips/foreign/dzsave.c:2344 +msgid "Filename suffix for tiles" msgstr "" -#: ../libvips/create/grey.c:89 -msgid "make a grey ramp image" +#: libvips/foreign/dzsave.c:2350 +msgid "Overlap" msgstr "" -#: ../libvips/create/mask_ideal.c:79 -msgid "make an ideal filter" +#: libvips/foreign/dzsave.c:2351 +msgid "Tile overlap in pixels" msgstr "" -#: ../libvips/create/mask_ideal.c:84 ../libvips/create/mask_ideal.c:85 -#: ../libvips/create/mask_gaussian.c:86 ../libvips/create/mask_gaussian.c:87 -#: ../libvips/create/mask_butterworth.c:95 -#: ../libvips/create/mask_butterworth.c:96 -msgid "Frequency cutoff" +#: libvips/foreign/dzsave.c:2357 +msgid "Tile size" msgstr "" -#: ../libvips/create/create.c:97 -msgid "create operations" +#: libvips/foreign/dzsave.c:2358 +msgid "Tile size in pixels" msgstr "" -#: ../libvips/create/mask_gaussian.c:81 -#: ../libvips/create/mask_gaussian_band.c:102 -msgid "make a gaussian filter" +#: libvips/foreign/dzsave.c:2365 libvips/foreign/tiffsave.c:379 +msgid "Pyramid depth" msgstr "" -#: ../libvips/create/mask_gaussian.c:93 ../libvips/create/mask_gaussian.c:94 -#: ../libvips/create/mask_butterworth_band.c:141 -#: ../libvips/create/mask_butterworth_band.c:142 -#: ../libvips/create/mask_butterworth.c:102 -#: ../libvips/create/mask_butterworth.c:103 -#: ../libvips/create/mask_gaussian_band.c:128 -#: ../libvips/create/mask_gaussian_band.c:129 -msgid "Amplitude cutoff" +#: libvips/foreign/dzsave.c:2371 +msgid "Center" msgstr "" -#: ../libvips/create/xyz.c:139 -msgid "lower dimensions not set" +#: libvips/foreign/dzsave.c:2372 +msgid "Center image in tile" msgstr "" -#: ../libvips/create/xyz.c:156 -msgid "image too large" +#: libvips/foreign/dzsave.c:2379 +msgid "Rotate image during save" msgstr "" -#: ../libvips/create/xyz.c:189 -msgid "make an image where pixel values are coordinates" +#: libvips/foreign/dzsave.c:2385 +msgid "Container" msgstr "" -#: ../libvips/create/xyz.c:207 -msgid "csize" +#: libvips/foreign/dzsave.c:2386 +msgid "Pyramid container type" msgstr "" -#: ../libvips/create/xyz.c:208 -msgid "Size of third dimension" +#: libvips/foreign/dzsave.c:2392 libvips/foreign/heifsave.c:795 +#: libvips/foreign/pngsave.c:211 libvips/foreign/spngsave.c:689 +#: libvips/foreign/tiffsave.c:257 +msgid "Compression" msgstr "" -#: ../libvips/create/xyz.c:214 -msgid "dsize" +#: libvips/foreign/dzsave.c:2393 +msgid "ZIP deflate compression level" msgstr "" -#: ../libvips/create/xyz.c:215 -msgid "Size of fourth dimension" +#: libvips/foreign/dzsave.c:2399 libvips/foreign/tiffsave.c:357 +msgid "Region shrink" msgstr "" -#: ../libvips/create/xyz.c:221 -msgid "esize" +#: libvips/foreign/dzsave.c:2400 libvips/foreign/tiffsave.c:358 +msgid "Method to shrink regions" msgstr "" -#: ../libvips/create/xyz.c:222 -msgid "Size of fifth dimension" +#: libvips/foreign/dzsave.c:2406 +msgid "Skip blanks" msgstr "" -#: ../libvips/create/invertlut.c:124 -msgid "bad input matrix" +#: libvips/foreign/dzsave.c:2407 +msgid "Skip tiles which are nearly equal to the background" msgstr "" -#: ../libvips/create/invertlut.c:129 -msgid "bad size" +#: libvips/foreign/dzsave.c:2413 +msgid "id" msgstr "" -#: ../libvips/create/invertlut.c:149 -#, c-format -msgid "element (%d, %d) is %g, outside range [0,1]" +#: libvips/foreign/dzsave.c:2414 +msgid "Resource ID" msgstr "" -#: ../libvips/create/invertlut.c:285 -msgid "build an inverted look-up table" +#: libvips/foreign/dzsave.c:2420 libvips/foreign/heifsave.c:774 +#: libvips/foreign/jp2ksave.c:1000 libvips/foreign/jpegsave.c:164 +#: libvips/foreign/jxlsave.c:838 libvips/foreign/tiffsave.c:265 +#: libvips/foreign/webpsave.c:826 +msgid "Q" msgstr "" -#: ../libvips/create/invertlut.c:290 ../libvips/create/buildlut.c:262 -msgid "Matrix of XY coordinates" +#: libvips/foreign/dzsave.c:2421 libvips/foreign/heifsave.c:775 +#: libvips/foreign/jp2ksave.c:1001 libvips/foreign/jpegsave.c:165 +#: libvips/foreign/tiffsave.c:266 libvips/foreign/webpsave.c:827 +msgid "Q factor" msgstr "" -#: ../libvips/create/invertlut.c:296 -msgid "LUT size to generate" +#: libvips/foreign/dzsave.c:2430 +msgid "No strip" msgstr "" -#: ../libvips/create/mask_butterworth_ring.c:101 -msgid "make a butterworth ring filter" +#: libvips/foreign/dzsave.c:2431 +msgid "Don't strip tile metadata" msgstr "" -#: ../libvips/create/mask_butterworth_ring.c:106 -#: ../libvips/create/mask_butterworth_ring.c:107 -#: ../libvips/create/mask_gaussian_ring.c:101 -#: ../libvips/create/mask_gaussian_ring.c:102 -#: ../libvips/create/mask_ideal_ring.c:98 -#: ../libvips/create/mask_ideal_ring.c:99 -msgid "Ringwidth" +#: libvips/foreign/dzsave.c:2437 +msgid "Base name" msgstr "" -#: ../libvips/create/logmat.c:147 ../libvips/create/gaussmat.c:133 -msgid "mask too large" +#: libvips/foreign/dzsave.c:2438 +msgid "Base name to save to" msgstr "" -#: ../libvips/create/logmat.c:197 -msgid "make a laplacian of gaussian image" +#: libvips/foreign/dzsave.c:2444 +msgid "Directory name" msgstr "" -#: ../libvips/create/logmat.c:202 -msgid "Radius of Logmatian" +#: libvips/foreign/dzsave.c:2445 +msgid "Directory name to save to" msgstr "" -#: ../libvips/create/logmat.c:209 -msgid "Minimum amplitude of Logmatian" +#: libvips/foreign/dzsave.c:2465 libvips/foreign/tiffsave.c:350 +msgid "Properties" msgstr "" -#: ../libvips/create/logmat.c:215 ../libvips/create/gaussmat.c:198 -msgid "Separable" +#: libvips/foreign/dzsave.c:2466 +msgid "Write a properties file to the output directory" msgstr "" -#: ../libvips/create/logmat.c:216 -msgid "Generate separable Logmatian" +#: libvips/foreign/dzsave.c:2533 +msgid "save image to deepzoom target" msgstr "" -#: ../libvips/create/logmat.c:222 ../libvips/create/gaussmat.c:205 -msgid "Integer" +#: libvips/foreign/dzsave.c:2593 +msgid "save image to deepzoom file" msgstr "" -#: ../libvips/create/logmat.c:223 -msgid "Generate integer Logmatian" +#: libvips/foreign/dzsave.c:2652 +msgid "save image to dz buffer" msgstr "" -#: ../libvips/create/logmat.c:230 ../libvips/create/gaussmat.c:213 -msgid "Generate with this precision" +#: libvips/foreign/exif.c:199 +msgid "exif too small" msgstr "" -#: ../libvips/create/gaussmat.c:180 -msgid "make a gaussian image" +#: libvips/foreign/exif.c:203 +msgid "exif too large" msgstr "" -#: ../libvips/create/gaussmat.c:199 -msgid "Generate separable Gaussian" +#: libvips/foreign/exif.c:208 +msgid "unable to init exif" msgstr "" -#: ../libvips/create/gaussmat.c:206 -msgid "Generate integer Gaussian" +#: libvips/foreign/exif.c:1260 libvips/foreign/exif.c:1270 +#: libvips/foreign/exif.c:1279 libvips/foreign/exif.c:1319 +#, c-format +msgid "bad exif meta \"%s\"" msgstr "" -#: ../libvips/create/worley.c:306 -msgid "make a worley noise image" +#: libvips/foreign/exif.c:1496 +msgid "error saving EXIF" msgstr "" -#: ../libvips/create/worley.c:324 ../libvips/create/perlin.c:311 -msgid "Cell size" +#: libvips/foreign/fits.c:184 libvips/foreign/matlab.c:113 +#: libvips/iofuncs/vips.c:159 libvips/mosaicing/global_balance.c:1240 +#: libvips/mosaicing/global_balance.c:1690 +#, c-format +msgid "unable to open \"%s\"" msgstr "" -#: ../libvips/create/worley.c:325 -msgid "Size of Worley cells" +#: libvips/foreign/fits.c:237 +msgid "no HDU found with naxes > 0" msgstr "" -#: ../libvips/create/mask_gaussian_ring.c:96 -msgid "make a gaussian ring filter" +#: libvips/foreign/fits.c:275 +msgid "dimensions above 3 must be size 1" msgstr "" -#: ../libvips/create/gaussnoise.c:164 -msgid "make a gaussnoise image" +#: libvips/foreign/fits.c:290 +#, c-format +msgid "bad number of axis %d" msgstr "" -#: ../libvips/create/gaussnoise.c:186 ../libvips/histogram/stdif.c:329 -msgid "Mean" +#: libvips/foreign/fits.c:301 +#, c-format +msgid "unsupported bitpix %d\n" msgstr "" -#: ../libvips/create/gaussnoise.c:187 -msgid "Mean of pixels in generated image" +#: libvips/foreign/fits.c:586 libvips/iofuncs/vips.c:222 +#, c-format +msgid "unable to write to \"%s\"" msgstr "" -#: ../libvips/create/gaussnoise.c:194 -msgid "Standard deviation of pixels in generated image" +#: libvips/foreign/fits.c:729 +#, c-format +msgid "unsupported BandFmt %d\n" msgstr "" -#: ../libvips/create/zone.c:90 -msgid "make a zone plate" +#: libvips/foreign/fitsload.c:101 libvips/foreign/niftiload.c:130 +#: libvips/foreign/openslideload.c:916 +msgid "no filename available" msgstr "" -#: ../libvips/create/tonelut.c:221 ../libvips/create/buildlut.c:257 -msgid "build a look-up table" +#: libvips/foreign/fitsload.c:183 +msgid "FITS loader base class" msgstr "" -#: ../libvips/create/tonelut.c:225 -msgid "In-max" +#: libvips/foreign/fitsload.c:251 +msgid "load a FITS image" msgstr "" -#: ../libvips/create/tonelut.c:226 -msgid "Size of LUT to build" +#: libvips/foreign/fitsload.c:329 +msgid "load FITS from a source" msgstr "" -#: ../libvips/create/tonelut.c:232 -msgid "Out-max" +#: libvips/foreign/fitssave.c:129 +msgid "save image to fits file" msgstr "" -#: ../libvips/create/tonelut.c:233 -msgid "Maximum value in output LUT" +#: libvips/foreign/foreign.c:408 +msgid "load and save image files" msgstr "" -#: ../libvips/create/tonelut.c:239 -msgid "Black point" +#: libvips/foreign/foreign.c:607 +#, c-format +msgid "file \"%s\" does not exist" msgstr "" -#: ../libvips/create/tonelut.c:240 -msgid "Lowest value in output" +#: libvips/foreign/foreign.c:612 +#, c-format +msgid "\"%s\" is a directory" msgstr "" -#: ../libvips/create/tonelut.c:246 -msgid "White point" +#: libvips/foreign/foreign.c:621 libvips/foreign/foreign.c:2003 +#, c-format +msgid "\"%s\" is not a known file format" msgstr "" -#: ../libvips/create/tonelut.c:247 -msgid "Highest value in output" +#: libvips/foreign/foreign.c:708 +msgid "buffer is not in a known format" msgstr "" -#: ../libvips/create/tonelut.c:253 -msgid "Shadow point" +#: libvips/foreign/foreign.c:769 +msgid "source is not in a known format" msgstr "" -#: ../libvips/create/tonelut.c:254 -msgid "Position of shadow" +#: libvips/foreign/foreign.c:979 +msgid "images do not match between header and load" msgstr "" -#: ../libvips/create/tonelut.c:260 -msgid "Mid-tone point" +#: libvips/foreign/foreign.c:1210 +msgid "loaders" msgstr "" -#: ../libvips/create/tonelut.c:261 -msgid "Position of mid-tones" +#: libvips/foreign/foreign.c:1221 +msgid "Flags" msgstr "" -#: ../libvips/create/tonelut.c:267 -msgid "Highlight point" +#: libvips/foreign/foreign.c:1222 +msgid "Flags for this file" msgstr "" -#: ../libvips/create/tonelut.c:268 -msgid "Position of highlights" +#: libvips/foreign/foreign.c:1228 libvips/iofuncs/target.c:294 +msgid "Memory" msgstr "" -#: ../libvips/create/tonelut.c:274 -msgid "Shadow adjust" +#: libvips/foreign/foreign.c:1229 +msgid "Force open via memory" msgstr "" -#: ../libvips/create/tonelut.c:275 -msgid "Adjust shadows by this much" +#: libvips/foreign/foreign.c:1236 +msgid "Required access pattern for this file" msgstr "" -#: ../libvips/create/tonelut.c:281 -msgid "Mid-tone adjust" +#: libvips/foreign/foreign.c:1242 libvips/resample/thumbnail.c:1037 +msgid "Fail on" msgstr "" -#: ../libvips/create/tonelut.c:282 -msgid "Adjust mid-tones by this much" +#: libvips/foreign/foreign.c:1243 libvips/resample/thumbnail.c:1038 +msgid "Error level to fail on" msgstr "" -#: ../libvips/create/tonelut.c:288 -msgid "Highlight adjust" +#: libvips/foreign/foreign.c:1249 +msgid "Revalidate" msgstr "" -#: ../libvips/create/tonelut.c:289 -msgid "Adjust highlights by this much" +#: libvips/foreign/foreign.c:1250 +msgid "Don't use a cached result for this operation" msgstr "" -#: ../libvips/create/perlin.c:293 -msgid "make a perlin noise image" +#: libvips/foreign/foreign.c:1256 +msgid "Sequential" msgstr "" -#: ../libvips/create/perlin.c:312 -msgid "Size of Perlin cells" +#: libvips/foreign/foreign.c:1257 +msgid "Sequential read only" msgstr "" -#: ../libvips/create/perlin.c:318 ../libvips/create/point.c:157 -msgid "Uchar" +#: libvips/foreign/foreign.c:1263 +msgid "Fail" msgstr "" -#: ../libvips/create/perlin.c:319 ../libvips/create/point.c:158 -msgid "Output an unsigned char image" +#: libvips/foreign/foreign.c:1264 +msgid "Fail on first warning" msgstr "" -#: ../libvips/create/point.c:134 -msgid "make a point image" +#: libvips/foreign/foreign.c:1270 +msgid "Disc" msgstr "" -#: ../libvips/create/mask.c:111 -msgid "base class for frequency filters" +#: libvips/foreign/foreign.c:1271 +msgid "Open to disc" msgstr "" -#: ../libvips/create/mask.c:119 -msgid "Optical" +#: libvips/foreign/foreign.c:1871 +msgid "savers" msgstr "" -#: ../libvips/create/mask.c:120 -msgid "Rotate quadrants to optical space" +#: libvips/foreign/foreign.c:1895 +msgid "Image to save" msgstr "" -#: ../libvips/create/mask.c:126 -msgid "Reject" +#: libvips/foreign/foreign.c:1900 +msgid "Keep" msgstr "" -#: ../libvips/create/mask.c:127 -msgid "Invert the sense of the filter" +#: libvips/foreign/foreign.c:1901 +msgid "Which metadata to retain" msgstr "" -#: ../libvips/create/mask.c:133 -msgid "Nodc" +#: libvips/foreign/foreign.c:1916 +msgid "Set page height for multipage save" msgstr "" -#: ../libvips/create/mask.c:134 -msgid "Remove DC component" +#: libvips/foreign/foreign.c:1923 +msgid "Filename of ICC profile to embed" msgstr "" -#: ../libvips/create/mask_butterworth_band.c:108 -msgid "make a butterworth_band filter" +#: libvips/foreign/foreign.c:1929 +msgid "Strip" msgstr "" -#: ../libvips/create/mask_butterworth_band.c:113 -#: ../libvips/create/mask_butterworth.c:88 -msgid "Order" +#: libvips/foreign/foreign.c:1930 +msgid "Strip all metadata from image" msgstr "" -#: ../libvips/create/mask_butterworth_band.c:114 -#: ../libvips/create/mask_butterworth.c:89 -msgid "Filter order" +#: libvips/foreign/foreign.c:2158 +#, c-format +msgid "\"%s\" is not a known target format" msgstr "" -#: ../libvips/create/mask_butterworth_band.c:120 -#: ../libvips/create/mask_butterworth_band.c:121 -#: ../libvips/create/mask_gaussian_band.c:107 -#: ../libvips/create/mask_gaussian_band.c:108 -#: ../libvips/create/mask_ideal_band.c:98 -#: ../libvips/create/mask_ideal_band.c:99 -msgid "Frequency cutoff x" +#: libvips/foreign/foreign.c:2216 +#, c-format +msgid "\"%s\" is not a known buffer format" msgstr "" -#: ../libvips/create/mask_butterworth_band.c:127 -#: ../libvips/create/mask_butterworth_band.c:128 -#: ../libvips/create/mask_gaussian_band.c:114 -#: ../libvips/create/mask_gaussian_band.c:115 -#: ../libvips/create/mask_ideal_band.c:105 -#: ../libvips/create/mask_ideal_band.c:106 -msgid "Frequency cutoff y" +#: libvips/foreign/heifload.c:820 libvips/foreign/jxlload.c:753 +#: libvips/foreign/nsgifload.c:448 libvips/foreign/webp2vips.c:501 +msgid "bad page number" msgstr "" -#: ../libvips/create/mask_butterworth_band.c:134 -#: ../libvips/create/mask_gaussian_band.c:121 -#: ../libvips/create/mask_ideal_band.c:112 -msgid "radius" +#: libvips/foreign/heifload.c:872 +msgid "undefined bits per pixel" msgstr "" -#: ../libvips/create/mask_butterworth_band.c:135 -#: ../libvips/create/mask_gaussian_band.c:122 -#: ../libvips/create/mask_ideal_band.c:113 -msgid "radius of circle" +#: libvips/foreign/heifload.c:884 +msgid "not all pages are the same size" msgstr "" -#: ../libvips/create/mask_ideal_ring.c:93 -msgid "make an ideal ring filter" +#: libvips/foreign/heifload.c:983 +msgid "bad image dimensions on decode" msgstr "" -#: ../libvips/create/mask_butterworth.c:83 -msgid "make a butterworth filter" +#: libvips/foreign/heifload.c:990 +msgid "unable to get image data" msgstr "" -#: ../libvips/create/fractsurf.c:98 -msgid "make a fractal surface" +#: libvips/foreign/heifload.c:1075 +msgid "load a HEIF image" msgstr "" -#: ../libvips/create/fractsurf.c:116 ../libvips/create/fractsurf.c:117 -#: ../libvips/create/mask_fractal.c:93 ../libvips/create/mask_fractal.c:94 -msgid "Fractal dimension" +#: libvips/foreign/heifload.c:1083 libvips/foreign/jp2kload.c:1229 +#: libvips/foreign/jxlload.c:1132 libvips/foreign/magick6load.c:141 +#: libvips/foreign/magick7load.c:382 libvips/foreign/nsgifload.c:620 +#: libvips/foreign/pdfiumload.c:695 libvips/foreign/popplerload.c:545 +#: libvips/foreign/tiffload.c:196 libvips/foreign/webpload.c:178 +msgid "Page" msgstr "" -#: ../libvips/create/identity.c:140 -msgid "make a 1D image where pixel values are indexes" +#: libvips/foreign/heifload.c:1084 libvips/foreign/jxlload.c:1133 +#: libvips/foreign/magick6load.c:142 libvips/foreign/magick7load.c:383 +#: libvips/foreign/nsgifload.c:621 libvips/foreign/pdfiumload.c:696 +#: libvips/foreign/popplerload.c:546 libvips/foreign/tiffload.c:197 +#: libvips/foreign/webpload.c:179 +msgid "First page to load" msgstr "" -#: ../libvips/create/identity.c:145 -msgid "Number of bands in LUT" +#: libvips/foreign/heifload.c:1091 libvips/foreign/jxlload.c:1140 +#: libvips/foreign/magick6load.c:149 libvips/foreign/magick7load.c:390 +#: libvips/foreign/nsgifload.c:628 libvips/foreign/pdfiumload.c:703 +#: libvips/foreign/popplerload.c:553 libvips/foreign/tiffload.c:204 +#: libvips/foreign/webpload.c:186 +msgid "Number of pages to load, -1 for all" msgstr "" -#: ../libvips/create/identity.c:151 -msgid "Ushort" +#: libvips/foreign/heifload.c:1097 +msgid "Thumbnail" msgstr "" -#: ../libvips/create/identity.c:152 -msgid "Create a 16-bit LUT" +#: libvips/foreign/heifload.c:1098 +msgid "Fetch thumbnail image" msgstr "" -#: ../libvips/create/identity.c:159 -msgid "Size of 16-bit LUT" +#: libvips/foreign/heifload.c:1104 libvips/foreign/jpegload.c:198 +#: libvips/foreign/tiffload.c:210 +msgid "Autorotate" msgstr "" -#: ../libvips/create/text.c:170 -msgid "invalid markup in text" +#: libvips/foreign/heifload.c:1105 libvips/foreign/jpegload.c:199 +msgid "Rotate image using exif orientation" msgstr "" -#: ../libvips/create/text.c:212 -msgid "no text to render" +#: libvips/foreign/heifload.c:1112 libvips/foreign/jpegload.c:206 +#: libvips/foreign/pngload.c:171 libvips/foreign/spngload.c:678 +#: libvips/foreign/svgload.c:732 libvips/foreign/tiffload.c:225 +msgid "Unlimited" msgstr "" -#: ../libvips/create/text.c:279 -msgid "make a text image" +#: libvips/foreign/heifload.c:1113 libvips/foreign/jpegload.c:207 +#: libvips/foreign/pngload.c:172 libvips/foreign/spngload.c:679 +#: libvips/foreign/tiffload.c:226 +msgid "Remove all denial of service limits" msgstr "" -#: ../libvips/create/text.c:283 -msgid "Text" +#: libvips/foreign/heifload.c:1341 libvips/foreign/jp2kload.c:1386 +#: libvips/foreign/jpegload.c:431 libvips/foreign/jxlload.c:1294 +#: libvips/foreign/magick6load.c:314 libvips/foreign/magick7load.c:933 +#: libvips/foreign/nsgifload.c:844 libvips/foreign/pdfiumload.c:873 +#: libvips/foreign/pngload.c:395 libvips/foreign/popplerload.c:750 +#: libvips/foreign/radload.c:357 libvips/foreign/spngload.c:912 +#: libvips/foreign/svgload.c:998 libvips/foreign/tiffload.c:461 +#: libvips/foreign/webpload.c:425 libvips/resample/thumbnail.c:1446 +msgid "Buffer to load from" msgstr "" -#: ../libvips/create/text.c:284 -msgid "Text to render" +#: libvips/foreign/heifsave.c:441 +#, fuzzy +msgid "unimplemented format conversion" +msgstr "unimplemented output colour space 0x%x" + +#: libvips/foreign/heifsave.c:550 +#, c-format +msgid "%d-bit colour depth not supported" msgstr "" -#: ../libvips/create/text.c:290 -msgid "Font" +#: libvips/foreign/heifsave.c:583 +#, fuzzy +msgid "Unsupported compression" +msgstr "unsupported colour type" + +#: libvips/foreign/heifsave.c:767 +msgid "save image in HEIF format" msgstr "" -#: ../libvips/create/text.c:291 -msgid "Font to render with" +#: libvips/foreign/heifsave.c:788 libvips/foreign/jp2ksave.c:985 +#: libvips/foreign/jxlsave.c:831 libvips/foreign/tiffsave.c:371 +#: libvips/foreign/webpsave.c:833 +msgid "Lossless" msgstr "" -#: ../libvips/create/text.c:298 -msgid "Maximum image width in pixels" +#: libvips/foreign/heifsave.c:789 libvips/foreign/jp2ksave.c:986 +#: libvips/foreign/jxlsave.c:832 libvips/foreign/webpsave.c:834 +msgid "Enable lossless compression" msgstr "" -#: ../libvips/create/text.c:305 -msgid "Align on the low, centre or high edge" +#: libvips/foreign/heifsave.c:796 +msgid "Compression format" msgstr "" -#: ../libvips/create/text.c:311 ../libvips/foreign/pdfload.c:482 -#: ../libvips/foreign/svgload.c:283 -msgid "DPI" +#: libvips/foreign/heifsave.c:804 libvips/foreign/heifsave.c:819 +msgid "CPU effort" msgstr "" -#: ../libvips/create/text.c:312 -msgid "DPI to render at" +#: libvips/foreign/heifsave.c:810 libvips/foreign/jp2ksave.c:992 +#: libvips/foreign/jpegsave.c:220 +msgid "Subsample mode" msgstr "" -#: ../libvips/create/text.c:318 -msgid "Spacing" +#: libvips/foreign/heifsave.c:811 libvips/foreign/jp2ksave.c:993 +#: libvips/foreign/jpegsave.c:221 +msgid "Select chroma subsample operation mode" msgstr "" -#: ../libvips/create/text.c:319 -msgid "Line spacing" +#: libvips/foreign/heifsave.c:818 +msgid "Speed" msgstr "" -#: ../libvips/create/mask_fractal.c:88 -msgid "make fractal filter" +#: libvips/foreign/heifsave.c:825 +msgid "Encoder" msgstr "" -#: ../libvips/create/eye.c:98 -msgid "make an image showing the eye's spatial response" +#: libvips/foreign/heifsave.c:826 +msgid "Select encoder to use" msgstr "" -#: ../libvips/create/eye.c:104 -msgid "Maximum spatial frequency" +#: libvips/foreign/heifsave.c:1047 +msgid "save image in AVIF format" msgstr "" -#: ../libvips/create/black.c:125 -msgid "make a black image" +#: libvips/foreign/jp2kload.c:235 +msgid "unable to create jp2k stream" msgstr "" -#: ../libvips/create/mask_ideal_band.c:93 -msgid "make an ideal band filter" +#: libvips/foreign/jp2kload.c:548 +#, fuzzy, c-format +msgid "unsupported colourspace %d" +msgstr "unsupported colourspace %d" + +#: libvips/foreign/jp2kload.c:597 +msgid "too many image bands" msgstr "" -#: ../libvips/create/buildlut.c:134 -#, c-format -msgid "x value row %d not an int" +#: libvips/foreign/jp2kload.c:601 +msgid "no image components" msgstr "" -#: ../libvips/create/buildlut.c:149 -msgid "x range too small" +#: libvips/foreign/jp2kload.c:618 +msgid "components differ in geometry" msgstr "" -#: ../libvips/draw/draw_line.c:280 -msgid "draw a line on an image" +#: libvips/foreign/jp2kload.c:625 +msgid "components differ in precision" msgstr "" -#: ../libvips/draw/draw_line.c:285 ../libvips/draw/draw_line.c:292 -msgid "Start of draw_line" +#: libvips/foreign/jp2kload.c:996 libvips/foreign/jp2kload.c:1093 +msgid "decoded image does not match container" msgstr "" -#: ../libvips/draw/draw_line.c:291 -msgid "y1" +#: libvips/foreign/jp2kload.c:1217 +msgid "load JPEG2000 image" msgstr "" -#: ../libvips/draw/draw_line.c:298 -msgid "x2" +#: libvips/foreign/jp2kload.c:1230 +msgid "Load this page from the image" msgstr "" -#: ../libvips/draw/draw_line.c:299 ../libvips/draw/draw_line.c:306 -msgid "End of draw_line" +#: libvips/foreign/jp2kload.c:1600 libvips/foreign/jp2ksave.c:1434 +msgid "libvips built without JPEG2000 support" msgstr "" -#: ../libvips/draw/draw_image.c:255 -msgid "paint an image into another image" +#: libvips/foreign/jp2ksave.c:818 +msgid "not an integer format" msgstr "" -#: ../libvips/draw/draw_image.c:266 ../libvips/draw/draw_image.c:273 -msgid "Draw image here" +#: libvips/foreign/jp2ksave.c:963 +msgid "save image in JPEG2000 format" msgstr "" -#: ../libvips/draw/draw_image.c:279 ../libvips/iofuncs/image.c:1207 -msgid "Mode" +#: libvips/foreign/jpeg2vips.c:415 +#, c-format +msgid "read gave %ld warnings" msgstr "" -#: ../libvips/draw/draw_image.c:280 -msgid "Combining mode" +#: libvips/foreign/jpeg2vips.c:886 libvips/foreign/spngload.c:529 +#: libvips/foreign/vipspng.c:723 +#, c-format +msgid "out of order read at line %d" msgstr "" -#: ../libvips/draw/draw_mask.c:319 -msgid "draw a mask on an image" +#: libvips/foreign/jpegload.c:116 +#, c-format +msgid "bad shrink factor %d" msgstr "" -#: ../libvips/draw/draw_mask.c:324 -msgid "Mask of pixels to draw" +#: libvips/foreign/jpegload.c:177 +msgid "load jpeg" msgstr "" -#: ../libvips/draw/draw_mask.c:330 ../libvips/draw/draw_mask.c:337 -msgid "Draw mask here" +#: libvips/foreign/jpegload.c:191 libvips/foreign/webpload.c:199 +msgid "Shrink" msgstr "" -#: ../libvips/draw/draw.c:129 -msgid "draw operations" +#: libvips/foreign/jpegload.c:192 libvips/foreign/webpload.c:200 +msgid "Shrink factor on load" msgstr "" -#: ../libvips/draw/draw.c:133 -msgid "Image" +#: libvips/foreign/jpegload.c:270 +msgid "load image from jpeg source" msgstr "" -#: ../libvips/draw/draw.c:134 -msgid "Image to draw on" +#: libvips/foreign/jpegload.c:346 +msgid "load jpeg from file" msgstr "" -#: ../libvips/draw/draw_smudge.c:193 -msgid "blur a rectangle on an image" +#: libvips/foreign/jpegload.c:424 +msgid "load jpeg from buffer" msgstr "" -#: ../libvips/draw/draw_smudge.c:198 ../libvips/draw/draw_smudge.c:205 -#: ../libvips/draw/draw_smudge.c:212 ../libvips/draw/draw_smudge.c:219 -#: ../libvips/draw/draw_rect.c:174 ../libvips/draw/draw_rect.c:181 -#: ../libvips/draw/draw_rect.c:188 ../libvips/draw/draw_rect.c:195 -msgid "Rect to fill" +#: libvips/foreign/jpegsave.c:153 +msgid "save jpeg" msgstr "" -#: ../libvips/draw/draw_smudge.c:204 ../libvips/draw/draw_rect.c:180 -msgid "top" +#: libvips/foreign/jpegsave.c:171 +msgid "Optimize coding" msgstr "" -#: ../libvips/draw/draw_smudge.c:211 ../libvips/draw/draw_rect.c:187 -msgid "width" +#: libvips/foreign/jpegsave.c:172 +msgid "Compute optimal Huffman coding tables" msgstr "" -#: ../libvips/draw/draw_smudge.c:218 ../libvips/draw/draw_rect.c:194 -msgid "height" +#: libvips/foreign/jpegsave.c:178 libvips/foreign/pngsave.c:218 +#: libvips/foreign/spngsave.c:696 +msgid "Interlace" msgstr "" -#: ../libvips/draw/drawink.c:86 -msgid "draw with ink operations" +#: libvips/foreign/jpegsave.c:179 +msgid "Generate an interlaced (progressive) jpeg" msgstr "" -#: ../libvips/draw/drawink.c:90 -msgid "Ink" +#: libvips/foreign/jpegsave.c:185 +msgid "No subsample" msgstr "" -#: ../libvips/draw/drawink.c:91 -msgid "Color for pixels" +#: libvips/foreign/jpegsave.c:186 +msgid "Disable chroma subsample" msgstr "" -#: ../libvips/draw/draw_circle.c:231 -msgid "draw a circle on an image" +#: libvips/foreign/jpegsave.c:192 +msgid "Trellis quantisation" msgstr "" -#: ../libvips/draw/draw_circle.c:235 -msgid "cx" +#: libvips/foreign/jpegsave.c:193 +msgid "Apply trellis quantisation to each 8x8 block" msgstr "" -#: ../libvips/draw/draw_circle.c:236 ../libvips/draw/draw_circle.c:243 -msgid "Centre of draw_circle" +#: libvips/foreign/jpegsave.c:199 +msgid "Overshoot de-ringing" msgstr "" -#: ../libvips/draw/draw_circle.c:242 -msgid "cy" +#: libvips/foreign/jpegsave.c:200 +msgid "Apply overshooting to samples with extreme values" msgstr "" -#: ../libvips/draw/draw_circle.c:250 -msgid "Radius in pixels" +#: libvips/foreign/jpegsave.c:206 +msgid "Optimize scans" msgstr "" -#: ../libvips/draw/draw_circle.c:256 ../libvips/draw/draw_rect.c:201 -msgid "Fill" +#: libvips/foreign/jpegsave.c:207 +msgid "Split spectrum of DCT coefficients into separate scans" msgstr "" -#: ../libvips/draw/draw_circle.c:257 ../libvips/draw/draw_rect.c:202 -msgid "Draw a solid object" +#: libvips/foreign/jpegsave.c:213 +msgid "Quantization table" msgstr "" -#: ../libvips/draw/draw_flood.c:548 -msgid "flood-fill an area" +#: libvips/foreign/jpegsave.c:214 +msgid "Use predefined quantization table with given index" msgstr "" -#: ../libvips/draw/draw_flood.c:553 ../libvips/draw/draw_flood.c:560 -msgid "DrawFlood start point" +#: libvips/foreign/jpegsave.c:228 +msgid "Restart interval" msgstr "" -#: ../libvips/draw/draw_flood.c:566 -msgid "Test" +#: libvips/foreign/jpegsave.c:229 +msgid "Add restart markers every specified number of mcu" msgstr "" -#: ../libvips/draw/draw_flood.c:567 -msgid "Test pixels in this image" +#: libvips/foreign/jpegsave.c:288 +msgid "save image to jpeg target" msgstr "" -#: ../libvips/draw/draw_flood.c:572 -msgid "Equal" +#: libvips/foreign/jpegsave.c:357 +msgid "save image to jpeg file" msgstr "" -#: ../libvips/draw/draw_flood.c:573 -msgid "DrawFlood while equal to edge" +#: libvips/foreign/jpegsave.c:435 +msgid "save image to jpeg buffer" msgstr "" -#: ../libvips/draw/draw_flood.c:580 -msgid "Left edge of modified area" +#: libvips/foreign/jpegsave.c:511 +msgid "save image to jpeg mime" msgstr "" -#: ../libvips/draw/draw_flood.c:587 -msgid "top edge of modified area" +#: libvips/foreign/jxlload.c:251 libvips/foreign/jxlsave.c:433 +#: libvips/iofuncs/dbuf.c:81 libvips/iofuncs/util.c:684 +msgid "out of memory" msgstr "" -#: ../libvips/draw/draw_flood.c:594 -msgid "width of modified area" +#: libvips/foreign/jxlload.c:576 +msgid "bad buffer size" msgstr "" -#: ../libvips/draw/draw_flood.c:601 -msgid "height of modified area" +#: libvips/foreign/jxlload.c:602 libvips/foreign/webp2vips.c:724 +msgid "not enough frames" msgstr "" -#: ../libvips/draw/draw_rect.c:169 -msgid "paint a rectangle on an image" +#: libvips/foreign/jxlload.c:683 libvips/foreign/radiance.c:704 +msgid "image size out of bounds" msgstr "" -#: ../libvips/foreign/foreign.c:357 -msgid "load and save image files" +#: libvips/foreign/jxlload.c:1119 +msgid "load JPEG-XL image" msgstr "" -#: ../libvips/foreign/foreign.c:520 ../libvips/mosaicing/im_remosaic.c:87 +#: libvips/foreign/jxlsave.c:748 libvips/foreign/webpsave.c:744 #, c-format -msgid "file \"%s\" not found" +msgid "failed to allocate %zu bytes" msgstr "" -#: ../libvips/foreign/foreign.c:529 ../libvips/foreign/foreign.c:1592 -#, c-format -msgid "\"%s\" is not a known file format" +#: libvips/foreign/jxlsave.c:796 +msgid "save image in JPEG-XL format" msgstr "" -#: ../libvips/foreign/foreign.c:605 -msgid "buffer is not in a known format" +#: libvips/foreign/jxlsave.c:810 +msgid "Tier" +msgstr "" + +#: libvips/foreign/jxlsave.c:811 +msgid "Decode speed tier" msgstr "" -#: ../libvips/foreign/foreign.c:773 -msgid "images do not match" +#: libvips/foreign/jxlsave.c:817 libvips/morphology/nearest.c:315 +msgid "Distance" msgstr "" -#: ../libvips/foreign/foreign.c:880 -msgid "" -"VIPS_FOREIGN_PARTIAL and VIPS_FOREIGN_SEQUENTIAL both set -- using SEQUENTIAL" +#: libvips/foreign/jxlsave.c:818 +msgid "Target butteraugli distance" msgstr "" -#: ../libvips/foreign/foreign.c:900 -msgid "" -"ignoring deprecated \"sequential\" mode -- please use \"access\" instead" +#: libvips/foreign/jxlsave.c:825 +msgid "Encoding effort" msgstr "" -#: ../libvips/foreign/foreign.c:979 -msgid "file loaders" +#: libvips/foreign/jxlsave.c:839 +msgid "Quality factor" msgstr "" -#: ../libvips/foreign/foreign.c:990 -msgid "Flags" +#: libvips/foreign/magick2vips.c:305 +#, c-format +msgid "unsupported image type %d" msgstr "" -#: ../libvips/foreign/foreign.c:991 -msgid "Flags for this file" +#: libvips/foreign/magick2vips.c:354 libvips/foreign/magick7load.c:471 +#, c-format +msgid "bad image dimensions %d x %d pixels, %d bands" msgstr "" -#: ../libvips/foreign/foreign.c:997 -msgid "Disc" +#: libvips/foreign/magick2vips.c:384 +#, c-format +msgid "unsupported bit depth %d" msgstr "" -#: ../libvips/foreign/foreign.c:998 -msgid "Open to disc" +#: libvips/foreign/magick2vips.c:791 libvips/foreign/webp2vips.c:638 +msgid "unable to read pixels" msgstr "" -#: ../libvips/foreign/foreign.c:1005 -msgid "Required access pattern for this file" +#: libvips/foreign/magick2vips.c:823 libvips/foreign/magick2vips.c:861 +#, c-format +msgid "unable to read file \"%s\"" msgstr "" -#: ../libvips/foreign/foreign.c:1011 -msgid "Sequential" +#: libvips/foreign/magick2vips.c:870 libvips/foreign/magick2vips.c:949 +msgid "bad image size" msgstr "" -#: ../libvips/foreign/foreign.c:1012 -msgid "Sequential read only" +#: libvips/foreign/magick2vips.c:902 +msgid "unable to read buffer" msgstr "" -#: ../libvips/foreign/foreign.c:1018 -msgid "Fail" +#: libvips/foreign/magick2vips.c:940 +msgid "unable to ping blob" msgstr "" -#: ../libvips/foreign/foreign.c:1019 -msgid "Fail on first warning" +#: libvips/foreign/magick6load.c:113 +msgid "load with ImageMagick" msgstr "" -#: ../libvips/foreign/foreign.c:1499 -msgid "file savers" +#: libvips/foreign/magick6load.c:134 libvips/foreign/magick7load.c:375 +msgid "Density" msgstr "" -#: ../libvips/foreign/foreign.c:1523 -msgid "Image to save" +#: libvips/foreign/magick6load.c:135 libvips/foreign/magick7load.c:376 +msgid "Canvas resolution for rendering vector formats like SVG" msgstr "" -#: ../libvips/foreign/foreign.c:1528 -msgid "Strip" +#: libvips/foreign/magick6load.c:155 libvips/foreign/magick7load.c:396 +msgid "All frames" msgstr "" -#: ../libvips/foreign/foreign.c:1529 -msgid "Strip all metadata from image" +#: libvips/foreign/magick6load.c:156 libvips/foreign/magick7load.c:397 +msgid "Read all frames from an image" msgstr "" -#: ../libvips/foreign/foreign.c:1667 -#, c-format -msgid "\"%s\" is not a known buffer format" +#: libvips/foreign/magick6load.c:231 +msgid "load file with ImageMagick" msgstr "" -#: ../libvips/foreign/ppm.c:116 -msgid "bad int" +#: libvips/foreign/magick6load.c:306 +msgid "load buffer with ImageMagick" msgstr "" -#: ../libvips/foreign/ppm.c:128 -msgid "bad float" +#: libvips/foreign/magick7load.c:353 +msgid "load with ImageMagick7" msgstr "" -#: ../libvips/foreign/ppm.c:179 -msgid "bad magic number" +#: libvips/foreign/magick7load.c:414 +#, c-format +msgid "Magick: %s %s" msgstr "" -#: ../libvips/foreign/ppm.c:230 -msgid "not whitespace before start of binary data" +#: libvips/foreign/magick7load.c:491 +#, c-format +msgid "unsupported bit depth %zd" msgstr "" -#: ../libvips/foreign/ppm.c:621 ../libvips/foreign/ppm.c:638 -#: ../libvips/foreign/ppm.c:672 ../libvips/foreign/ppm.c:686 -msgid "write error" +#: libvips/foreign/magick7load.c:845 +msgid "load file with ImageMagick7" msgstr "" -#: ../libvips/foreign/ppm.c:803 -msgid "float images must be binary -- disabling ascii" +#: libvips/foreign/magick7load.c:926 +msgid "load buffer with ImageMagick7" msgstr "" -#: ../libvips/foreign/ppm.c:813 ../libvips/foreign/vips2tiff.c:1001 -msgid "can only squash 1 band uchar images -- disabling squash" +#: libvips/foreign/magick.c:804 +#, c-format +msgid "libMagick error: %s %s" msgstr "" -#: ../libvips/foreign/csvsave.c:95 -msgid "save image to csv file" +#: libvips/foreign/magick.c:807 +#, c-format +msgid "libMagick error: %s" msgstr "" -#: ../libvips/foreign/csvsave.c:103 ../libvips/foreign/pngload.c:144 -#: ../libvips/foreign/webpload.c:192 ../libvips/foreign/pngsave.c:189 -#: ../libvips/foreign/fitsload.c:123 ../libvips/foreign/matrixsave.c:121 -#: ../libvips/foreign/ppmsave.c:123 ../libvips/foreign/csvload.c:141 -#: ../libvips/foreign/ppmload.c:135 ../libvips/foreign/magickload.c:223 -#: ../libvips/foreign/gifload.c:892 ../libvips/foreign/magick7load.c:803 -#: ../libvips/foreign/fitssave.c:138 ../libvips/foreign/pdfload.c:590 -#: ../libvips/foreign/openslideload.c:187 ../libvips/foreign/rawload.c:116 -#: ../libvips/foreign/tiffsave.c:362 ../libvips/foreign/svgload.c:368 -#: ../libvips/foreign/radsave.c:154 ../libvips/foreign/dzsave.c:2319 -#: ../libvips/foreign/radload.c:138 ../libvips/foreign/openexrload.c:144 -#: ../libvips/foreign/vipssave.c:114 ../libvips/foreign/webpsave.c:214 -#: ../libvips/foreign/rawsave.c:145 ../libvips/foreign/jpegsave.c:268 -#: ../libvips/foreign/matrixload.c:153 ../libvips/foreign/jpegload.c:232 -#: ../libvips/foreign/analyzeload.c:135 ../libvips/foreign/matload.c:133 -#: ../libvips/foreign/vipsload.c:138 ../libvips/foreign/tiffload.c:223 -#: ../libvips/iofuncs/image.c:1200 ../libvips/resample/thumbnail.c:669 -msgid "Filename" +#: libvips/foreign/magick.c:810 +msgid "libMagick error:" msgstr "" -#: ../libvips/foreign/csvsave.c:104 ../libvips/foreign/pngsave.c:190 -#: ../libvips/foreign/matrixsave.c:122 ../libvips/foreign/ppmsave.c:124 -#: ../libvips/foreign/fitssave.c:139 ../libvips/foreign/tiffsave.c:363 -#: ../libvips/foreign/radsave.c:155 ../libvips/foreign/dzsave.c:2320 -#: ../libvips/foreign/vipssave.c:115 ../libvips/foreign/webpsave.c:215 -#: ../libvips/foreign/rawsave.c:146 ../libvips/foreign/jpegsave.c:269 -msgid "Filename to save to" +#: libvips/foreign/matlab.c:121 +#, c-format +msgid "no matrix variables in \"%s\"" msgstr "" -#: ../libvips/foreign/csvsave.c:110 ../libvips/foreign/csvload.c:169 -msgid "Separator" +#: libvips/foreign/matlab.c:203 +#, c-format +msgid "unsupported rank %d\n" msgstr "" -#: ../libvips/foreign/csvsave.c:111 -msgid "Separator characters" +#: libvips/foreign/matlab.c:211 +#, c-format +msgid "unsupported class type %d\n" msgstr "" -#: ../libvips/foreign/webp2vips.c:199 -msgid "bad setting for shrink" +#: libvips/foreign/matlab.c:265 +msgid "Mat_VarReadDataAll failed" msgstr "" -#: ../libvips/foreign/webp2vips.c:247 -msgid "unable to read image metadata" +#: libvips/foreign/matload.c:122 +msgid "load mat from file" msgstr "" -#: ../libvips/foreign/webp2vips.c:290 ../libvips/foreign/webp2vips.c:340 -#: ../libvips/foreign/matlab.c:113 ../libvips/foreign/fits.c:189 -#: ../libvips/iofuncs/vips.c:163 ../libvips/mosaicing/global_balance.c:1192 -#: ../libvips/mosaicing/global_balance.c:1530 +#: libvips/foreign/matrixload.c:128 libvips/foreign/matrixload.c:242 #, c-format -msgid "unable to open \"%s\"" +msgid "bad number \"%s\"" msgstr "" -#: ../libvips/foreign/webp2vips.c:323 ../libvips/foreign/magick2vips.c:723 -msgid "unable to read pixels" +#: libvips/foreign/matrixload.c:137 +msgid "no width / height" msgstr "" -#: ../libvips/foreign/webp2vips.c:360 ../libvips/foreign/webp2vips.c:382 -msgid "unable to open buffer" +#: libvips/foreign/matrixload.c:143 +msgid "width / height not int" msgstr "" -#: ../libvips/foreign/pngload.c:128 -msgid "load png from file" +#: libvips/foreign/matrixload.c:156 +msgid "width / height out of range" msgstr "" -#: ../libvips/foreign/pngload.c:145 ../libvips/foreign/webpload.c:193 -#: ../libvips/foreign/fitsload.c:124 ../libvips/foreign/csvload.c:142 -#: ../libvips/foreign/ppmload.c:136 ../libvips/foreign/magickload.c:224 -#: ../libvips/foreign/gifload.c:893 ../libvips/foreign/magick7load.c:804 -#: ../libvips/foreign/pdfload.c:591 ../libvips/foreign/openslideload.c:188 -#: ../libvips/foreign/rawload.c:117 ../libvips/foreign/svgload.c:369 -#: ../libvips/foreign/radload.c:139 ../libvips/foreign/openexrload.c:145 -#: ../libvips/foreign/matrixload.c:154 ../libvips/foreign/jpegload.c:233 -#: ../libvips/foreign/analyzeload.c:136 ../libvips/foreign/matload.c:134 -#: ../libvips/foreign/vipsload.c:139 ../libvips/foreign/tiffload.c:224 -msgid "Filename to load from" +#: libvips/foreign/matrixload.c:160 +msgid "zero scale" msgstr "" -#: ../libvips/foreign/pngload.c:222 -msgid "load png from buffer" +#: libvips/foreign/matrixload.c:251 +#, c-format +msgid "line %d too short" msgstr "" -#: ../libvips/foreign/pngload.c:230 ../libvips/foreign/webpload.c:268 -#: ../libvips/foreign/pngsave.c:255 ../libvips/foreign/magickload.c:307 -#: ../libvips/foreign/gifload.c:977 ../libvips/foreign/magick7load.c:900 -#: ../libvips/foreign/pdfload.c:652 ../libvips/foreign/tiffsave.c:437 -#: ../libvips/foreign/svgload.c:531 ../libvips/foreign/radsave.c:217 -#: ../libvips/foreign/dzsave.c:2406 ../libvips/foreign/webpsave.c:285 -#: ../libvips/foreign/jpegsave.c:340 ../libvips/foreign/jpegload.c:311 -#: ../libvips/foreign/tiffload.c:314 ../libvips/resample/thumbnail.c:836 -msgid "Buffer" +#: libvips/foreign/matrixload.c:273 +msgid "load matrix" msgstr "" -#: ../libvips/foreign/pngload.c:231 ../libvips/foreign/webpload.c:269 -#: ../libvips/foreign/magickload.c:308 ../libvips/foreign/gifload.c:978 -#: ../libvips/foreign/magick7load.c:901 ../libvips/foreign/pdfload.c:653 -#: ../libvips/foreign/svgload.c:532 ../libvips/foreign/jpegload.c:312 -#: ../libvips/foreign/tiffload.c:315 ../libvips/resample/thumbnail.c:837 -msgid "Buffer to load from" +#: libvips/foreign/matrixsave.c:175 +msgid "save image to matrix" msgstr "" -#: ../libvips/foreign/matlab.c:121 -#, c-format -msgid "no matrix variables in \"%s\"" +#: libvips/foreign/matrixsave.c:323 +msgid "print matrix" msgstr "" -#: ../libvips/foreign/matlab.c:203 -#, c-format -msgid "unsupported rank %d\n" +#: libvips/foreign/niftiload.c:406 +msgid "invalid dimension" msgstr "" -#: ../libvips/foreign/matlab.c:211 -#, c-format -msgid "unsupported class type %d\n" +#: libvips/foreign/niftiload.c:417 +msgid "invalid resolution" msgstr "" -#: ../libvips/foreign/matlab.c:260 -msgid "Mat_VarReadDataAll failed" +#: libvips/foreign/niftiload.c:431 libvips/foreign/niftiload.c:435 +#: libvips/foreign/niftisave.c:309 +msgid "dimension overflow" msgstr "" -#: ../libvips/foreign/webpload.c:94 -msgid "load webp" +#: libvips/foreign/niftiload.c:536 +msgid "unable to read NIFTI header" msgstr "" -#: ../libvips/foreign/webpload.c:100 ../libvips/foreign/jpegload.c:137 -msgid "Shrink" +#: libvips/foreign/niftiload.c:564 +msgid "unable to load NIFTI file" msgstr "" -#: ../libvips/foreign/webpload.c:101 ../libvips/foreign/jpegload.c:138 -msgid "Shrink factor on load" +#: libvips/foreign/niftiload.c:594 +msgid "load a NIFTI image" msgstr "" -#: ../libvips/foreign/webpload.c:181 -msgid "load webp from file" +#: libvips/foreign/niftiload.c:705 +msgid "load NIfTI volume" msgstr "" -#: ../libvips/foreign/webpload.c:257 -msgid "load webp from buffer" +#: libvips/foreign/niftiload.c:783 +msgid "load NIfTI volumes" msgstr "" -#: ../libvips/foreign/pngsave.c:100 -msgid "save png" -msgstr "" +#: libvips/foreign/niftisave.c:115 libvips/foreign/niftisave.c:322 +#, fuzzy +msgid "unsupported libvips image type" +msgstr "unsupported colour type" -#: ../libvips/foreign/pngsave.c:108 ../libvips/foreign/tiffsave.c:181 -#: ../libvips/foreign/dzsave.c:2200 -msgid "Compression" +#: libvips/foreign/niftisave.c:122 +msgid "8-bit colour images only" msgstr "" -#: ../libvips/foreign/pngsave.c:109 -msgid "Compression factor" +#: libvips/foreign/niftisave.c:132 +msgid "3 or 4 band colour images only" msgstr "" -#: ../libvips/foreign/pngsave.c:115 ../libvips/foreign/jpegsave.c:170 -msgid "Interlace" +#: libvips/foreign/niftisave.c:251 +msgid "bad nifti-ext- field name" msgstr "" -#: ../libvips/foreign/pngsave.c:116 -msgid "Interlace image" +#: libvips/foreign/niftisave.c:260 +msgid "unable to attach nifti ext" msgstr "" -#: ../libvips/foreign/pngsave.c:122 ../libvips/foreign/jpegsave.c:156 -msgid "Profile" +#: libvips/foreign/niftisave.c:315 libvips/foreign/nsgifload.c:644 +#: libvips/foreign/webp2vips.c:550 +msgid "bad image dimensions" msgstr "" -#: ../libvips/foreign/pngsave.c:123 ../libvips/foreign/tiffsave.c:205 -#: ../libvips/foreign/jpegsave.c:157 -msgid "ICC profile to embed" +#: libvips/foreign/niftisave.c:375 +msgid "unable to set nifti filename" msgstr "" -#: ../libvips/foreign/pngsave.c:129 -msgid "Filter" +#: libvips/foreign/niftisave.c:427 +msgid "save image to nifti file" msgstr "" -#: ../libvips/foreign/pngsave.c:130 -msgid "libpng row filter flag(s)" +#: libvips/foreign/nsgifload.c:420 +msgid "no frames in GIF" msgstr "" -#: ../libvips/foreign/pngsave.c:185 -msgid "save image to png file" +#: libvips/foreign/nsgifload.c:463 +msgid "bad frame" msgstr "" -#: ../libvips/foreign/pngsave.c:251 -msgid "save image to png buffer" +#: libvips/foreign/nsgifload.c:607 libvips/foreign/nsgifload.c:757 +#: libvips/foreign/nsgifload.c:837 +msgid "load GIF with libnsgif" msgstr "" -#: ../libvips/foreign/pngsave.c:256 ../libvips/foreign/tiffsave.c:438 -#: ../libvips/foreign/radsave.c:218 ../libvips/foreign/dzsave.c:2407 -#: ../libvips/foreign/webpsave.c:286 ../libvips/foreign/jpegsave.c:341 -msgid "Buffer to save to" +#: libvips/foreign/nsgifload.c:901 +msgid "load gif from source" msgstr "" -#: ../libvips/foreign/tiff2vips.c:333 ../libvips/foreign/tiff2vips.c:351 +#: libvips/foreign/openexr2vips.c:123 #, c-format -msgid "required field %d missing" +msgid "EXR error: %s" msgstr "" -#: ../libvips/foreign/tiff2vips.c:393 -msgid "unknown resolution unit" +#: libvips/foreign/openexrload.c:129 +msgid "load an OpenEXR image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:398 -#, c-format -msgid "" -"no resolution information for TIFF image \"%s\" -- defaulting to 1 pixel per " -"mm" +#: libvips/foreign/openslideload.c:207 +msgid "invalid associated image name" msgstr "" -#: ../libvips/foreign/tiff2vips.c:465 -msgid "read error" +#: libvips/foreign/openslideload.c:252 +msgid "specify only one of level and associated image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:482 -#, c-format -msgid "TIFF does not contain page %d" +#: libvips/foreign/openslideload.c:259 +msgid "specify only one of attach_assicated and associated image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:516 +#: libvips/foreign/openslideload.c:376 libvips/foreign/openslideload.c:491 +#: libvips/foreign/openslideload.c:652 #, c-format -msgid "not %d bands" +msgid "opening slide: %s" msgstr "" -#: ../libvips/foreign/tiff2vips.c:530 +#: libvips/foreign/openslideload.c:398 #, c-format -msgid "not at least %d samples per pixel" +msgid "reading associated image: %s" msgstr "" -#: ../libvips/foreign/tiff2vips.c:544 -#, c-format -msgid "not photometric interpretation %d" +#: libvips/foreign/openslideload.c:485 +msgid "unsupported slide format" msgstr "" -#: ../libvips/foreign/tiff2vips.c:557 -#, c-format -msgid "not %d bits per sample" +#: libvips/foreign/openslideload.c:498 +msgid "invalid slide level" msgstr "" -#: ../libvips/foreign/tiff2vips.c:573 +#: libvips/foreign/openslideload.c:590 #, c-format -msgid "%d bits per sample palette image not supported" +msgid "getting dimensions: %s" msgstr "" -#: ../libvips/foreign/tiff2vips.c:630 -msgid "unsupported tiff image type\n" +#: libvips/foreign/openslideload.c:597 +msgid "image dimensions overflow int" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1038 -msgid "bad colormap" -msgstr "bad colourmap" - -#: ../libvips/foreign/tiff2vips.c:1059 -msgid "assuming 8-bit palette" +#: libvips/foreign/openslideload.c:753 +#, c-format +msgid "reading region: %s" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1594 -msgid "tiled separate planes not supported" +#: libvips/foreign/openslideload.c:1017 +msgid "load OpenSlide base class" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1616 ../libvips/foreign/tiff2vips.c:1883 -msgid "unsupported tiff image type" +#: libvips/foreign/openslideload.c:1046 libvips/foreign/tiffsave.c:364 +msgid "Level" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1981 -#, c-format -msgid "bad page number %d" +#: libvips/foreign/openslideload.c:1047 +msgid "Load this level from the file" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1991 -#, c-format -msgid "bad number of pages %d" +#: libvips/foreign/openslideload.c:1053 +msgid "Autocrop" msgstr "" -#: ../libvips/foreign/tiff2vips.c:2022 -msgid "width/height out of range" +#: libvips/foreign/openslideload.c:1054 +msgid "Crop to image bounds" msgstr "" -#: ../libvips/foreign/tiff2vips.c:2031 -msgid "samples out of range" +#: libvips/foreign/openslideload.c:1060 +msgid "Associated" msgstr "" -#: ../libvips/foreign/tiff2vips.c:2160 -#, c-format -msgid "page %d differs from page %d" +#: libvips/foreign/openslideload.c:1061 +msgid "Load this associated image" msgstr "" -#: ../libvips/foreign/fitsload.c:110 -msgid "load a FITS image" +#: libvips/foreign/openslideload.c:1067 +msgid "Attach associated" msgstr "" -#: ../libvips/foreign/matrixsave.c:112 -msgid "save image to matrix file" +#: libvips/foreign/openslideload.c:1068 +msgid "Attach all associated images" msgstr "" -#: ../libvips/foreign/matrixsave.c:192 -msgid "print matrix" +#: libvips/foreign/openslideload.c:1074 +msgid "RGB" msgstr "" -#: ../libvips/foreign/vips2webp.c:128 -msgid "output webp image too large" +#: libvips/foreign/openslideload.c:1075 +msgid "Output RGB (not RGBA)" msgstr "" -#: ../libvips/foreign/vips2webp.c:134 ../libvips/iofuncs/util.c:738 -msgid "out of memory" +#: libvips/foreign/openslideload.c:1144 +msgid "load file with OpenSlide" msgstr "" -#: ../libvips/foreign/vips2webp.c:242 ../libvips/foreign/vips2webp.c:252 -msgid "config version error" +#: libvips/foreign/openslideload.c:1223 +msgid "load source with OpenSlide" msgstr "" -#: ../libvips/foreign/vips2webp.c:266 -msgid "lossless unsupported" +#: libvips/foreign/pdfiumload.c:196 +msgid "unknown error" msgstr "" -#: ../libvips/foreign/vips2webp.c:268 -msgid "alpha_q unsupported" +#: libvips/foreign/pdfiumload.c:291 +#, c-format +msgid "%s: too large for pdfium" msgstr "" -#: ../libvips/foreign/vips2webp.c:278 -msgid "near_lossless unsupported" +#: libvips/foreign/pdfiumload.c:307 +#, c-format +msgid "%s: unable to load" msgstr "" -#: ../libvips/foreign/vips2webp.c:280 -msgid "smart_subsample unsupported" +#: libvips/foreign/pdfiumload.c:318 +#, c-format +msgid "%s: unable to initialize form fill environment" msgstr "" -#: ../libvips/foreign/vips2webp.c:284 -msgid "invalid configuration" +#: libvips/foreign/pdfiumload.c:366 libvips/foreign/popplerload.c:239 +#, c-format +msgid "unable to load page %d" msgstr "" -#: ../libvips/foreign/vips2webp.c:302 -msgid "picture memory error" +#: libvips/foreign/pdfiumload.c:478 libvips/foreign/popplerload.c:333 +msgid "pages out of range" msgstr "" -#: ../libvips/foreign/vips2webp.c:308 -msgid "unable to encode" +#: libvips/foreign/pdfiumload.c:513 +msgid "page size out of range" msgstr "" -#: ../libvips/foreign/vips2webp.c:526 ../libvips/foreign/vips2webp.c:579 -msgid "picture version error" +#: libvips/foreign/pdfiumload.c:685 +msgid "load PDF with PDFium" msgstr "" -#: ../libvips/foreign/tiff.c:123 -#, c-format -msgid "unable to open \"%s\" for output" +#: libvips/foreign/pdfiumload.c:717 libvips/foreign/popplerload.c:567 +#: libvips/foreign/webpload.c:193 +msgid "Factor to scale by" msgstr "" -#: ../libvips/foreign/tiff.c:169 -#, c-format -msgid "unable to open \"%s\" for input" +#: libvips/foreign/pdfiumload.c:724 libvips/foreign/popplerload.c:574 +msgid "Background colour" msgstr "" -#: ../libvips/foreign/tiff.c:195 -msgid "read beyond end of buffer" +#: libvips/foreign/pdfiumload.c:730 libvips/foreign/popplerload.c:580 +msgid "Password" msgstr "" -#: ../libvips/foreign/tiff.c:291 -msgid "unable to open memory buffer for input" +#: libvips/foreign/pdfiumload.c:731 libvips/foreign/popplerload.c:581 +msgid "Password to decrypt with" msgstr "" -#: ../libvips/foreign/tiff.c:348 -msgid "Out of memory." +#: libvips/foreign/pdfiumload.c:803 libvips/foreign/popplerload.c:680 +msgid "load PDF from file" msgstr "" -#: ../libvips/foreign/tiff.c:450 -msgid "unable to open memory buffer for output" +#: libvips/foreign/pdfiumload.c:866 libvips/foreign/popplerload.c:743 +msgid "load PDF from buffer" msgstr "" -#: ../libvips/foreign/ppmsave.c:114 -msgid "save image to ppm file" +#: libvips/foreign/pdfiumload.c:924 libvips/foreign/popplerload.c:801 +msgid "load PDF from source" msgstr "" -#: ../libvips/foreign/ppmsave.c:130 -msgid "ASCII" +#: libvips/foreign/pngload.c:157 libvips/foreign/spngload.c:664 +msgid "load png base class" msgstr "" -#: ../libvips/foreign/ppmsave.c:131 -msgid "save as ascii" +#: libvips/foreign/pngload.c:234 libvips/foreign/spngload.c:749 +msgid "load png from source" msgstr "" -#: ../libvips/foreign/ppmsave.c:137 ../libvips/foreign/tiffsave.c:239 -msgid "Squash" +#: libvips/foreign/pngload.c:310 libvips/foreign/spngload.c:827 +msgid "load png from file" msgstr "" -#: ../libvips/foreign/ppmsave.c:138 -msgid "save as one bit" +#: libvips/foreign/pngload.c:388 libvips/foreign/spngload.c:905 +msgid "load png from buffer" msgstr "" -#. Only a warning, since (for example) exported spreadsheets -#. * will often have text or date fields. -#. -#: ../libvips/foreign/csv.c:198 -#, c-format -msgid "error parsing number, line %d, column %d" +#: libvips/foreign/pngsave.c:202 +msgid "save png" msgstr "" -#: ../libvips/foreign/csv.c:256 -msgid "end of file while skipping start" +#: libvips/foreign/pngsave.c:212 libvips/foreign/spngsave.c:690 +msgid "Compression factor" msgstr "" -#: ../libvips/foreign/csv.c:265 ../libvips/iofuncs/util.c:1050 -#: ../libvips/iofuncs/util.c:1056 -msgid "unable to seek" +#: libvips/foreign/pngsave.c:219 libvips/foreign/spngsave.c:697 +msgid "Interlace image" msgstr "" -#: ../libvips/foreign/csv.c:276 -msgid "empty line" +#: libvips/foreign/pngsave.c:225 libvips/foreign/spngsave.c:703 +msgid "Filter" msgstr "" -#: ../libvips/foreign/csv.c:316 -#, c-format -msgid "unexpected EOF, line %d col %d" +#: libvips/foreign/pngsave.c:226 +msgid "libpng row filter flag(s)" msgstr "" -#: ../libvips/foreign/csv.c:322 -#, c-format -msgid "unexpected EOL, line %d col %d" +#: libvips/foreign/pngsave.c:233 libvips/foreign/spngsave.c:711 +msgid "Palette" msgstr "" -#: ../libvips/foreign/csv.c:554 -msgid "no width / height" +#: libvips/foreign/pngsave.c:234 libvips/foreign/spngsave.c:712 +msgid "Quantise to 8bpp palette" msgstr "" -#: ../libvips/foreign/csv.c:560 -msgid "width / height not int" +#: libvips/foreign/pngsave.c:240 libvips/foreign/spngsave.c:718 +#: libvips/foreign/vips2magick.c:489 +msgid "Quality" msgstr "" -#: ../libvips/foreign/csv.c:570 -msgid "width / height out of range" +#: libvips/foreign/pngsave.c:241 libvips/foreign/spngsave.c:719 +msgid "Quantisation quality" msgstr "" -#: ../libvips/foreign/csv.c:574 -msgid "extra chars in header" +#: libvips/foreign/pngsave.c:255 libvips/foreign/spngsave.c:733 +msgid "Write as a 1, 2, 4, 8 or 16 bit image" msgstr "" -#: ../libvips/foreign/csv.c:578 -msgid "zero scale" +#: libvips/foreign/pngsave.c:262 libvips/foreign/spngsave.c:740 +msgid "Quantisation CPU effort" msgstr "" -#: ../libvips/foreign/csv.c:626 -msgid "line too short" +#: libvips/foreign/pngsave.c:268 libvips/foreign/spngsave.c:746 +msgid "Colours" msgstr "" -#: ../libvips/foreign/csv.c:670 -#, c-format -msgid "line %d too short" +#: libvips/foreign/pngsave.c:269 libvips/foreign/spngsave.c:747 +msgid "Max number of palette colours" msgstr "" -#: ../libvips/foreign/csvload.c:126 -msgid "load csv from file" +#: libvips/foreign/pngsave.c:322 libvips/foreign/spngsave.c:801 +msgid "save image to target as PNG" msgstr "" -#: ../libvips/foreign/csvload.c:148 -msgid "Skip" +#: libvips/foreign/pngsave.c:374 +msgid "save image to png file" msgstr "" -#: ../libvips/foreign/csvload.c:149 -msgid "Skip this many lines at the start of the file" +#: libvips/foreign/pngsave.c:433 +msgid "save image to png buffer" msgstr "" -#: ../libvips/foreign/csvload.c:155 -msgid "Lines" +#: libvips/foreign/popplerload.c:531 +msgid "load PDF with libpoppler" msgstr "" -#: ../libvips/foreign/csvload.c:156 -msgid "Read this many lines from the file" +#: libvips/foreign/ppmload.c:264 +msgid "bad magic number" msgstr "" -#: ../libvips/foreign/csvload.c:162 -msgid "Whitespace" +#: libvips/foreign/ppmload.c:521 +msgid "file truncated" msgstr "" -#: ../libvips/foreign/csvload.c:163 -msgid "Set of whitespace characters" +#: libvips/foreign/ppmload.c:746 +msgid "load ppm base class" msgstr "" -#: ../libvips/foreign/csvload.c:170 -msgid "Set of separator characters" +#: libvips/foreign/ppmload.c:823 +msgid "load ppm from file" msgstr "" -#: ../libvips/foreign/vipspng.c:307 -msgid "unsupported color type" -msgstr "unsupported colour type" +#: libvips/foreign/ppmsave.c:321 +msgid "too few bands for format" +msgstr "" -#: ../libvips/foreign/vipspng.c:417 -msgid "unable to read PNG header" +#: libvips/foreign/ppmsave.c:499 +msgid "save to ppm" msgstr "" -#: ../libvips/foreign/vipspng.c:504 ../libvips/foreign/jpeg2vips.c:560 -#, c-format -msgid "out of order read at line %d" +#: libvips/foreign/ppmsave.c:507 libvips/foreign/vips2magick.c:483 +msgid "Format to save in" msgstr "" -#: ../libvips/foreign/vipspng.c:878 -msgid "compress should be in [0,9]" +#: libvips/foreign/ppmsave.c:514 +msgid "ASCII" msgstr "" -#: ../libvips/foreign/vipspng.c:900 -#, c-format -msgid "can't save %d band image as png" +#: libvips/foreign/ppmsave.c:515 +msgid "Save as ascii" msgstr "" -#: ../libvips/foreign/vipspng.c:1010 -#, c-format -msgid "unable to write \"%s\"" +#: libvips/foreign/ppmsave.c:522 +msgid "Set to 1 to write as a 1 bit image" msgstr "" -#: ../libvips/foreign/vipspng.c:1078 -msgid "unable to write to buffer" +#: libvips/foreign/ppmsave.c:528 libvips/foreign/tiffsave.c:406 +msgid "Squash" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:148 -#, c-format -msgid "%s" +#: libvips/foreign/ppmsave.c:529 +msgid "Save as one bit" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:254 -#, c-format -msgid "field \"%s\" is too large for a single JPEG marker, ignoring" +#: libvips/foreign/ppmsave.c:586 +msgid "save image to ppm file" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:496 -msgid "trellis_quant unsupported" +#: libvips/foreign/ppmsave.c:675 +msgid "save image in pbm format" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:509 -msgid "overshoot_deringing unsupported" +#: libvips/foreign/ppmsave.c:707 +msgid "save image in pgm format" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:523 ../libvips/foreign/vips2jpeg.c:550 -msgid "ignoring optimize_scans" +#: libvips/foreign/ppmsave.c:739 +msgid "save image in pfm format" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:527 -msgid "ignoring optimize_scans for baseline" +#: libvips/foreign/ppmsave.c:771 +msgid "save image in pnm format" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:539 -msgid "setting quant_table unsupported" +#: libvips/foreign/quantise.c:469 +msgid "libvips not built with quantisation support" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:546 -msgid "ignoring trellis_quant" +#: libvips/foreign/radiance.c:438 +msgid "scanline length mismatch" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:548 -msgid "ignoring overshoot_deringing" +#: libvips/foreign/radiance.c:455 +msgid "overrun" msgstr "" -#: ../libvips/foreign/vips2jpeg.c:552 -msgid "ignoring quant_table" +#: libvips/foreign/radiance.c:687 +msgid "error reading radiance header" msgstr "" -#: ../libvips/foreign/ppmload.c:119 -msgid "load ppm from file" +#: libvips/foreign/radiance.c:774 +#, c-format +msgid "read error line %d" msgstr "" -#: ../libvips/foreign/magickload.c:105 -msgid "load with ImageMagick" +#: libvips/foreign/radload.c:125 +msgid "load rad base class" msgstr "" -#: ../libvips/foreign/magickload.c:117 ../libvips/foreign/magick7load.c:379 -msgid "all_frames" +#: libvips/foreign/radload.c:197 +msgid "load rad from source" msgstr "" -#: ../libvips/foreign/magickload.c:118 ../libvips/foreign/magick7load.c:380 -msgid "Read all frames from an image" +#: libvips/foreign/radload.c:273 +msgid "load a Radiance image from a file" msgstr "" -#: ../libvips/foreign/magickload.c:124 ../libvips/foreign/magick7load.c:386 -msgid "Density" +#: libvips/foreign/radload.c:350 +msgid "load rad from buffer" msgstr "" -#: ../libvips/foreign/magickload.c:125 ../libvips/foreign/magick7load.c:387 -msgid "Canvas resolution for rendering vector formats like SVG" +#: libvips/foreign/radsave.c:92 +msgid "save Radiance" msgstr "" -#: ../libvips/foreign/magickload.c:131 ../libvips/foreign/gifload.c:816 -#: ../libvips/foreign/magick7load.c:393 ../libvips/foreign/pdfload.c:468 -#: ../libvips/foreign/tiffload.c:99 -msgid "Page" +#: libvips/foreign/radsave.c:150 +msgid "save image to Radiance file" msgstr "" -#: ../libvips/foreign/magickload.c:132 ../libvips/foreign/gifload.c:817 -#: ../libvips/foreign/magick7load.c:394 ../libvips/foreign/pdfload.c:469 -msgid "Load this page from the file" +#: libvips/foreign/radsave.c:203 +msgid "save image to Radiance target" msgstr "" -#: ../libvips/foreign/magickload.c:139 ../libvips/foreign/gifload.c:824 -#: ../libvips/foreign/magick7load.c:401 ../libvips/foreign/pdfload.c:476 -#: ../libvips/foreign/tiffload.c:107 -msgid "Load this many pages" +#: libvips/foreign/radsave.c:269 +msgid "save image to Radiance buffer" msgstr "" -#: ../libvips/foreign/magickload.c:216 -msgid "load file with ImageMagick" +#: libvips/foreign/rawload.c:131 +msgid "load raw data from a file" msgstr "" -#: ../libvips/foreign/magickload.c:300 -msgid "load buffer with ImageMagick" +#: libvips/foreign/rawload.c:167 libvips/iofuncs/image.c:1200 +msgid "Size of header" msgstr "" -#: ../libvips/foreign/openexr2vips.c:121 -#, c-format -msgid "EXR error: %s" +#: libvips/foreign/rawload.c:168 libvips/iofuncs/image.c:1201 +msgid "Offset in bytes from start of file" msgstr "" -#: ../libvips/foreign/gifload.c:145 -msgid "Failed to open given file" +#: libvips/foreign/rawsave.c:138 +msgid "save image to raw" msgstr "" -#: ../libvips/foreign/gifload.c:148 -msgid "Failed to read from given file" +#: libvips/foreign/rawsave.c:190 +msgid "save image to raw file" msgstr "" -#: ../libvips/foreign/gifload.c:151 -msgid "Data is not a GIF file" +#: libvips/foreign/rawsave.c:246 +msgid "write raw image to target" msgstr "" -#: ../libvips/foreign/gifload.c:154 -msgid "No screen descriptor detected" +#: libvips/foreign/rawsave.c:308 +msgid "write raw image to buffer" msgstr "" -#: ../libvips/foreign/gifload.c:157 -msgid "No image descriptor detected" +#: libvips/foreign/spngload.c:252 libvips/foreign/vipspng.c:582 +#, c-format +msgid "%d text chunks, only %d text chunks will be loaded" msgstr "" -#: ../libvips/foreign/gifload.c:160 -msgid "Neither global nor local color map" -msgstr "Neither global nor local colour map" +#: libvips/foreign/spngload.c:403 +#, fuzzy +msgid "unknown color type" +msgstr "unsupported colour type" -#: ../libvips/foreign/gifload.c:163 -msgid "Wrong record type detected" +#: libvips/foreign/spngload.c:562 +msgid "libspng read error" msgstr "" -#: ../libvips/foreign/gifload.c:166 -msgid "Number of pixels bigger than width * height" +#: libvips/foreign/spngsave.c:164 libvips/foreign/vipspng.c:1013 +msgid "bad png comment key" msgstr "" -#: ../libvips/foreign/gifload.c:169 -msgid "Failed to allocate required memory" +#: libvips/foreign/spngsave.c:680 +msgid "save spng" msgstr "" -#: ../libvips/foreign/gifload.c:172 -msgid "Failed to close given file" +#: libvips/foreign/spngsave.c:704 +msgid "libspng row filter flag(s)" msgstr "" -#: ../libvips/foreign/gifload.c:175 -msgid "Given file was not opened for read" +#: libvips/foreign/spngsave.c:854 +msgid "save image to file as PNG" msgstr "" -#: ../libvips/foreign/gifload.c:178 -msgid "Image is defective, decoding aborted" +#: libvips/foreign/spngsave.c:914 +msgid "save image to buffer as PNG" msgstr "" -#: ../libvips/foreign/gifload.c:181 -msgid "Image EOF detected, before image complete" +#: libvips/foreign/svgload.c:626 libvips/foreign/svgload.c:644 +msgid "SVG rendering failed" msgstr "" -#: ../libvips/foreign/gifload.c:184 -msgid "Unknown error" +#: libvips/foreign/svgload.c:700 +msgid "load SVG with rsvg" msgstr "" -#: ../libvips/foreign/gifload.c:371 -msgid "pixel value out of range" +#: libvips/foreign/svgload.c:718 +msgid "Render at this DPI" msgstr "" -#: ../libvips/foreign/gifload.c:411 -msgid "frame is outside image area" +#: libvips/foreign/svgload.c:725 +msgid "Scale output by this factor" msgstr "" -#: ../libvips/foreign/gifload.c:662 ../libvips/foreign/gifload.c:711 -msgid "too few frames in GIF file" +#: libvips/foreign/svgload.c:733 +msgid "Allow SVG of any size" msgstr "" -#: ../libvips/foreign/gifload.c:809 ../libvips/foreign/gifload.c:884 -#: ../libvips/foreign/gifload.c:971 -msgid "load GIF with giflib" +#: libvips/foreign/svgload.c:827 +msgid "load svg from source" msgstr "" -#: ../libvips/foreign/magick7load.c:366 -msgid "load with ImageMagick7" +#: libvips/foreign/tiff2vips.c:480 libvips/foreign/tiff2vips.c:498 +#, c-format +msgid "required field %d missing" msgstr "" -#: ../libvips/foreign/magick7load.c:419 -#, c-format -msgid "Magick: %s %s" +#: libvips/foreign/tiff2vips.c:540 +msgid "unknown resolution unit" msgstr "" -#: ../libvips/foreign/magick7load.c:474 +#: libvips/foreign/tiff2vips.c:680 #, c-format -msgid "unsupported bit depth %zd" +msgid "bad page number %d" msgstr "" -#: ../libvips/foreign/magick7load.c:506 ../libvips/foreign/magick2vips.c:387 +#: libvips/foreign/tiff2vips.c:690 #, c-format -msgid "unsupported colorspace %d" -msgstr "unsupported colourspace %d" - -#: ../libvips/foreign/magick7load.c:797 -msgid "load file with ImageMagick7" +msgid "bad number of pages %d" msgstr "" -#: ../libvips/foreign/magick7load.c:894 -msgid "load buffer with ImageMagick7" +#: libvips/foreign/tiff2vips.c:718 libvips/foreign/tiff2vips.c:760 +#: libvips/iofuncs/source.c:812 +msgid "read error" msgstr "" -#: ../libvips/foreign/openslide2vips.c:195 -msgid "invalid associated image name" +#: libvips/foreign/tiff2vips.c:802 +#, c-format +msgid "TIFF does not contain page %d" msgstr "" -#: ../libvips/foreign/openslide2vips.c:239 -msgid "specify only one of level or associated image" +#: libvips/foreign/tiff2vips.c:812 +msgid "no SUBIFD tag" msgstr "" -#: ../libvips/foreign/openslide2vips.c:275 -msgid "unsupported slide format" +#: libvips/foreign/tiff2vips.c:818 +#, c-format +msgid "subifd %d out of range, only 0-%d available" msgstr "" -#: ../libvips/foreign/openslide2vips.c:282 -#, c-format -msgid "opening slide: %s" +#: libvips/foreign/tiff2vips.c:826 +msgid "subdirectory unreadable" msgstr "" -#: ../libvips/foreign/openslide2vips.c:289 -msgid "invalid slide level" +#: libvips/foreign/tiff2vips.c:867 +#, c-format +msgid "not %d bands" msgstr "" -#: ../libvips/foreign/openslide2vips.c:371 +#: libvips/foreign/tiff2vips.c:880 #, c-format -msgid "getting dimensions: %s" +msgid "not at least %d samples per pixel" msgstr "" -#: ../libvips/foreign/openslide2vips.c:378 -msgid "image dimensions overflow int" +#: libvips/foreign/tiff2vips.c:895 +msgid "samples_per_pixel not a whole number of bytes" msgstr "" -#: ../libvips/foreign/openslide2vips.c:505 +#: libvips/foreign/tiff2vips.c:908 #, c-format -msgid "reading region: %s" +msgid "not photometric interpretation %d" msgstr "" -#: ../libvips/foreign/openslide2vips.c:587 +#: libvips/foreign/tiff2vips.c:920 #, c-format -msgid "reading associated image: %s" +msgid "not %d bits per sample" msgstr "" -#: ../libvips/foreign/exif.c:158 -msgid "unable to init exif" +#: libvips/foreign/tiff2vips.c:936 +#, c-format +msgid "%d bits per sample palette image not supported" msgstr "" -#: ../libvips/foreign/exif.c:413 ../libvips/foreign/exif.c:788 -msgid "unknown EXIF resolution unit" +#: libvips/foreign/tiff2vips.c:995 +msgid "unsupported tiff image type\n" msgstr "" -#: ../libvips/foreign/exif.c:918 ../libvips/foreign/exif.c:928 -#: ../libvips/foreign/exif.c:933 +#: libvips/foreign/tiff2vips.c:1603 +msgid "bad colormap" +msgstr "bad colourmap" + +#: libvips/foreign/tiff2vips.c:2330 #, c-format -msgid "bad exif meta \"%s\"" +msgid "decompress error tile %d x %d" msgstr "" -#: ../libvips/foreign/exif.c:1097 -msgid "error saving EXIF" +#: libvips/foreign/tiff2vips.c:2608 +msgid "tiled separate planes not supported" msgstr "" -#: ../libvips/foreign/fitssave.c:129 -msgid "save image to fits file" +#: libvips/foreign/tiff2vips.c:2627 libvips/foreign/tiff2vips.c:2910 +#: libvips/foreign/tiff2vips.c:3034 +msgid "unsupported tiff image type" msgstr "" -#: ../libvips/foreign/pdfload.c:189 +#: libvips/foreign/tiff2vips.c:2761 #, c-format -msgid "unable to load page %d" -msgstr "" - -#: ../libvips/foreign/pdfload.c:281 -msgid "pages out of range" +msgid "out of order read -- at line %d, but line %d requested" msgstr "" -#: ../libvips/foreign/pdfload.c:459 -msgid "load PDF with libpoppler" +#: libvips/foreign/tiff2vips.c:3070 +msgid "subsampled images not supported" msgstr "" -#: ../libvips/foreign/pdfload.c:483 ../libvips/foreign/svgload.c:284 -msgid "Render at this DPI" +#: libvips/foreign/tiff2vips.c:3082 +msgid "not SGI-compressed LOGLUV" msgstr "" -#: ../libvips/foreign/pdfload.c:490 ../libvips/foreign/svgload.c:291 -msgid "Scale output by this factor" +#: libvips/foreign/tiff2vips.c:3099 +msgid "width/height out of range" msgstr "" -#: ../libvips/foreign/magick2vips.c:293 -#, c-format -msgid "unsupported image type %d" +#: libvips/foreign/tiff2vips.c:3108 +msgid "samples out of range" msgstr "" -#: ../libvips/foreign/magick2vips.c:355 -#, c-format -msgid "unsupported bit depth %d" +#: libvips/foreign/tiff2vips.c:3194 libvips/foreign/tiff2vips.c:3222 +msgid "tile size out of range" msgstr "" -#: ../libvips/foreign/magick2vips.c:753 +#: libvips/foreign/tiff2vips.c:3414 #, c-format -msgid "" -"unable to read file \"%s\"\n" -"libMagick error: %s %s" +msgid "page %d differs from page %d" msgstr "" -#: ../libvips/foreign/magick2vips.c:792 -#, c-format -msgid "" -"unable to ping file \"%s\"\n" -"libMagick error: %s %s" +#: libvips/foreign/tiff.c:207 libvips/foreign/tiff.c:222 +msgid "unable to open source for input" msgstr "" -#: ../libvips/foreign/magick2vips.c:804 ../libvips/foreign/magick2vips.c:880 -msgid "bad image size" +#: libvips/foreign/tiff.c:330 libvips/foreign/tiff.c:345 +msgid "unable to open target for output" msgstr "" -#: ../libvips/foreign/magick2vips.c:835 -#, c-format -msgid "" -"unable to read buffer\n" -"libMagick error: %s %s" +#: libvips/foreign/tiffload.c:183 +msgid "load tiff" msgstr "" -#: ../libvips/foreign/magick2vips.c:869 -#, c-format -msgid "" -"unable to ping blob\n" -"libMagick error: %s %s" +#: libvips/foreign/tiffload.c:211 +msgid "Rotate image using orientation tag" msgstr "" -#: ../libvips/foreign/fits.c:263 -msgid "dimensions above 3 must be size 1" +#: libvips/foreign/tiffload.c:217 +msgid "subifd" msgstr "" -#: ../libvips/foreign/fits.c:279 -#, c-format -msgid "bad number of axis %d" +#: libvips/foreign/tiffload.c:218 +msgid "Subifd index" msgstr "" -#: ../libvips/foreign/fits.c:295 -#, c-format -msgid "unsupported bitpix %d\n" +#: libvips/foreign/tiffload.c:294 +msgid "load tiff from source" msgstr "" -#: ../libvips/foreign/fits.c:612 ../libvips/iofuncs/vips.c:191 -#, c-format -msgid "unable to write to \"%s\"" +#: libvips/foreign/tiffload.c:374 +msgid "load tiff from file" msgstr "" -#: ../libvips/foreign/fits.c:673 -#, c-format -msgid "unsupported BandFmt %d\n" +#: libvips/foreign/tiffload.c:454 +msgid "load tiff from buffer" msgstr "" -#: ../libvips/foreign/openslideload.c:167 -msgid "load file with OpenSlide" +#: libvips/foreign/tiffsave.c:248 +msgid "save image as tiff" msgstr "" -#: ../libvips/foreign/openslideload.c:194 -msgid "Level" +#: libvips/foreign/tiffsave.c:258 +msgid "Compression for this file" msgstr "" -#: ../libvips/foreign/openslideload.c:195 -msgid "Load this level from the file" +#: libvips/foreign/tiffsave.c:272 +msgid "Predictor" msgstr "" -#: ../libvips/foreign/openslideload.c:201 -msgid "Autocrop" +#: libvips/foreign/tiffsave.c:273 +msgid "Compression prediction" msgstr "" -#: ../libvips/foreign/openslideload.c:202 -msgid "Crop to image bounds" +#: libvips/foreign/tiffsave.c:280 +msgid "Tile" msgstr "" -#: ../libvips/foreign/openslideload.c:208 -msgid "Associated" +#: libvips/foreign/tiffsave.c:281 +msgid "Write a tiled tiff" msgstr "" -#: ../libvips/foreign/openslideload.c:209 -msgid "Load this associated image" +#: libvips/foreign/tiffsave.c:301 +msgid "Pyramid" msgstr "" -#: ../libvips/foreign/rawload.c:108 -msgid "load raw data from a file" +#: libvips/foreign/tiffsave.c:302 +msgid "Write a pyramidal tiff" msgstr "" -#: ../libvips/foreign/rawload.c:144 ../libvips/iofuncs/image.c:1228 -msgid "Size of header" +#: libvips/foreign/tiffsave.c:308 +msgid "Miniswhite" msgstr "" -#: ../libvips/foreign/rawload.c:145 ../libvips/iofuncs/image.c:1229 -msgid "Offset in bytes from start of file" +#: libvips/foreign/tiffsave.c:309 +msgid "Use 0 for white in 1-bit images" msgstr "" -#: ../libvips/foreign/jpeg2vips.c:187 -#, c-format -msgid "read gave %ld warnings" +#: libvips/foreign/tiffsave.c:316 +msgid "Write as a 1, 2, 4 or 8 bit image" msgstr "" -#: ../libvips/foreign/jpeg2vips.c:387 -msgid "unknown JFIF resolution unit" +#: libvips/foreign/tiffsave.c:322 libvips/foreign/tiffsave.c:323 +msgid "Resolution unit" msgstr "" -#: ../libvips/foreign/tiffsave.c:172 ../libvips/foreign/tiffsave.c:358 -msgid "save image to tiff file" +#: libvips/foreign/tiffsave.c:343 +msgid "Bigtiff" msgstr "" -#: ../libvips/foreign/tiffsave.c:182 -msgid "Compression for this file" +#: libvips/foreign/tiffsave.c:344 +msgid "Write a bigtiff image" msgstr "" -#: ../libvips/foreign/tiffsave.c:189 ../libvips/foreign/webpsave.c:115 -#: ../libvips/foreign/jpegsave.c:149 -msgid "Q" +#: libvips/foreign/tiffsave.c:351 +msgid "Write a properties document to IMAGEDESCRIPTION" msgstr "" -#: ../libvips/foreign/tiffsave.c:190 ../libvips/foreign/webpsave.c:116 -#: ../libvips/foreign/jpegsave.c:150 -msgid "Q factor" +#: libvips/foreign/tiffsave.c:365 +msgid "Deflate (1-9, default 6) or ZSTD (1-22, default 9) compression level" msgstr "" -#: ../libvips/foreign/tiffsave.c:196 -msgid "predictor" +#: libvips/foreign/tiffsave.c:372 +msgid "Enable WEBP lossless mode" msgstr "" -#: ../libvips/foreign/tiffsave.c:197 -msgid "Compression prediction" +#: libvips/foreign/tiffsave.c:385 +msgid "Sub-IFD" msgstr "" -#: ../libvips/foreign/tiffsave.c:204 -msgid "profile" +#: libvips/foreign/tiffsave.c:386 +msgid "Save pyr layers as sub-IFDs" msgstr "" -#: ../libvips/foreign/tiffsave.c:211 -msgid "Tile" +#: libvips/foreign/tiffsave.c:392 +msgid "Premultiply" msgstr "" -#: ../libvips/foreign/tiffsave.c:212 -msgid "Write a tiled tiff" +#: libvips/foreign/tiffsave.c:393 +msgid "Save with premultiplied alpha" msgstr "" -#: ../libvips/foreign/tiffsave.c:232 -msgid "Pyramid" +#: libvips/foreign/tiffsave.c:399 +msgid "RGB JPEG" msgstr "" -#: ../libvips/foreign/tiffsave.c:233 -msgid "Write a pyramidal tiff" +#: libvips/foreign/tiffsave.c:400 +msgid "Output RGB JPEG rather than YCbCr" msgstr "" -#: ../libvips/foreign/tiffsave.c:240 +#: libvips/foreign/tiffsave.c:407 msgid "Squash images down to 1 bit" msgstr "" -#: ../libvips/foreign/tiffsave.c:246 -msgid "Miniswhite" +#: libvips/foreign/tiffsave.c:470 +msgid "save image to tiff target" msgstr "" -#: ../libvips/foreign/tiffsave.c:247 -msgid "Use 0 for white in 1-bit images" +#: libvips/foreign/tiffsave.c:523 +msgid "save image to tiff file" msgstr "" -#: ../libvips/foreign/tiffsave.c:253 ../libvips/foreign/tiffsave.c:254 -msgid "Resolution unit" +#: libvips/foreign/tiffsave.c:584 +msgid "save image to tiff buffer" msgstr "" -#: ../libvips/foreign/tiffsave.c:274 -msgid "Bigtiff" +#: libvips/foreign/vips2jpeg.c:176 +#, c-format +msgid "%s" msgstr "" -#: ../libvips/foreign/tiffsave.c:275 -msgid "Write a bigtiff image" +#: libvips/foreign/vips2jpeg.c:273 +#, c-format +msgid "field \"%s\" is too large for a single JPEG marker, ignoring" msgstr "" -#: ../libvips/foreign/tiffsave.c:281 -msgid "RGB JPEG" +#: libvips/foreign/vips2jpeg.c:1059 +msgid "libvips built without JPEG support" msgstr "" -#: ../libvips/foreign/tiffsave.c:282 -msgid "Output RGB JPEG rather than YCbCr" -msgstr "" +#: libvips/foreign/vips2magick.c:319 +#, fuzzy +msgid "unsupported image format" +msgstr "unsupported colour type" -#: ../libvips/foreign/tiffsave.c:288 ../libvips/foreign/dzsave.c:2193 -msgid "Properties" +#: libvips/foreign/vips2magick.c:349 +msgid "unsupported number of image bands" msgstr "" -#: ../libvips/foreign/tiffsave.c:289 -msgid "Write a properties document to IMAGEDESCRIPTION" +#: libvips/foreign/vips2magick.c:464 +msgid "save with ImageMagick" msgstr "" -#: ../libvips/foreign/tiffsave.c:433 -msgid "save image to tiff buffer" +#: libvips/foreign/vips2magick.c:490 +msgid "Quality to use" msgstr "" -#: ../libvips/foreign/svgload.c:207 -msgid "SVG rendering failed" +#: libvips/foreign/vips2magick.c:496 +msgid "Optimize_gif_frames" msgstr "" -#: ../libvips/foreign/svgload.c:274 -msgid "load SVG with rsvg" +#: libvips/foreign/vips2magick.c:497 +msgid "Apply GIF frames optimization" msgstr "" -#: ../libvips/foreign/radsave.c:97 -msgid "save Radiance" +#: libvips/foreign/vips2magick.c:503 +msgid "Optimize_gif_transparency" msgstr "" -#: ../libvips/foreign/radsave.c:150 -msgid "save image to Radiance file" +#: libvips/foreign/vips2magick.c:504 +msgid "Apply GIF transparency optimization" msgstr "" -#: ../libvips/foreign/radsave.c:213 -msgid "save image to Radiance buffer" +#: libvips/foreign/vips2magick.c:574 +msgid "save file with ImageMagick" msgstr "" -#: ../libvips/foreign/dzsave.c:181 ../libvips/iofuncs/vips.c:712 -#, c-format -msgid "unable to set property \"%s\" to value \"%s\"." +#: libvips/foreign/vips2magick.c:646 +msgid "save image to magick buffer" msgstr "" -#: ../libvips/foreign/dzsave.c:196 -#, c-format -msgid "unable to set create node \"%s\"" +#: libvips/foreign/vips2magick.c:677 +msgid "save bmp image with ImageMagick" msgstr "" -#: ../libvips/foreign/dzsave.c:252 ../libvips/foreign/dzsave.c:257 -#: ../libvips/foreign/dzsave.c:284 ../libvips/iofuncs/vips.c:849 -#: ../libvips/iofuncs/vips.c:856 -msgid "xml save error" +#: libvips/foreign/vips2magick.c:710 +msgid "save bmp image to magick buffer" msgstr "" -#: ../libvips/foreign/dzsave.c:351 ../libvips/foreign/dzsave.c:357 -msgid "unable to close stream" +#: libvips/foreign/vips2magick.c:743 +msgid "save gif image with ImageMagick" msgstr "" -#: ../libvips/foreign/dzsave.c:1395 -msgid "too many files in zip" +#: libvips/foreign/vips2magick.c:776 +msgid "save gif image to magick buffer" msgstr "" -#: ../libvips/foreign/dzsave.c:1405 -msgid "output file too large" +#: libvips/foreign/vips2tiff.c:1449 +msgid "can only pyramid LABQ and non-complex images" msgstr "" -#: ../libvips/foreign/dzsave.c:1762 -msgid "overlap too large" +#: libvips/foreign/vips2tiff.c:1472 +msgid "tile size not a multiple of 16" msgstr "" -#: ../libvips/foreign/dzsave.c:1904 -#, c-format -msgid "output directory %s/%s_files exists" +#: libvips/foreign/vips2tiff.c:1830 libvips/foreign/vips2tiff.c:2019 +msgid "TIFF write tile failed" msgstr "" -#: ../libvips/foreign/dzsave.c:1932 ../libvips/iofuncs/util.c:1625 -#, c-format -msgid "unable to make temporary file %s" +#: libvips/foreign/vipsload.c:126 +msgid "no filename associated with source" msgstr "" -#: ../libvips/foreign/dzsave.c:2002 -msgid "deflate-level not supported by libgsf, using default compression" +#: libvips/foreign/vipsload.c:157 +msgid "load vips base class" msgstr "" -#: ../libvips/foreign/dzsave.c:2117 -msgid "save image to deep zoom format" +#: libvips/foreign/vipsload.c:228 +msgid "load vips from file" msgstr "" -#: ../libvips/foreign/dzsave.c:2127 -msgid "Base name" +#: libvips/foreign/vipsload.c:303 +msgid "load vips from source" msgstr "" -#: ../libvips/foreign/dzsave.c:2128 -msgid "Base name to save to" +#: libvips/foreign/vipspng.c:450 +msgid "unsupported color type" +msgstr "unsupported colour type" + +#: libvips/foreign/vipspng.c:564 +msgid "unable to read PNG header" msgstr "" -#: ../libvips/foreign/dzsave.c:2134 -msgid "Layout" +#: libvips/foreign/vipspng.c:756 +msgid "libpng read error" msgstr "" -#: ../libvips/foreign/dzsave.c:2135 -msgid "Directory layout" +#: libvips/foreign/vipspng.c:1113 +msgid "compress should be in [0,9]" msgstr "" -#: ../libvips/foreign/dzsave.c:2142 -msgid "suffix" +#: libvips/foreign/vipspng.c:1141 +#, c-format +msgid "can't save %d band image as png" msgstr "" -#: ../libvips/foreign/dzsave.c:2143 -msgid "Filename suffix for tiles" +#: libvips/foreign/vipspng.c:1349 +#, c-format +msgid "unable to write to target %s" msgstr "" -#: ../libvips/foreign/dzsave.c:2149 -msgid "Overlap" +#: libvips/foreign/vipssave.c:114 +msgid "no filename associated with target" msgstr "" -#: ../libvips/foreign/dzsave.c:2150 -msgid "Tile overlap in pixels" +#: libvips/foreign/vipssave.c:141 +msgid "save vips base class" msgstr "" -#: ../libvips/foreign/dzsave.c:2156 -msgid "Tile size" +#: libvips/foreign/vipssave.c:193 +msgid "save image to file in vips format" msgstr "" -#: ../libvips/foreign/dzsave.c:2157 -msgid "Tile size in pixels" +#: libvips/foreign/vipssave.c:249 +msgid "save image to target in vips format" msgstr "" -#: ../libvips/foreign/dzsave.c:2164 -msgid "Pyramid depth" +#: libvips/foreign/webp2vips.c:407 +msgid "unable to parse image" msgstr "" -#: ../libvips/foreign/dzsave.c:2171 -msgid "Center" +#: libvips/foreign/webp2vips.c:595 +msgid "unable to loop through frames" msgstr "" -#: ../libvips/foreign/dzsave.c:2172 -msgid "Center image in tile" +#: libvips/foreign/webpload.c:164 +msgid "load webp" msgstr "" -#: ../libvips/foreign/dzsave.c:2179 -msgid "Rotate image during save" +#: libvips/foreign/webpload.c:258 +msgid "load webp from source" msgstr "" -#: ../libvips/foreign/dzsave.c:2185 -msgid "Container" +#: libvips/foreign/webpload.c:338 +msgid "load webp from file" msgstr "" -#: ../libvips/foreign/dzsave.c:2186 -msgid "Pyramid container type" +#: libvips/foreign/webpload.c:418 +msgid "load webp from buffer" msgstr "" -#: ../libvips/foreign/dzsave.c:2194 -msgid "Write a properties file to the output directory" +#: libvips/foreign/webpsave.c:248 +msgid "picture version error" msgstr "" -#: ../libvips/foreign/dzsave.c:2201 -msgid "ZIP deflate compression level" +#: libvips/foreign/webpsave.c:290 +msgid "picture memory error" msgstr "" -#: ../libvips/foreign/dzsave.c:2210 -msgid "Directory name" +#: libvips/foreign/webpsave.c:315 +msgid "anim add error" msgstr "" -#: ../libvips/foreign/dzsave.c:2211 -msgid "Directory name to save to" +#: libvips/foreign/webpsave.c:332 +msgid "unable to encode" msgstr "" -#: ../libvips/foreign/dzsave.c:2315 -msgid "save image to deepzoom file" +#: libvips/foreign/webpsave.c:428 +msgid "chunk add error" msgstr "" -#: ../libvips/foreign/dzsave.c:2377 ../libvips/iofuncs/image.c:2590 -#: ../libvips/iofuncs/image.c:2592 ../libvips/iofuncs/memory.c:309 -#: ../libvips/iofuncs/memory.c:311 -#, c-format -msgid "out of memory --- size == %dMB" +#: libvips/foreign/webpsave.c:534 libvips/foreign/webpsave.c:575 +msgid "mux error" msgstr "" -#: ../libvips/foreign/dzsave.c:2402 -msgid "save image to dz buffer" +#: libvips/foreign/webpsave.c:595 libvips/foreign/webpsave.c:605 +#: libvips/foreign/webpsave.c:644 +msgid "config version error" msgstr "" -#: ../libvips/foreign/radload.c:122 -msgid "load a Radiance image from a file" +#: libvips/foreign/webpsave.c:625 +msgid "invalid configuration" msgstr "" -#: ../libvips/foreign/openexrload.c:128 -msgid "load an OpenEXR image" +#: libvips/foreign/webpsave.c:655 +msgid "unable to init animation" msgstr "" -#: ../libvips/foreign/vipssave.c:104 -msgid "save image to vips file" +#: libvips/foreign/webpsave.c:698 +msgid "anim close error" msgstr "" -#: ../libvips/foreign/webpsave.c:107 -msgid "save webp" +#: libvips/foreign/webpsave.c:703 +msgid "anim build error" msgstr "" -#: ../libvips/foreign/webpsave.c:122 -msgid "lossless" +#: libvips/foreign/webpsave.c:711 libvips/mosaicing/lrmerge.c:309 +#: libvips/mosaicing/tbmerge.c:187 libvips/mosaicing/tbmerge.c:262 +#: libvips/mosaicing/tbmerge.c:594 +msgid "internal error" msgstr "" -#: ../libvips/foreign/webpsave.c:123 -msgid "enable lossless compression" +#: libvips/foreign/webpsave.c:817 +msgid "save as WebP" msgstr "" -#: ../libvips/foreign/webpsave.c:129 -msgid "preset" +#: libvips/foreign/webpsave.c:840 +msgid "Preset" msgstr "" -#: ../libvips/foreign/webpsave.c:130 +#: libvips/foreign/webpsave.c:841 msgid "Preset for lossy compression" msgstr "" -#: ../libvips/foreign/webpsave.c:137 +#: libvips/foreign/webpsave.c:848 msgid "Smart subsampling" msgstr "" -#: ../libvips/foreign/webpsave.c:138 +#: libvips/foreign/webpsave.c:849 msgid "Enable high quality chroma subsampling" msgstr "" -#: ../libvips/foreign/webpsave.c:144 +#: libvips/foreign/webpsave.c:855 msgid "Near lossless" msgstr "" -#: ../libvips/foreign/webpsave.c:145 +#: libvips/foreign/webpsave.c:856 msgid "Enable preprocessing in lossless mode (uses Q)" msgstr "" -#: ../libvips/foreign/webpsave.c:151 +#: libvips/foreign/webpsave.c:862 msgid "Alpha quality" msgstr "" -#: ../libvips/foreign/webpsave.c:152 +#: libvips/foreign/webpsave.c:863 msgid "Change alpha plane fidelity for lossy compression" msgstr "" -#: ../libvips/foreign/webpsave.c:210 -msgid "save image to webp file" -msgstr "" - -#: ../libvips/foreign/webpsave.c:281 -msgid "save image to webp buffer" -msgstr "" - -#: ../libvips/foreign/webpsave.c:330 ../libvips/foreign/jpegsave.c:386 -msgid "error writing output" +#: libvips/foreign/webpsave.c:869 +msgid "Minimise size" msgstr "" -#: ../libvips/foreign/webpsave.c:346 -msgid "save image to webp mime" +#: libvips/foreign/webpsave.c:870 +msgid "Optimise for minimum size" msgstr "" -#: ../libvips/foreign/radiance.c:685 -msgid "end of file" +#: libvips/foreign/webpsave.c:876 +msgid "Minimum keyframe spacing" msgstr "" -#: ../libvips/foreign/radiance.c:773 -msgid "scanline length mismatch" +#: libvips/foreign/webpsave.c:877 +msgid "Minimum number of frames between key frames" msgstr "" -#: ../libvips/foreign/radiance.c:790 -msgid "overrun" +#: libvips/foreign/webpsave.c:883 +msgid "Maximum keyframe spacing" msgstr "" -#: ../libvips/foreign/radiance.c:1040 -msgid "error reading radiance header" +#: libvips/foreign/webpsave.c:884 +msgid "Maximum number of frames between key frames" msgstr "" -#: ../libvips/foreign/radiance.c:1057 -msgid "image size out of bounds" +#: libvips/foreign/webpsave.c:891 libvips/foreign/webpsave.c:912 +msgid "Level of CPU effort to reduce file size" msgstr "" -#: ../libvips/foreign/radiance.c:1125 -#, c-format -msgid "read error line %d" +#: libvips/foreign/webpsave.c:897 +msgid "Target size" msgstr "" -#: ../libvips/foreign/rawsave.c:139 -msgid "save image to raw file" +#: libvips/foreign/webpsave.c:898 +msgid "Desired target size in bytes" msgstr "" -#: ../libvips/foreign/rawsave.c:245 -msgid "write raw image to file descriptor" +#: libvips/foreign/webpsave.c:904 +msgid "Passes" msgstr "" -#: ../libvips/foreign/rawsave.c:251 -msgid "File descriptor" +#: libvips/foreign/webpsave.c:905 +msgid "Number of entropy-analysis passes (in [1..10])" msgstr "" -#: ../libvips/foreign/rawsave.c:252 -msgid "File descriptor to write to" +#: libvips/foreign/webpsave.c:911 +msgid "Reduction effort" msgstr "" -#: ../libvips/foreign/jpegsave.c:139 -msgid "save jpeg" +#: libvips/foreign/webpsave.c:918 +msgid "Mixed encoding" msgstr "" -#: ../libvips/foreign/jpegsave.c:163 -msgid "Optimize_coding" +#: libvips/foreign/webpsave.c:919 +msgid "Allow mixed encoding (might reduce file size)" msgstr "" -#: ../libvips/foreign/jpegsave.c:164 -msgid "Compute optimal Huffman coding tables" +#: libvips/foreign/webpsave.c:925 +msgid "Smart deblocking" msgstr "" -#: ../libvips/foreign/jpegsave.c:171 -msgid "Generate an interlaced (progressive) jpeg" +#: libvips/foreign/webpsave.c:926 +msgid "Enable auto-adjusting of the deblocking filter" msgstr "" -#: ../libvips/foreign/jpegsave.c:177 -msgid "No subsample" +#: libvips/foreign/webpsave.c:1156 +msgid "save image to webp mime" msgstr "" -#: ../libvips/foreign/jpegsave.c:178 -msgid "Disable chroma subsample" +#: libvips/freqfilt/freqfilt.c:94 +msgid "frequency-domain filter operations" msgstr "" -#: ../libvips/foreign/jpegsave.c:184 -msgid "Trellis quantisation" +#: libvips/freqfilt/freqmult.c:126 +msgid "frequency-domain filtering" msgstr "" -#: ../libvips/foreign/jpegsave.c:185 -msgid "Apply trellis quantisation to each 8x8 block" +#: libvips/freqfilt/freqmult.c:131 +msgid "Input mask image" msgstr "" -#: ../libvips/foreign/jpegsave.c:191 -msgid "Overshoot de-ringing" +#: libvips/freqfilt/fwfft.c:145 libvips/freqfilt/fwfft.c:266 +#: libvips/freqfilt/invfft.c:124 libvips/freqfilt/invfft.c:203 +msgid "unable to create transform plan" msgstr "" -#: ../libvips/foreign/jpegsave.c:192 -msgid "Apply overshooting to samples with extreme values" +#: libvips/freqfilt/fwfft.c:351 +msgid "forward FFT" msgstr "" -#: ../libvips/foreign/jpegsave.c:198 -msgid "Optimize scans" +#: libvips/freqfilt/invfft.c:263 +msgid "inverse FFT" msgstr "" -#: ../libvips/foreign/jpegsave.c:199 -msgid "Split the spectrum of DCT coefficients into separate scans" +#: libvips/freqfilt/invfft.c:267 +msgid "Real" msgstr "" -#: ../libvips/foreign/jpegsave.c:205 -msgid "Quantization table" +#: libvips/freqfilt/invfft.c:268 +msgid "Output only the real part of the transform" msgstr "" -#: ../libvips/foreign/jpegsave.c:206 -msgid "Use predefined quantization table with given index" +#: libvips/freqfilt/phasecor.c:107 +msgid "calculate phase correlation" msgstr "" -#: ../libvips/foreign/jpegsave.c:264 -msgid "save image to jpeg file" +#: libvips/freqfilt/spectrum.c:100 +msgid "make displayable power spectrum" msgstr "" -#: ../libvips/foreign/jpegsave.c:336 -msgid "save image to jpeg buffer" +#: libvips/histogram/case.c:164 +msgid "bad number of cases" msgstr "" -#: ../libvips/foreign/jpegsave.c:402 -msgid "save image to jpeg mime" +#: libvips/histogram/case.c:169 +msgid "index image not 1-band" msgstr "" -#: ../libvips/foreign/analyze2vips.c:311 -msgid "header file size incorrect" +#: libvips/histogram/case.c:233 +msgid "use pixel values to pick cases from an array of images" msgstr "" -#: ../libvips/foreign/analyze2vips.c:356 -msgid "header size incorrect" +#: libvips/histogram/case.c:245 +msgid "Cases" msgstr "" -#: ../libvips/foreign/analyze2vips.c:374 -#, c-format -msgid "%d-dimensional images not supported" +#: libvips/histogram/case.c:246 +msgid "Array of case images" msgstr "" -#: ../libvips/foreign/analyze2vips.c:427 -#, c-format -msgid "datatype %d not supported" +#: libvips/histogram/hist_cum.c:158 +msgid "form cumulative histogram" msgstr "" -#: ../libvips/foreign/matrixload.c:137 -msgid "load matrix from file" +#: libvips/histogram/hist_entropy.c:107 +msgid "estimate image entropy" msgstr "" -#: ../libvips/foreign/jpegload.c:109 -#, c-format -msgid "bad shrink factor %d" +#: libvips/histogram/hist_entropy.c:112 +#: libvips/histogram/hist_ismonotonic.c:119 +msgid "Input histogram image" msgstr "" -#: ../libvips/foreign/jpegload.c:131 -msgid "load jpeg" +#: libvips/histogram/hist_equal.c:110 +msgid "histogram equalisation" msgstr "" -#: ../libvips/foreign/jpegload.c:144 ../libvips/foreign/tiffload.c:113 -msgid "Autorotate" +#: libvips/histogram/hist_equal.c:127 +msgid "Equalise with this band" msgstr "" -#: ../libvips/foreign/jpegload.c:145 -msgid "Rotate image using exif orientation" +#: libvips/histogram/hist_ismonotonic.c:114 +msgid "test for monotonicity" msgstr "" -#: ../libvips/foreign/jpegload.c:219 -msgid "load jpeg from file" +#: libvips/histogram/hist_ismonotonic.c:124 +msgid "Monotonic" msgstr "" -#: ../libvips/foreign/jpegload.c:304 -msgid "load jpeg from buffer" +#: libvips/histogram/hist_ismonotonic.c:125 +msgid "true if in is monotonic" msgstr "" -#: ../libvips/foreign/analyzeload.c:119 -msgid "load an Analyze6 image" +#: libvips/histogram/hist_local.c:304 libvips/histogram/stdif.c:236 +#: libvips/morphology/rank.c:491 +msgid "window too large" msgstr "" -#: ../libvips/foreign/vips2tiff.c:470 -msgid "rounding up IPCT data length" +#: libvips/histogram/hist_local.c:355 +msgid "local histogram equalisation" msgstr "" -#: ../libvips/foreign/vips2tiff.c:948 -#, c-format -msgid "image height %d is not a factor of page-height %d" +#: libvips/histogram/hist_local.c:374 libvips/histogram/stdif.c:309 +#: libvips/morphology/rank.c:571 +msgid "Window width in pixels" msgstr "" -#: ../libvips/foreign/vips2tiff.c:964 -msgid "can't pyramid multi page images --- disabling pyramid" +#: libvips/histogram/hist_local.c:381 libvips/histogram/stdif.c:316 +#: libvips/morphology/rank.c:578 +msgid "Window height in pixels" msgstr "" -#: ../libvips/foreign/vips2tiff.c:977 -msgid "tile size not a multiple of 16" +#: libvips/histogram/hist_local.c:387 +msgid "Max slope" msgstr "" -#: ../libvips/foreign/vips2tiff.c:988 -msgid "can only pyramid LABQ and non-complex images" +#: libvips/histogram/hist_local.c:388 +msgid "Maximum slope (CLAHE)" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1009 -msgid "can't have 1-bit JPEG -- disabling JPEG" +#: libvips/histogram/hist_match.c:154 +msgid "match two histograms" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1020 -msgid "" -"can only save non-complex greyscale images as miniswhite -- disabling " -"miniswhite" +#: libvips/histogram/hist_match.c:162 +msgid "Input histogram" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1043 -msgid "image over 4gb, enabling bigtiff" +#: libvips/histogram/hist_match.c:167 libvips/mosaicing/match.c:196 +#: libvips/mosaicing/merge.c:122 libvips/mosaicing/mosaic1.c:498 +#: libvips/mosaicing/mosaic.c:179 +msgid "Reference" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1295 -msgid "TIFF write tile failed" +#: libvips/histogram/hist_match.c:168 +msgid "Reference histogram" msgstr "" -#: ../libvips/foreign/matload.c:121 -msgid "load mat from file" +#: libvips/histogram/hist_norm.c:137 +msgid "normalise histogram" msgstr "" -#: ../libvips/foreign/vipsload.c:122 -msgid "load vips from file" +#: libvips/histogram/histogram.c:223 +msgid "histogram operations" msgstr "" -#: ../libvips/foreign/tiffload.c:96 -msgid "load tiff" +#: libvips/histogram/hist_plot.c:329 +msgid "plot histogram" msgstr "" -#: ../libvips/foreign/tiffload.c:100 -msgid "Load this page from the image" +#: libvips/histogram/hist_unary.c:84 +msgid "hist_unary operations" msgstr "" -#: ../libvips/foreign/tiffload.c:114 -msgid "Rotate image using orientation tag" +#: libvips/histogram/maplut.c:110 +#, c-format +msgid "%d overflows detected" msgstr "" -#: ../libvips/foreign/tiffload.c:207 -msgid "load tiff from file" +#: libvips/histogram/maplut.c:738 +msgid "map an image though a lut" msgstr "" -#: ../libvips/foreign/tiffload.c:306 -msgid "load tiff from buffer" +#: libvips/histogram/maplut.c:756 +msgid "LUT" msgstr "" -#: ../libvips/freqfilt/spectrum.c:101 -msgid "make displayable power spectrum" +#: libvips/histogram/maplut.c:757 +msgid "Look-up table image" msgstr "" -#: ../libvips/freqfilt/phasecor.c:108 -msgid "calculate phase correlation" +#: libvips/histogram/maplut.c:763 +msgid "Apply one-band lut to this band of in" msgstr "" -#: ../libvips/freqfilt/fwfft.c:137 ../libvips/freqfilt/fwfft.c:252 -#: ../libvips/freqfilt/invfft.c:120 ../libvips/freqfilt/invfft.c:194 -msgid "unable to create transform plan" +#: libvips/histogram/percent.c:105 +msgid "find threshold for percent of pixels" msgstr "" -#: ../libvips/freqfilt/fwfft.c:335 -msgid "forward FFT" +#: libvips/histogram/percent.c:115 +msgid "Percent" msgstr "" -#: ../libvips/freqfilt/freqmult.c:127 -msgid "frequency-domain filtering" +#: libvips/histogram/percent.c:116 +msgid "Percent of pixels" msgstr "" -#: ../libvips/freqfilt/freqmult.c:131 -msgid "mask" +#: libvips/histogram/percent.c:123 +msgid "Threshold above which lie percent of pixels" msgstr "" -#: ../libvips/freqfilt/freqmult.c:132 -msgid "Input mask image" +#: libvips/histogram/stdif.c:240 +msgid "too many bands" msgstr "" -#: ../libvips/freqfilt/freqfilt.c:94 -msgid "frequency-domain filter operations" +#: libvips/histogram/stdif.c:290 +msgid "statistical difference" msgstr "" -#: ../libvips/freqfilt/invfft.c:252 -msgid "inverse FFT" +#: libvips/histogram/stdif.c:322 +msgid "Mean weight" msgstr "" -#: ../libvips/freqfilt/invfft.c:256 -msgid "Real" +#: libvips/histogram/stdif.c:323 +msgid "Weight of new mean" msgstr "" -#: ../libvips/freqfilt/invfft.c:257 -msgid "Output only the real part of the transform" +#: libvips/histogram/stdif.c:330 +msgid "New mean" msgstr "" -#: ../libvips/histogram/hist_match.c:154 -msgid "match two histograms" +#: libvips/histogram/stdif.c:336 +msgid "Deviation weight" msgstr "" -#: ../libvips/histogram/hist_match.c:162 -msgid "Input histogram" +#: libvips/histogram/stdif.c:337 +msgid "Weight of new deviation" msgstr "" -#: ../libvips/histogram/hist_match.c:167 ../libvips/mosaicing/merge.c:109 -#: ../libvips/mosaicing/mosaic.c:180 ../libvips/mosaicing/match.c:204 -#: ../libvips/mosaicing/mosaic1.c:489 -msgid "Reference" +#: libvips/histogram/stdif.c:343 +msgid "Deviation" msgstr "" -#: ../libvips/histogram/hist_match.c:168 -msgid "Reference histogram" +#: libvips/histogram/stdif.c:344 +msgid "New deviation" msgstr "" -#: ../libvips/histogram/hist_cum.c:148 -msgid "form cumulative histogram" +#: libvips/iofuncs/buf.c:609 +#, c-format +msgid "%zd bytes of binary data" msgstr "" -#: ../libvips/histogram/hist_equal.c:104 -msgid "histogram equalisation" +#: libvips/iofuncs/connection.c:126 +msgid "Descriptor" msgstr "" -#: ../libvips/histogram/hist_equal.c:121 -msgid "Equalise with this band" +#: libvips/iofuncs/connection.c:127 +msgid "File descriptor for read or write" msgstr "" -#: ../libvips/histogram/stdif.c:236 ../libvips/histogram/hist_local.c:304 -#: ../libvips/morphology/rank.c:354 -msgid "window too large" +#: libvips/iofuncs/connection.c:134 +msgid "Name of file to open" msgstr "" -#: ../libvips/histogram/stdif.c:240 -msgid "too many bands" +#: libvips/iofuncs/error.c:296 +msgid "system error" msgstr "" -#: ../libvips/histogram/stdif.c:290 -msgid "statistical difference" +#: libvips/iofuncs/error.c:443 +msgid "image must be uncoded" msgstr "" -#: ../libvips/histogram/stdif.c:309 ../libvips/histogram/hist_local.c:371 -#: ../libvips/morphology/rank.c:420 -msgid "Window width in pixels" +#: libvips/iofuncs/error.c:471 +msgid "image coding must be 'none' or 'labq'" msgstr "" -#: ../libvips/histogram/stdif.c:316 ../libvips/histogram/hist_local.c:378 -#: ../libvips/morphology/rank.c:427 -msgid "Window height in pixels" +#: libvips/iofuncs/error.c:499 +msgid "unknown image coding" msgstr "" -#: ../libvips/histogram/stdif.c:322 -msgid "Mean weight" +#: libvips/iofuncs/error.c:524 +#, c-format +msgid "coding '%s' only" msgstr "" -#: ../libvips/histogram/stdif.c:323 -msgid "Weight of new mean" +#: libvips/iofuncs/error.c:549 +msgid "image must one band" msgstr "" -#: ../libvips/histogram/stdif.c:330 -msgid "New mean" +#: libvips/iofuncs/error.c:574 +#, c-format +msgid "image must have %d bands" msgstr "" -#: ../libvips/histogram/stdif.c:336 -msgid "Deviation weight" +#: libvips/iofuncs/error.c:599 +msgid "image must have one or three bands" msgstr "" -#: ../libvips/histogram/stdif.c:337 -msgid "Weight of new deviation" +#: libvips/iofuncs/error.c:625 +#, c-format +msgid "image must have at least %d bands" msgstr "" -#: ../libvips/histogram/stdif.c:343 -msgid "Deviation" +#: libvips/iofuncs/error.c:653 +msgid "images must have the same number of bands, or one must be single-band" msgstr "" -#: ../libvips/histogram/stdif.c:344 -msgid "New deviation" +#: libvips/iofuncs/error.c:680 +#, c-format +msgid "image must have 1 or %d bands" msgstr "" -#: ../libvips/histogram/histogram.c:223 -msgid "histogram operations" +#: libvips/iofuncs/error.c:704 +msgid "image must be non-complex" msgstr "" -#: ../libvips/histogram/hist_entropy.c:109 -msgid "estimate image entropy" +#: libvips/iofuncs/error.c:728 +msgid "image must be complex" msgstr "" -#: ../libvips/histogram/hist_entropy.c:114 -#: ../libvips/histogram/hist_ismonotonic.c:118 -msgid "Input histogram image" +#: libvips/iofuncs/error.c:755 +msgid "image must be two-band or complex" msgstr "" -#: ../libvips/histogram/hist_ismonotonic.c:113 -msgid "test for monotonicity" +#: libvips/iofuncs/error.c:781 +#, c-format +msgid "image must be %s" msgstr "" -#: ../libvips/histogram/hist_ismonotonic.c:123 -msgid "Monotonic" +#: libvips/iofuncs/error.c:806 +msgid "image must be integer" msgstr "" -#: ../libvips/histogram/hist_ismonotonic.c:124 -msgid "true if in is monotonic" +#: libvips/iofuncs/error.c:831 +msgid "image must be unsigned integer" msgstr "" -#: ../libvips/histogram/hist_norm.c:137 -msgid "normalise histogram" +#: libvips/iofuncs/error.c:859 +msgid "image must be 8- or 16-bit integer, signed or unsigned" msgstr "" -#: ../libvips/histogram/hist_plot.c:338 -msgid "plot histogram" +#: libvips/iofuncs/error.c:885 +msgid "image must be 8- or 16-bit unsigned integer" msgstr "" -#: ../libvips/histogram/hist_unary.c:85 -msgid "hist_unary operations" +#: libvips/iofuncs/error.c:911 +msgid "image must be 8- or 16-bit unsigned integer, or float" msgstr "" -#: ../libvips/histogram/hist_local.c:354 -msgid "local histogram equalisation" +#: libvips/iofuncs/error.c:938 +msgid "image must be unsigned int or float" msgstr "" -#: ../libvips/histogram/hist_local.c:384 -msgid "Max slope" +#: libvips/iofuncs/error.c:964 +msgid "images must match in size" msgstr "" -#: ../libvips/histogram/hist_local.c:385 -msgid "Maximum slope (CLAHE)" +#: libvips/iofuncs/error.c:990 +msgid "images must be odd and square" msgstr "" -#: ../libvips/histogram/percent.c:106 -msgid "find threshold for percent of pixels" +#: libvips/iofuncs/error.c:1016 +msgid "images must have the same number of bands" msgstr "" -#: ../libvips/histogram/percent.c:116 -msgid "Percent" +#: libvips/iofuncs/error.c:1070 +msgid "images must have the same band format" msgstr "" -#: ../libvips/histogram/percent.c:117 -msgid "Percent of pixels" +#: libvips/iofuncs/error.c:1096 +msgid "images must have the same coding" msgstr "" -#: ../libvips/histogram/percent.c:123 -msgid "Threshold" +#: libvips/iofuncs/error.c:1119 +#, c-format +msgid "vector must have %d elements" msgstr "" -#: ../libvips/histogram/percent.c:124 -msgid "Threshold above which lie percent of pixels" +#: libvips/iofuncs/error.c:1155 +msgid "vector must have 1 element" msgstr "" -#: ../libvips/histogram/maplut.c:110 +#: libvips/iofuncs/error.c:1158 #, c-format -msgid "%d overflows detected" +msgid "vector must have 1 or %d elements" msgstr "" -#: ../libvips/histogram/maplut.c:688 -msgid "map an image though a lut" +#: libvips/iofuncs/error.c:1183 +msgid "histograms must have width or height 1" msgstr "" -#: ../libvips/histogram/maplut.c:706 -msgid "LUT" +#: libvips/iofuncs/error.c:1188 +msgid "histograms must have not have more than 65536 elements" msgstr "" -#: ../libvips/histogram/maplut.c:707 -msgid "Look-up table image" +#: libvips/iofuncs/error.c:1224 +msgid "matrix image too large" msgstr "" -#: ../libvips/histogram/maplut.c:712 -msgid "band" +#: libvips/iofuncs/error.c:1229 +msgid "matrix image must have one band" +msgstr "" + +#: libvips/iofuncs/error.c:1263 +msgid "separable matrix images must have width or height 1" msgstr "" -#: ../libvips/histogram/maplut.c:713 -msgid "apply one-band lut to this band of in" +#: libvips/iofuncs/error.c:1289 +msgid "precision must be int or float" msgstr "" -#: ../libvips/introspect.c:54 -msgid "dump introspection data" +#: libvips/iofuncs/generate.c:696 +msgid "demand hint not set" msgstr "" -#: ../libvips/introspect.c:71 -msgid "- introspect" +#: libvips/iofuncs/generate.c:715 libvips/iofuncs/generate.c:743 +msgid "generate() called twice" msgstr "" -#: ../libvips/iofuncs/sink.c:106 +#: libvips/iofuncs/generate.c:784 libvips/iofuncs/image.c:3235 #, c-format -msgid "stop function failed for image \"%s\"" +msgid "unable to output to a %s image" msgstr "" -#: ../libvips/iofuncs/sink.c:143 +#: libvips/iofuncs/ginputsource.c:164 libvips/iofuncs/ginputsource.c:229 #, c-format -msgid "start function failed for image \"%s\"" +msgid "Error while seeking: %s" msgstr "" -#: ../libvips/iofuncs/sink.c:176 -msgid "per-thread state for sink" +#: libvips/iofuncs/ginputsource.c:185 +msgid "Cannot truncate VipsGInputStream" msgstr "" -#: ../libvips/iofuncs/type.c:854 +#: libvips/iofuncs/ginputsource.c:206 #, c-format -msgid "unable to convert \"%s\" to int" +msgid "Error while reading: %s" msgstr "" -#: ../libvips/iofuncs/type.c:1046 -#, c-format -msgid "unable to convert \"%s\" to float" +#: libvips/iofuncs/ginputsource.c:275 +msgid "Stream to wrap" msgstr "" -#: ../libvips/iofuncs/image.c:536 -msgid "unable to close fd" +#: libvips/iofuncs/header.c:1380 +#, c-format +msgid "field \"%s\" not found" msgstr "" -#: ../libvips/iofuncs/image.c:617 +#: libvips/iofuncs/header.c:1614 #, c-format -msgid "%dx%d %s, %d band, %s" -msgid_plural "%dx%d %s, %d bands, %s" -msgstr[0] "" -msgstr[1] "" +msgid "field \"%s\" is of type %s, not %s" +msgstr "" -#: ../libvips/iofuncs/image.c:651 +#: libvips/iofuncs/header.c:1888 #, c-format -msgid " %s, %d band, %s" -msgid_plural " %s, %d bands, %s" -msgstr[0] "" -msgstr[1] "" +msgid "field \"%s\" is of type %s, not VipsRefString" +msgstr "" -#: ../libvips/iofuncs/image.c:784 +#: libvips/iofuncs/image.c:539 +msgid "unable to close fd" +msgstr "" + +#: libvips/iofuncs/image.c:762 #, c-format msgid "%s %s: %d x %d pixels, %d threads, %d x %d tiles, %d lines in buffer" msgstr "" -#: ../libvips/iofuncs/image.c:797 +#: libvips/iofuncs/image.c:775 #, c-format msgid "%s %s: %d%% complete" msgstr "" -#. Spaces at end help to erase the %complete message we overwrite. -#. -#: ../libvips/iofuncs/image.c:816 +#: libvips/iofuncs/image.c:794 #, c-format msgid "%s %s: done in %.3gs \n" msgstr "" -#: ../libvips/iofuncs/image.c:1000 +#: libvips/iofuncs/image.c:976 #, c-format msgid "unable to open \"%s\", file too short" msgstr "" -#: ../libvips/iofuncs/image.c:1009 +#: libvips/iofuncs/image.c:985 #, c-format msgid "%s is longer than expected" msgstr "" -#: ../libvips/iofuncs/image.c:1027 +#: libvips/iofuncs/image.c:1003 #, c-format msgid "bad mode \"%s\"" msgstr "" -#: ../libvips/iofuncs/image.c:1103 +#: libvips/iofuncs/image.c:1075 msgid "image class" msgstr "" -#: ../libvips/iofuncs/image.c:1201 +#: libvips/iofuncs/image.c:1173 msgid "Image filename" msgstr "" -#: ../libvips/iofuncs/image.c:1208 +#: libvips/iofuncs/image.c:1180 msgid "Open mode" msgstr "" -#: ../libvips/iofuncs/image.c:1214 +#: libvips/iofuncs/image.c:1186 msgid "Kill" msgstr "" -#: ../libvips/iofuncs/image.c:1215 +#: libvips/iofuncs/image.c:1187 msgid "Block evaluation on this image" msgstr "" -#: ../libvips/iofuncs/image.c:1221 +#: libvips/iofuncs/image.c:1193 msgid "Demand style" msgstr "" -#: ../libvips/iofuncs/image.c:1222 +#: libvips/iofuncs/image.c:1194 msgid "Preferred demand style for this image" msgstr "" -#: ../libvips/iofuncs/image.c:1235 +#: libvips/iofuncs/image.c:1207 msgid "Foreign buffer" msgstr "" -#: ../libvips/iofuncs/image.c:1236 +#: libvips/iofuncs/image.c:1208 msgid "Pointer to foreign pixels" msgstr "" -#: ../libvips/iofuncs/image.c:1647 +#: libvips/iofuncs/image.c:1660 #, c-format msgid "killed for image \"%s\"" msgstr "" -#: ../libvips/iofuncs/image.c:2049 -#, c-format -msgid "memory area too small --- should be %zd bytes, you passed %zd" +#: libvips/iofuncs/image.c:2069 +msgid "memory area too small --- should be %" msgstr "" -#: ../libvips/iofuncs/image.c:2264 +#: libvips/iofuncs/image.c:2258 +msgid "unable to load source" +msgstr "" + +#: libvips/iofuncs/image.c:2369 #, c-format msgid "bad array length --- should be %d, you passed %d" msgstr "" -#: ../libvips/iofuncs/image.c:2854 -msgid "bad image descriptor" +#: libvips/iofuncs/image.c:2886 libvips/iofuncs/image.c:2888 +#: libvips/iofuncs/memory.c:336 libvips/iofuncs/memory.c:338 +#: libvips/iofuncs/memory.c:409 libvips/iofuncs/memory.c:411 +#, c-format +msgid "out of memory --- size == %dMB" msgstr "" -#: ../libvips/iofuncs/image.c:2912 ../libvips/iofuncs/generate.c:779 -#, c-format -msgid "unable to output to a %s image" +#: libvips/iofuncs/image.c:3179 +msgid "bad image descriptor" msgstr "" -#: ../libvips/iofuncs/image.c:2976 +#: libvips/iofuncs/image.c:3298 #, c-format msgid "auto-rewind for %s failed" msgstr "" -#: ../libvips/iofuncs/image.c:3045 ../libvips/iofuncs/image.c:3175 -#: ../libvips/iofuncs/image.c:3354 +#: libvips/iofuncs/image.c:3372 libvips/iofuncs/image.c:3502 +#: libvips/iofuncs/image.c:3679 msgid "image not readable" msgstr "" -#: ../libvips/iofuncs/image.c:3090 ../libvips/iofuncs/image.c:3314 -#: ../libvips/iofuncs/image.c:3331 +#: libvips/iofuncs/image.c:3417 libvips/iofuncs/image.c:3643 msgid "no image data" msgstr "" -#: ../libvips/iofuncs/image.c:3196 ../libvips/iofuncs/image.c:3384 -#: ../libvips/iofuncs/image.c:3393 +#: libvips/iofuncs/image.c:3523 libvips/iofuncs/image.c:3709 +#: libvips/iofuncs/image.c:3718 msgid "image already written" msgstr "" -#: ../libvips/iofuncs/image.c:3220 ../libvips/iofuncs/image.c:3405 +#: libvips/iofuncs/image.c:3547 libvips/iofuncs/image.c:3730 msgid "image not writeable" msgstr "" -#: ../libvips/iofuncs/image.c:3272 +#: libvips/iofuncs/image.c:3602 msgid "bad file type" msgstr "" -#: ../libvips/iofuncs/threadpool.c:247 -msgid "unable to create thread" -msgstr "" - -#: ../libvips/iofuncs/threadpool.c:410 +#: libvips/iofuncs/init.c:316 tools/vips.c:772 #, c-format -msgid "threads clipped to %d" +msgid "unable to load \"%s\" -- %s" msgstr "" -#: ../libvips/iofuncs/threadpool.c:456 -msgid "per-thread state for vipsthreadpool" +#: libvips/iofuncs/init.c:1270 +msgid "flag not in [0, 5]" msgstr "" -#: ../libvips/iofuncs/mapfile.c:131 ../libvips/iofuncs/mapfile.c:298 +#: libvips/iofuncs/mapfile.c:189 libvips/iofuncs/mapfile.c:355 msgid "unable to CreateFileMapping" msgstr "" -#: ../libvips/iofuncs/mapfile.c:139 ../libvips/iofuncs/mapfile.c:310 +#: libvips/iofuncs/mapfile.c:196 libvips/iofuncs/mapfile.c:367 msgid "unable to MapViewOfFile" msgstr "" -#: ../libvips/iofuncs/mapfile.c:179 +#: libvips/iofuncs/mapfile.c:235 msgid "unable to mmap" msgstr "" -#: ../libvips/iofuncs/mapfile.c:180 -#, c-format -msgid "" -"map failed (%s), running very low on system resources, expect a crash soon" -msgstr "" - -#: ../libvips/iofuncs/mapfile.c:197 ../libvips/iofuncs/mapfile.c:304 +#: libvips/iofuncs/mapfile.c:250 libvips/iofuncs/mapfile.c:361 msgid "unable to UnmapViewOfFile" msgstr "" -#: ../libvips/iofuncs/mapfile.c:203 +#: libvips/iofuncs/mapfile.c:256 msgid "unable to munmap file" msgstr "" -#: ../libvips/iofuncs/mapfile.c:225 +#: libvips/iofuncs/mapfile.c:278 msgid "file is less than 64 bytes" msgstr "" -#: ../libvips/iofuncs/mapfile.c:230 ../libvips/iofuncs/mapfile.c:264 +#: libvips/iofuncs/mapfile.c:283 libvips/iofuncs/mapfile.c:317 msgid "unable to get file status" msgstr "" -#: ../libvips/iofuncs/mapfile.c:236 +#: libvips/iofuncs/mapfile.c:289 msgid "not a regular file" msgstr "" -#: ../libvips/iofuncs/mapfile.c:270 +#: libvips/iofuncs/mapfile.c:323 msgid "unable to read data" msgstr "" -#: ../libvips/iofuncs/mapfile.c:330 +#: libvips/iofuncs/mapfile.c:387 #, c-format msgid "unable to mmap: \"%s\" - %s" msgstr "" -#: ../libvips/iofuncs/mapfile.c:340 +#: libvips/iofuncs/mapfile.c:398 #, c-format msgid "unable to mmap \"%s\" to same address" msgstr "" -#: ../libvips/iofuncs/sinkdisc.c:122 -msgid "per-thread state for sinkdisc" -msgstr "" - -#: ../libvips/iofuncs/sinkdisc.c:261 ../libvips/iofuncs/util.c:535 -msgid "write failed" -msgstr "" - -#: ../libvips/iofuncs/operation.c:225 -#, c-format -msgid "%d pixels calculated" -msgstr "" - -#: ../libvips/iofuncs/operation.c:309 ../libvips/iofuncs/operation.c:330 -#: ../libvips/iofuncs/operation.c:338 ../libvips/iofuncs/operation.c:350 -msgid "default" -msgstr "" - -#: ../libvips/iofuncs/operation.c:313 -msgid "allowed" -msgstr "" - -#: ../libvips/iofuncs/operation.c:341 ../libvips/iofuncs/operation.c:353 -msgid "min" -msgstr "" - -#: ../libvips/iofuncs/operation.c:343 ../libvips/iofuncs/operation.c:355 -msgid "max" -msgstr "" - -#: ../libvips/iofuncs/operation.c:571 -msgid "operations" -msgstr "" - -#: ../libvips/iofuncs/operation.c:659 ../libvips/iofuncs/object.c:1511 -#: ../libvips/resample/interpolate.c:637 -#, c-format -msgid "class \"%s\" not found" -msgstr "" - -#: ../libvips/iofuncs/operation.c:665 +#: libvips/iofuncs/object.c:346 #, c-format -msgid "\"%s\" is not an instantiable class" +msgid "parameter %s not set" msgstr "" -#: ../libvips/iofuncs/operation.c:1129 +#: libvips/iofuncs/object.c:781 #, c-format -msgid "unknown argument '%s'" -msgstr "" - -#: ../libvips/iofuncs/operation.c:1253 -msgid "too few arguments" -msgstr "" - -#: ../libvips/iofuncs/operation.c:1374 -msgid "too many arguments" -msgstr "" - -#: ../libvips/iofuncs/sinkmemory.c:109 -msgid "per-thread state for sinkmemory" -msgstr "" - -#: ../libvips/iofuncs/generate.c:425 -msgid "too many images" -msgstr "" - -#: ../libvips/iofuncs/generate.c:690 -msgid "demand hint not set" -msgstr "" - -#: ../libvips/iofuncs/generate.c:709 ../libvips/iofuncs/generate.c:737 -msgid "generate() called twice" +msgid "no property named `%s'" msgstr "" -#: ../libvips/iofuncs/window.c:237 ../libvips/iofuncs/vips.c:918 +#: libvips/iofuncs/object.c:787 #, c-format -msgid "unable to read data for \"%s\", %s" -msgstr "" - -#: ../libvips/iofuncs/window.c:238 ../libvips/iofuncs/vips.c:808 -#: ../libvips/iofuncs/vips.c:919 -msgid "file has been truncated" -msgstr "" - -#: ../libvips/iofuncs/system.c:184 -msgid "unable to substitute input filename" -msgstr "" - -#: ../libvips/iofuncs/system.c:191 -msgid "unable to substitute output filename" +msgid "no vips argument named `%s'" msgstr "" -#: ../libvips/iofuncs/system.c:226 +#: libvips/iofuncs/object.c:793 #, c-format -msgid "command \"%s\" failed" +msgid "argument `%s' has no instance" msgstr "" -#: ../libvips/iofuncs/system.c:234 +#: libvips/iofuncs/object.c:1533 libvips/iofuncs/operation.c:749 +#: libvips/resample/interpolate.c:659 #, c-format -msgid "stderr output: %s" -msgstr "" - -#: ../libvips/iofuncs/system.c:269 -msgid "run an external command" -msgstr "" - -#: ../libvips/iofuncs/system.c:290 -msgid "Command" -msgstr "" - -#: ../libvips/iofuncs/system.c:291 -msgid "Command to run" +msgid "class \"%s\" not found" msgstr "" -#: ../libvips/iofuncs/system.c:297 -msgid "Input format" +#: libvips/iofuncs/object.c:1584 +msgid "base class" msgstr "" -#: ../libvips/iofuncs/system.c:298 -msgid "Format for input filename" +#: libvips/iofuncs/object.c:1598 +msgid "Nickname" msgstr "" -#: ../libvips/iofuncs/system.c:304 -msgid "Output format" +#: libvips/iofuncs/object.c:1599 +msgid "Class nickname" msgstr "" -#: ../libvips/iofuncs/system.c:305 -msgid "Format for output filename" +#: libvips/iofuncs/object.c:1605 +msgid "Description" msgstr "" -#: ../libvips/iofuncs/system.c:312 -msgid "Command log" +#: libvips/iofuncs/object.c:1606 +msgid "Class description" msgstr "" -#: ../libvips/iofuncs/header.c:1067 +#: libvips/iofuncs/object.c:1844 #, c-format -msgid "field \"%s\" not found" +msgid "no value supplied for argument '%s'" msgstr "" -#: ../libvips/iofuncs/header.c:1269 +#: libvips/iofuncs/object.c:1847 #, c-format -msgid "field \"%s\" is of type %s, not %s" +msgid "no value supplied for argument '%s' ('%s')" msgstr "" -#: ../libvips/iofuncs/header.c:1498 +#: libvips/iofuncs/object.c:2039 libvips/iofuncs/object.c:2058 #, c-format -msgid "field \"%s\" is of type %s, not VipsRefString" +msgid "'%s' is not an integer" msgstr "" -#: ../libvips/iofuncs/init.c:234 +#: libvips/iofuncs/object.c:2481 #, c-format -msgid "unable to load \"%s\" -- %s" -msgstr "" - -#: ../libvips/iofuncs/init.c:655 -msgid "show informative messages" -msgstr "" - -#: ../libvips/iofuncs/init.c:658 -msgid "abort on first error or warning" +msgid "expected string or ), saw %s" msgstr "" -#: ../libvips/iofuncs/init.c:661 -msgid "evaluate with N concurrent threads" +#: libvips/iofuncs/object.c:2524 +#, c-format +msgid "unable to set '%s'" msgstr "" -#: ../libvips/iofuncs/init.c:664 -msgid "set tile width to N (DEBUG)" +#: libvips/iofuncs/object.c:2537 +msgid "not , or ) after parameter" msgstr "" -#: ../libvips/iofuncs/init.c:667 -msgid "set tile height to N (DEBUG)" +#: libvips/iofuncs/object.c:2544 +msgid "extra tokens after ')'" msgstr "" -#: ../libvips/iofuncs/init.c:670 -msgid "set thinstrip height to N (DEBUG)" +#: libvips/iofuncs/operation.c:235 +#, c-format +msgid "%d pixels calculated" msgstr "" -#: ../libvips/iofuncs/init.c:673 -msgid "set fatstrip height to N (DEBUG)" +#: libvips/iofuncs/operation.c:343 +msgid "default enum" msgstr "" -#: ../libvips/iofuncs/init.c:676 -msgid "show progress feedback" +#: libvips/iofuncs/operation.c:347 +msgid "allowed enums" msgstr "" -#: ../libvips/iofuncs/init.c:679 -msgid "leak-check on exit" +#: libvips/iofuncs/operation.c:375 +msgid "default flags" msgstr "" -#: ../libvips/iofuncs/init.c:682 -msgid "profile and dump timing on exit" +#: libvips/iofuncs/operation.c:380 +msgid "allowed flags" msgstr "" -#: ../libvips/iofuncs/init.c:685 -msgid "images larger than N are decompressed to disc" +#: libvips/iofuncs/operation.c:396 libvips/iofuncs/operation.c:404 +#: libvips/iofuncs/operation.c:416 +msgid "default" msgstr "" -#: ../libvips/iofuncs/init.c:688 -msgid "disable vectorised versions of operations" +#: libvips/iofuncs/operation.c:407 libvips/iofuncs/operation.c:419 +msgid "min" msgstr "" -#: ../libvips/iofuncs/init.c:691 -msgid "cache at most N operations" +#: libvips/iofuncs/operation.c:409 libvips/iofuncs/operation.c:421 +msgid "max" msgstr "" -#: ../libvips/iofuncs/init.c:694 -msgid "cache at most N bytes in memory" +#: libvips/iofuncs/operation.c:618 +msgid "operation is blocked" msgstr "" -#: ../libvips/iofuncs/init.c:697 -msgid "allow at most N open files" +#: libvips/iofuncs/operation.c:664 +msgid "operations" msgstr "" -#: ../libvips/iofuncs/init.c:700 -msgid "trace operation cache" +#: libvips/iofuncs/operation.c:755 +#, c-format +msgid "\"%s\" is not an instantiable class" msgstr "" -#: ../libvips/iofuncs/init.c:703 -msgid "dump operation cache on exit" +#: libvips/iofuncs/operation.c:1225 +#, c-format +msgid "unknown argument '%s'" msgstr "" -#: ../libvips/iofuncs/init.c:706 -msgid "print libvips version" +#: libvips/iofuncs/operation.c:1350 +msgid "too few arguments" msgstr "" -#: ../libvips/iofuncs/init.c:1091 -msgid "flag not in [0, 5]" +#: libvips/iofuncs/operation.c:1469 +msgid "too many arguments" msgstr "" -#: ../libvips/iofuncs/region.c:585 ../libvips/iofuncs/region.c:657 -#: ../libvips/iofuncs/region.c:805 ../libvips/iofuncs/region.c:1516 +#: libvips/iofuncs/region.c:565 libvips/iofuncs/region.c:635 +#: libvips/iofuncs/region.c:777 libvips/iofuncs/region.c:1848 msgid "valid clipped to nothing" msgstr "" -#: ../libvips/iofuncs/region.c:702 +#: libvips/iofuncs/region.c:675 msgid "bad image type" msgstr "" -#: ../libvips/iofuncs/region.c:747 +#: libvips/iofuncs/region.c:719 msgid "no pixel data on attached image" msgstr "" -#: ../libvips/iofuncs/region.c:753 +#: libvips/iofuncs/region.c:725 msgid "images do not match in pixel size" msgstr "" -#: ../libvips/iofuncs/region.c:786 ../libvips/iofuncs/region.c:1498 +#: libvips/iofuncs/region.c:758 libvips/iofuncs/region.c:1830 msgid "dest too small" msgstr "" -#: ../libvips/iofuncs/region.c:875 +#: libvips/iofuncs/region.c:847 msgid "bad position" msgstr "" -#: ../libvips/iofuncs/region.c:1291 +#: libvips/iofuncs/region.c:1628 msgid "stop requested" msgstr "" -#: ../libvips/iofuncs/region.c:1376 ../libvips/iofuncs/region.c:1569 +#: libvips/iofuncs/region.c:1711 libvips/iofuncs/region.c:1901 #, c-format msgid "unable to input from a %s image" msgstr "" -#: ../libvips/iofuncs/region.c:1400 +#: libvips/iofuncs/region.c:1735 msgid "incomplete header" msgstr "" -#: ../libvips/iofuncs/region.c:1472 +#: libvips/iofuncs/region.c:1804 msgid "inappropriate region type" msgstr "" -#: ../libvips/iofuncs/vips.c:306 -#, c-format -msgid "\"%s\" is not a VIPS image" +#: libvips/iofuncs/sbuf.c:85 +msgid "buffered source" msgstr "" -#: ../libvips/iofuncs/vips.c:406 -msgid "unable to read history" +#: libvips/iofuncs/sbuf.c:280 +msgid "end of file" msgstr "" -#: ../libvips/iofuncs/vips.c:439 -msgid "more than a 10 megabytes of XML? sufferin' succotash!" +#: libvips/iofuncs/sink.c:262 +#, c-format +msgid "stop function failed for image \"%s\"" msgstr "" -#: ../libvips/iofuncs/vips.c:487 -msgid "incorrect namespace in XML" +#: libvips/iofuncs/sink.c:299 +#, c-format +msgid "start function failed for image \"%s\"" msgstr "" -#: ../libvips/iofuncs/vips.c:611 -msgid "error transforming from save format" +#: libvips/iofuncs/sink.c:331 +msgid "per-thread state for sink" msgstr "" -#: ../libvips/iofuncs/vips.c:760 -msgid "error transforming to save format" +#: libvips/iofuncs/sinkdisc.c:108 libvips/iofuncs/util.c:477 +msgid "write failed" msgstr "" -#: ../libvips/iofuncs/vips.c:904 -#, c-format -msgid "unable to read header for \"%s\"" +#: libvips/iofuncs/sinkdisc.c:137 +msgid "per-thread state for sinkdisc" msgstr "" -#: ../libvips/iofuncs/vips.c:930 -#, c-format -msgid "error reading XML: %s" +#: libvips/iofuncs/sinkmemory.c:109 +msgid "per-thread state for sinkmemory" msgstr "" -#: ../libvips/iofuncs/error.c:287 -msgid "windows error" +#: libvips/iofuncs/sinkscreen.c:196 +msgid "per-thread state for render" msgstr "" -#: ../libvips/iofuncs/error.c:296 -msgid "unix error" +#: libvips/iofuncs/sinkscreen.c:1122 +msgid "bad parameters" msgstr "" -#: ../libvips/iofuncs/error.c:447 -msgid "image must be uncoded" +#: libvips/iofuncs/source.c:281 libvips/iofuncs/target.c:114 +msgid "don't set 'filename' and 'descriptor'" msgstr "" -#: ../libvips/iofuncs/error.c:475 -msgid "image coding must be 'none' or 'labq'" +#: libvips/iofuncs/source.c:358 +msgid "input source" msgstr "" -#: ../libvips/iofuncs/error.c:503 -msgid "unknown image coding" +#: libvips/iofuncs/source.c:366 libvips/iofuncs/target.c:304 +msgid "Blob" msgstr "" -#: ../libvips/iofuncs/error.c:528 -#, c-format -msgid "coding '%s' only" +#: libvips/iofuncs/source.c:367 +msgid "Blob to load from" msgstr "" -#: ../libvips/iofuncs/error.c:553 -msgid "image must one band" -msgstr "" +#: libvips/iofuncs/source.c:512 +#, fuzzy +msgid "unimplemented target" +msgstr "unimplemented input colour space 0x%x" -#: ../libvips/iofuncs/error.c:578 -#, c-format -msgid "image must have %d bands" +#: libvips/iofuncs/source.c:649 +msgid "unable to open for read" msgstr "" -#: ../libvips/iofuncs/error.c:603 -msgid "image must have one or three bands" +#: libvips/iofuncs/source.c:890 +msgid "pipe too long" msgstr "" -#: ../libvips/iofuncs/error.c:629 -#, c-format -msgid "image must have at least %d bands" +#: libvips/iofuncs/source.c:1165 libvips/iofuncs/source.c:1190 +#: libvips/iofuncs/target.c:206 +msgid "bad 'whence'" msgstr "" -#: ../libvips/iofuncs/error.c:657 -msgid "images must have the same number of bands, or one must be single-band" +#: libvips/iofuncs/source.c:1211 +msgid "bad seek to %" msgstr "" -#: ../libvips/iofuncs/error.c:684 -#, c-format -msgid "image must have 1 or %d bands" +#: libvips/iofuncs/sourcecustom.c:173 +msgid "Custom source" msgstr "" -#: ../libvips/iofuncs/error.c:708 -msgid "image must be non-complex" +#: libvips/iofuncs/sourceginput.c:219 +msgid "GInputStream source" msgstr "" -#: ../libvips/iofuncs/error.c:732 -msgid "image must be complex" +#: libvips/iofuncs/sourceginput.c:227 +msgid "Stream" msgstr "" -#: ../libvips/iofuncs/error.c:759 -msgid "image must be two-band or complex" +#: libvips/iofuncs/sourceginput.c:228 +msgid "GInputStream to read from" msgstr "" -#: ../libvips/iofuncs/error.c:785 -#, c-format -msgid "image must be %s" +#: libvips/iofuncs/system.c:185 +msgid "unable to substitute input filename" msgstr "" -#: ../libvips/iofuncs/error.c:810 -msgid "image must be integer" +#: libvips/iofuncs/system.c:191 +msgid "unable to substitute output filename" msgstr "" -#: ../libvips/iofuncs/error.c:835 -msgid "image must be unsigned integer" +#: libvips/iofuncs/system.c:226 +#, c-format +msgid "command \"%s\" failed" msgstr "" -#: ../libvips/iofuncs/error.c:863 -msgid "image must be 8- or 16-bit integer, signed or unsigned" +#: libvips/iofuncs/system.c:234 +#, c-format +msgid "stderr output: %s" msgstr "" -#: ../libvips/iofuncs/error.c:890 -msgid "image must be 8- or 16-bit unsigned integer" +#: libvips/iofuncs/system.c:269 +msgid "run an external command" msgstr "" -#: ../libvips/iofuncs/error.c:916 -msgid "image must be 8- or 16-bit unsigned integer, or float" +#: libvips/iofuncs/system.c:290 +msgid "Command" msgstr "" -#: ../libvips/iofuncs/error.c:944 -msgid "image must be unsigned int or float" +#: libvips/iofuncs/system.c:291 +msgid "Command to run" msgstr "" -#: ../libvips/iofuncs/error.c:969 -msgid "images must match in size" +#: libvips/iofuncs/system.c:297 +msgid "Input format" msgstr "" -#: ../libvips/iofuncs/error.c:995 -msgid "images must be odd and square" +#: libvips/iofuncs/system.c:298 +msgid "Format for input filename" msgstr "" -#: ../libvips/iofuncs/error.c:1021 -msgid "images must have the same number of bands" +#: libvips/iofuncs/system.c:304 +msgid "Output format" msgstr "" -#: ../libvips/iofuncs/error.c:1075 -msgid "images must have the same band format" +#: libvips/iofuncs/system.c:305 +msgid "Format for output filename" msgstr "" -#: ../libvips/iofuncs/error.c:1101 -msgid "images must have the same coding" +#: libvips/iofuncs/system.c:312 +msgid "Command log" msgstr "" -#: ../libvips/iofuncs/error.c:1124 -#, c-format -msgid "vector must have %d elements" +#: libvips/iofuncs/target.c:295 +msgid "File descriptor should output to memory" msgstr "" -#: ../libvips/iofuncs/error.c:1149 -#, c-format -msgid "vector must have 1 or %d elements" +#: libvips/iofuncs/target.c:305 +msgid "Blob to save to" msgstr "" -#: ../libvips/iofuncs/error.c:1174 -msgid "histograms must have width or height 1" +#: libvips/iofuncs/target.c:474 +msgid "write error" msgstr "" -#: ../libvips/iofuncs/error.c:1179 -msgid "histograms must have not have more than 65536 elements" +#: libvips/iofuncs/targetcustom.c:235 +msgid "Custom target" msgstr "" -#: ../libvips/iofuncs/error.c:1216 -msgid "matrix image too large" +#: libvips/iofuncs/thread.c:179 +msgid "unable to create thread" msgstr "" -#: ../libvips/iofuncs/error.c:1221 -msgid "matrix image must have one band" +#: libvips/iofuncs/thread.c:214 libvips/iofuncs/thread.c:243 +#, c-format +msgid "threads clipped to %d" msgstr "" -#: ../libvips/iofuncs/error.c:1255 -msgid "separable matrix images must have width or height 1" +#: libvips/iofuncs/threadpool.c:193 +msgid "per-thread state for vipsthreadpool" msgstr "" -#: ../libvips/iofuncs/error.c:1282 -msgid "precision must be int or float" +#: libvips/iofuncs/type.c:958 +#, c-format +msgid "unable to convert \"%s\" to int" msgstr "" -#: ../libvips/iofuncs/util.c:518 +#: libvips/iofuncs/util.c:455 msgid "unable to get file stats" msgstr "" -#: ../libvips/iofuncs/util.c:674 +#: libvips/iofuncs/util.c:619 #, c-format msgid "unable to open file \"%s\" for reading" msgstr "" -#: ../libvips/iofuncs/util.c:696 +#: libvips/iofuncs/util.c:641 #, c-format msgid "unable to open file \"%s\" for writing" msgstr "" -#: ../libvips/iofuncs/util.c:718 +#: libvips/iofuncs/util.c:662 #, c-format msgid "\"%s\" too long" msgstr "" -#: ../libvips/iofuncs/util.c:765 +#: libvips/iofuncs/util.c:710 #, c-format msgid "error reading from file \"%s\"" msgstr "" -#: ../libvips/iofuncs/util.c:812 +#: libvips/iofuncs/util.c:756 #, c-format msgid "write error (%zd out of %zd blocks written)" msgstr "" -#: ../libvips/iofuncs/util.c:1084 ../libvips/iofuncs/util.c:1091 -msgid "unable to truncate" +#: libvips/iofuncs/util.c:1003 +msgid "unable to seek" msgstr "" -#: ../libvips/iofuncs/util.c:1167 -#, c-format -msgid "unable to create directory \"%s\", %s" +#: libvips/iofuncs/util.c:1028 libvips/iofuncs/util.c:1035 +msgid "unable to truncate" msgstr "" -#: ../libvips/iofuncs/util.c:1191 +#: libvips/iofuncs/util.c:1121 #, c-format msgid "unable to remove directory \"%s\", %s" msgstr "" -#: ../libvips/iofuncs/util.c:1208 +#: libvips/iofuncs/util.c:1138 #, c-format msgid "unable to rename file \"%s\" as \"%s\", %s" msgstr "" -#: ../libvips/iofuncs/util.c:1348 +#: libvips/iofuncs/util.c:1267 msgid "unexpected end of string" msgstr "" -#: ../libvips/iofuncs/util.c:1366 ../libvips/iofuncs/util.c:1436 +#: libvips/iofuncs/util.c:1285 libvips/iofuncs/util.c:1355 #, c-format msgid "expected %s, saw %s" msgstr "" -#: ../libvips/iofuncs/util.c:1750 +#: libvips/iofuncs/util.c:1664 msgid "no such enum type" msgstr "" -#: ../libvips/iofuncs/util.c:1768 +#: libvips/iofuncs/util.c:1682 #, c-format msgid "enum '%s' has no member '%s', should be one of: %s" msgstr "" -#: ../libvips/iofuncs/util.c:1786 +#: libvips/iofuncs/util.c:1701 msgid "no such flag type" msgstr "" -#: ../libvips/iofuncs/util.c:1802 +#: libvips/iofuncs/util.c:1720 #, c-format -msgid "flags '%s' has no member '%s', should be one of: %s" -msgstr "" - -#: ../libvips/iofuncs/util.c:1889 -msgid "unable to form filename" -msgstr "" - -#: ../libvips/iofuncs/memory.c:251 -msgid "vips_free: too many frees" +msgid "flags '%s' has no member '%s'" msgstr "" -#: ../libvips/iofuncs/memory.c:253 -msgid "vips_free: too much free" -msgstr "" - -#: ../libvips/iofuncs/sinkscreen.c:188 -msgid "per-thread state for render" +#: libvips/iofuncs/vips.c:338 +#, c-format +msgid "\"%s\" is not a VIPS image" msgstr "" -#: ../libvips/iofuncs/sinkscreen.c:1088 -msgid "bad parameters" +#: libvips/iofuncs/vips.c:395 +msgid "unknown coding" msgstr "" -#: ../libvips/iofuncs/object.c:316 -#, c-format -msgid "parameter %s not set" +#: libvips/iofuncs/vips.c:405 +msgid "malformed LABQ image" msgstr "" -#: ../libvips/iofuncs/object.c:751 -#, c-format -msgid "no property named `%s'" +#: libvips/iofuncs/vips.c:414 +msgid "malformed RAD image" msgstr "" -#: ../libvips/iofuncs/object.c:759 -#, c-format -msgid "no vips argument named `%s'" +#: libvips/iofuncs/vips.c:485 +msgid "unable to read history" msgstr "" -#: ../libvips/iofuncs/object.c:765 -#, c-format -msgid "argument `%s' has no instance" +#: libvips/iofuncs/vips.c:518 +msgid "more than 100 megabytes of XML? sufferin' succotash!" msgstr "" -#: ../libvips/iofuncs/object.c:1561 -msgid "base class" +#: libvips/iofuncs/vips.c:552 +msgid "unable to allocate read buffer" msgstr "" -#: ../libvips/iofuncs/object.c:1575 -msgid "Nickname" +#: libvips/iofuncs/vips.c:558 +msgid "read error while fetching XML" msgstr "" -#: ../libvips/iofuncs/object.c:1576 -msgid "Class nickname" +#: libvips/iofuncs/vips.c:570 +msgid "XML parse error" msgstr "" -#: ../libvips/iofuncs/object.c:1582 -msgid "Description" +#: libvips/iofuncs/vips.c:635 +msgid "incorrect namespace in XML" msgstr "" -#: ../libvips/iofuncs/object.c:1583 -msgid "Class description" +#: libvips/iofuncs/vips.c:683 +msgid "error transforming from save format" msgstr "" -#: ../libvips/iofuncs/object.c:1781 -#, c-format -msgid "no value supplied for argument '%s'" +#: libvips/iofuncs/vips.c:784 libvips/iofuncs/vips.c:1056 +#: libvips/iofuncs/window.c:232 +msgid "file has been truncated" msgstr "" -#: ../libvips/iofuncs/object.c:1784 -#, c-format -msgid "no value supplied for argument '%s' ('%s')" +#: libvips/iofuncs/vips.c:836 libvips/iofuncs/vips.c:927 +msgid "error transforming to save format" msgstr "" -#: ../libvips/iofuncs/object.c:1942 ../libvips/iofuncs/object.c:1961 -#: ../libvips/iofuncs/object.c:2014 +#: libvips/iofuncs/vips.c:1041 #, c-format -msgid "'%s' is not an integer" +msgid "unable to read header for \"%s\"" msgstr "" -#: ../libvips/iofuncs/object.c:1978 +#: libvips/iofuncs/vips.c:1055 libvips/iofuncs/window.c:231 #, c-format -msgid "'%s' is not a double" +msgid "unable to read data for \"%s\", %s" msgstr "" -#: ../libvips/iofuncs/object.c:2293 +#: libvips/iofuncs/vips.c:1067 #, c-format -msgid "expected string or ), saw %s" +msgid "error reading vips image metadata: %s" msgstr "" -#: ../libvips/iofuncs/object.c:2336 -#, c-format -msgid "unable to set '%s'" +#: libvips/morphology/countlines.c:135 +msgid "count lines in an image" msgstr "" -#: ../libvips/iofuncs/object.c:2349 -msgid "not , or ) after parameter" +#: libvips/morphology/countlines.c:139 +msgid "Nolines" msgstr "" -#: ../libvips/iofuncs/object.c:2356 -msgid "extra tokens after ')'" +#: libvips/morphology/countlines.c:140 +msgid "Number of lines" msgstr "" -#: ../libvips/iofuncs/buf.c:610 -#, c-format -msgid "%zd bytes of binary data" +#: libvips/morphology/countlines.c:147 +msgid "Countlines left-right or up-down" msgstr "" -#. File length unit. -#. -#: ../libvips/iofuncs/buf.c:679 -msgid "bytes" +#: libvips/morphology/labelregions.c:120 +msgid "label regions in an image" msgstr "" -#. Kilobyte unit. -#. -#: ../libvips/iofuncs/buf.c:683 -msgid "KB" +#: libvips/morphology/labelregions.c:125 +msgid "Mask of region labels" msgstr "" -#. Megabyte unit. -#. -#: ../libvips/iofuncs/buf.c:687 -msgid "MB" +#: libvips/morphology/labelregions.c:130 +msgid "Segments" msgstr "" -#. Gigabyte unit. -#. -#: ../libvips/iofuncs/buf.c:691 -msgid "GB" +#: libvips/morphology/labelregions.c:131 +msgid "Number of discrete contiguous regions" msgstr "" -#. Terabyte unit. -#. -#: ../libvips/iofuncs/buf.c:695 -msgid "TB" +#: libvips/morphology/morph.c:885 +#, c-format +msgid "bad mask element (%f should be 0, 128 or 255)" msgstr "" -#: ../libvips/morphology/morph.c:139 +#: libvips/morphology/morph.c:955 msgid "morphology operation" msgstr "" -#: ../libvips/morphology/morph.c:155 +#: libvips/morphology/morph.c:971 msgid "Morphology" msgstr "" -#: ../libvips/morphology/morph.c:156 +#: libvips/morphology/morph.c:972 msgid "Morphological operation to perform" msgstr "" -#: ../libvips/morphology/rank.c:359 -msgid "index out of range" +#: libvips/morphology/morphology.c:115 +msgid "morphological operations" msgstr "" -#: ../libvips/morphology/rank.c:409 -msgid "rank filter" +#: libvips/morphology/nearest.c:305 +msgid "fill image zeros with nearest non-zero pixel" msgstr "" -#: ../libvips/morphology/rank.c:433 -msgid "index" +#: libvips/morphology/nearest.c:309 +msgid "Out" msgstr "" -#: ../libvips/morphology/rank.c:434 -msgid "Select pixel at index" +#: libvips/morphology/nearest.c:310 +msgid "Value of nearest non-zero pixel" msgstr "" -#: ../libvips/morphology/countlines.c:131 -msgid "count lines in an image" +#: libvips/morphology/nearest.c:316 +msgid "Distance to nearest non-zero pixel" msgstr "" -#: ../libvips/morphology/countlines.c:135 -msgid "Nolines" +#: libvips/morphology/rank.c:496 +msgid "index out of range" msgstr "" -#: ../libvips/morphology/countlines.c:136 -msgid "Number of lines" +#: libvips/morphology/rank.c:560 +msgid "rank filter" msgstr "" -#: ../libvips/morphology/countlines.c:143 -msgid "Countlines left-right or up-down" +#: libvips/morphology/rank.c:585 +msgid "Select pixel at index" msgstr "" -#: ../libvips/morphology/labelregions.c:121 -msgid "label regions in an image" +#: libvips/mosaicing/chkpair.c:200 +msgid "inputs incompatible" msgstr "" -#: ../libvips/morphology/labelregions.c:126 -msgid "Mask of region labels" +#: libvips/mosaicing/chkpair.c:204 libvips/mosaicing/im_tbcalcon.c:105 +msgid "help!" msgstr "" -#: ../libvips/morphology/labelregions.c:131 -msgid "Segments" +#: libvips/mosaicing/global_balance.c:151 +msgid "no matching '>'" msgstr "" -#: ../libvips/morphology/labelregions.c:132 -msgid "Number of discrete contiguous regions" +#: libvips/mosaicing/global_balance.c:160 +msgid "too many items" msgstr "" -#: ../libvips/morphology/morphology.c:111 -msgid "morphological operations" +#: libvips/mosaicing/global_balance.c:463 +msgid "circularity detected" msgstr "" -#: ../libvips/morphology/hitmiss.c:321 +#: libvips/mosaicing/global_balance.c:497 +#: libvips/mosaicing/global_balance.c:557 #, c-format -msgid "bad mask element (%d should be 0, 128 or 255)" +msgid "image \"%s\" used twice as output" msgstr "" -#: ../libvips/mosaicing/im_tbmerge.c:164 ../libvips/mosaicing/im_tbmerge.c:218 -#: ../libvips/mosaicing/im_tbmerge.c:536 ../libvips/mosaicing/im_lrmerge.c:216 -#: ../libvips/mosaicing/im_lrmerge.c:265 ../libvips/mosaicing/im_lrmerge.c:606 -msgid "internal error" +#: libvips/mosaicing/global_balance.c:606 +msgid "bad number of args in join line" msgstr "" -#: ../libvips/mosaicing/im_tbmerge.c:635 ../libvips/mosaicing/im_lrmerge.c:806 -msgid "unknown coding type" +#: libvips/mosaicing/global_balance.c:648 +msgid "bad number of args in join1 line" msgstr "" -#: ../libvips/mosaicing/im_tbmerge.c:653 ../libvips/mosaicing/im_lrmerge.c:823 -msgid "too much overlap" +#: libvips/mosaicing/global_balance.c:684 +msgid "bad number of args in copy line" msgstr "" -#: ../libvips/mosaicing/im_chkpair.c:201 -msgid "inputs incompatible" +#: libvips/mosaicing/global_balance.c:742 +msgid "" +"mosaic root not found in desc file\n" +"is this really a mosaiced image?" msgstr "" -#: ../libvips/mosaicing/im_chkpair.c:205 ../libvips/mosaicing/im_tbcalcon.c:103 -msgid "help!" +#: libvips/mosaicing/global_balance.c:753 +msgid "more than one root" msgstr "" -#: ../libvips/mosaicing/im_lrmosaic.c:114 ../libvips/mosaicing/im_tbmosaic.c:90 -msgid "bad area parameters" +#: libvips/mosaicing/global_balance.c:1525 +msgid "bad sizes" msgstr "" -#: ../libvips/mosaicing/im_lrmosaic.c:135 -#: ../libvips/mosaicing/im_tbmosaic.c:111 -msgid "overlap too small for search" +#: libvips/mosaicing/global_balance.c:1920 +msgid "global balance an image mosaic" msgstr "" -#: ../libvips/mosaicing/im_lrmosaic.c:168 -#: ../libvips/mosaicing/im_tbmosaic.c:144 -msgid "unknown Coding type" +#: libvips/mosaicing/global_balance.c:1936 +msgid "Gamma" msgstr "" -#: ../libvips/mosaicing/im_tbcalcon.c:117 -msgid "overlap too small" +#: libvips/mosaicing/global_balance.c:1937 +msgid "Image gamma" msgstr "" -#: ../libvips/mosaicing/merge.c:105 -msgid "merge two images" +#: libvips/mosaicing/global_balance.c:1943 +msgid "Int output" msgstr "" -#: ../libvips/mosaicing/merge.c:110 ../libvips/mosaicing/mosaic.c:181 -#: ../libvips/mosaicing/match.c:205 ../libvips/mosaicing/mosaic1.c:490 -msgid "Reference image" +#: libvips/mosaicing/global_balance.c:1944 +msgid "Integer output" msgstr "" -#: ../libvips/mosaicing/merge.c:115 ../libvips/mosaicing/mosaic.c:186 -#: ../libvips/mosaicing/match.c:210 ../libvips/mosaicing/mosaic1.c:495 -msgid "Secondary" +#: libvips/mosaicing/im_avgdxdy.c:65 +msgid "no points to average" msgstr "" -#: ../libvips/mosaicing/merge.c:116 ../libvips/mosaicing/mosaic.c:187 -#: ../libvips/mosaicing/match.c:211 ../libvips/mosaicing/mosaic1.c:496 -msgid "Secondary image" +#: libvips/mosaicing/im_clinear.c:138 +msgid "vips_invmat failed" msgstr "" -#: ../libvips/mosaicing/merge.c:128 -msgid "Horizontal or vertcial merge" +#: libvips/mosaicing/im_lrcalcon.c:206 +msgid "overlap too small for your search size" msgstr "" -#: ../libvips/mosaicing/merge.c:134 -msgid "dx" +#: libvips/mosaicing/im_lrcalcon.c:245 +#, c-format +msgid "found %d tie-points, need at least %d" msgstr "" -#: ../libvips/mosaicing/merge.c:135 -msgid "Horizontal displacement from sec to ref" +#: libvips/mosaicing/im_lrcalcon.c:290 +msgid "not 1-band uchar image" msgstr "" -#: ../libvips/mosaicing/merge.c:141 -msgid "dy" +#: libvips/mosaicing/im_tbcalcon.c:119 +msgid "overlap too small" msgstr "" -#: ../libvips/mosaicing/merge.c:142 -msgid "Vertical displacement from sec to ref" +#: libvips/mosaicing/lrmerge.c:786 +msgid "mwidth must be -1 or >= 0" msgstr "" -#: ../libvips/mosaicing/merge.c:148 ../libvips/mosaicing/mosaic.c:247 -#: ../libvips/mosaicing/mosaic1.c:597 -msgid "Max blend" +#: libvips/mosaicing/lrmerge.c:818 +msgid "no overlap" msgstr "" -#: ../libvips/mosaicing/merge.c:149 ../libvips/mosaicing/mosaic.c:248 -#: ../libvips/mosaicing/mosaic1.c:598 -msgid "Maximum blend size" +#: libvips/mosaicing/lrmerge.c:888 libvips/mosaicing/tbmerge.c:693 +msgid "unknown coding type" msgstr "" -#: ../libvips/mosaicing/im_remosaic.c:115 -#, c-format -msgid "substitute image \"%s\" is not the same size as \"%s\"" +#: libvips/mosaicing/lrmerge.c:906 libvips/mosaicing/tbmerge.c:711 +msgid "too much overlap" msgstr "" -#: ../libvips/mosaicing/im_remosaic.c:160 -#: ../libvips/mosaicing/global_balance.c:1767 -msgid "global balance an image mosaic" +#: libvips/mosaicing/lrmosaic.c:122 libvips/mosaicing/tbmosaic.c:93 +msgid "bad area parameters" msgstr "" -#: ../libvips/mosaicing/im_remosaic.c:176 -msgid "old_str" +#: libvips/mosaicing/lrmosaic.c:143 libvips/mosaicing/tbmosaic.c:114 +msgid "overlap too small for search" msgstr "" -#: ../libvips/mosaicing/im_remosaic.c:177 -msgid "Search for this string" +#: libvips/mosaicing/lrmosaic.c:171 libvips/mosaicing/tbmosaic.c:142 +msgid "unknown Coding type" msgstr "" -#: ../libvips/mosaicing/im_remosaic.c:183 -msgid "new_str" +#: libvips/mosaicing/match.c:192 +msgid "first-order match of two images" msgstr "" -#: ../libvips/mosaicing/im_remosaic.c:184 -msgid "And swap for this string" +#: libvips/mosaicing/match.c:197 libvips/mosaicing/merge.c:123 +#: libvips/mosaicing/mosaic1.c:499 libvips/mosaicing/mosaic.c:180 +msgid "Reference image" msgstr "" -#: ../libvips/mosaicing/im_lrcalcon.c:204 -msgid "overlap too small for your search size" +#: libvips/mosaicing/match.c:202 libvips/mosaicing/merge.c:128 +#: libvips/mosaicing/mosaic1.c:504 libvips/mosaicing/mosaic.c:185 +msgid "Secondary" msgstr "" -#: ../libvips/mosaicing/im_lrcalcon.c:243 -#, c-format -msgid "found %d tie-points, need at least %d" +#: libvips/mosaicing/match.c:203 libvips/mosaicing/merge.c:129 +#: libvips/mosaicing/mosaic1.c:505 libvips/mosaicing/mosaic.c:186 +msgid "Secondary image" msgstr "" -#: ../libvips/mosaicing/im_lrcalcon.c:288 -msgid "not 1-band uchar image" +#: libvips/mosaicing/match.c:214 libvips/mosaicing/mosaic1.c:523 +msgid "xr1" msgstr "" -#: ../libvips/mosaicing/global_balance.c:148 -msgid "no matching '>'" +#: libvips/mosaicing/match.c:215 libvips/mosaicing/match.c:222 +#: libvips/mosaicing/mosaic1.c:524 libvips/mosaicing/mosaic1.c:531 +msgid "Position of first reference tie-point" msgstr "" -#: ../libvips/mosaicing/global_balance.c:157 -msgid "too many items" +#: libvips/mosaicing/match.c:221 libvips/mosaicing/mosaic1.c:530 +msgid "yr1" msgstr "" -#: ../libvips/mosaicing/global_balance.c:451 -msgid "circularity detected" +#: libvips/mosaicing/match.c:228 libvips/mosaicing/mosaic1.c:537 +msgid "xs1" msgstr "" -#: ../libvips/mosaicing/global_balance.c:485 -#: ../libvips/mosaicing/global_balance.c:545 -#, c-format -msgid "image \"%s\" used twice as output" +#: libvips/mosaicing/match.c:229 libvips/mosaicing/match.c:236 +#: libvips/mosaicing/mosaic1.c:538 libvips/mosaicing/mosaic1.c:545 +msgid "Position of first secondary tie-point" msgstr "" -#: ../libvips/mosaicing/global_balance.c:594 -msgid "bad number of args in join line" +#: libvips/mosaicing/match.c:235 libvips/mosaicing/mosaic1.c:544 +msgid "ys1" msgstr "" -#: ../libvips/mosaicing/global_balance.c:636 -msgid "bad number of args in join1 line" +#: libvips/mosaicing/match.c:242 libvips/mosaicing/mosaic1.c:551 +msgid "xr2" msgstr "" -#: ../libvips/mosaicing/global_balance.c:672 -msgid "bad number of args in copy line" +#: libvips/mosaicing/match.c:243 libvips/mosaicing/match.c:250 +#: libvips/mosaicing/mosaic1.c:552 libvips/mosaicing/mosaic1.c:559 +msgid "Position of second reference tie-point" msgstr "" -#: ../libvips/mosaicing/global_balance.c:730 -msgid "" -"mosaic root not found in desc file\n" -"is this really a mosaiced image?" +#: libvips/mosaicing/match.c:249 libvips/mosaicing/mosaic1.c:558 +msgid "yr2" msgstr "" -#: ../libvips/mosaicing/global_balance.c:741 -msgid "more than one root" +#: libvips/mosaicing/match.c:256 libvips/mosaicing/mosaic1.c:565 +msgid "xs2" msgstr "" -#: ../libvips/mosaicing/global_balance.c:1060 -msgid "empty overlap!" +#: libvips/mosaicing/match.c:257 libvips/mosaicing/match.c:264 +#: libvips/mosaicing/mosaic1.c:566 libvips/mosaicing/mosaic1.c:573 +msgid "Position of second secondary tie-point" msgstr "" -#: ../libvips/mosaicing/global_balance.c:1783 -msgid "gamma" +#: libvips/mosaicing/match.c:263 libvips/mosaicing/mosaic1.c:572 +msgid "ys2" msgstr "" -#: ../libvips/mosaicing/global_balance.c:1784 -msgid "Image gamma" +#: libvips/mosaicing/match.c:270 libvips/mosaicing/mosaic1.c:579 +#: libvips/mosaicing/mosaic.c:232 +msgid "hwindow" msgstr "" -#: ../libvips/mosaicing/global_balance.c:1790 -msgid "Int output" +#: libvips/mosaicing/match.c:271 libvips/mosaicing/mosaic1.c:580 +#: libvips/mosaicing/mosaic.c:233 +msgid "Half window size" msgstr "" -#: ../libvips/mosaicing/global_balance.c:1791 -msgid "Integer output" +#: libvips/mosaicing/match.c:277 libvips/mosaicing/mosaic1.c:586 +#: libvips/mosaicing/mosaic.c:239 +msgid "harea" msgstr "" -#: ../libvips/mosaicing/im_avgdxdy.c:65 -msgid "no points to average" +#: libvips/mosaicing/match.c:278 libvips/mosaicing/mosaic1.c:587 +#: libvips/mosaicing/mosaic.c:240 +msgid "Half area size" msgstr "" -#: ../libvips/mosaicing/im_lrmerge.c:706 -msgid "mwidth must be -1 or >= 0" +#: libvips/mosaicing/match.c:284 libvips/mosaicing/mosaic1.c:593 +msgid "Search" msgstr "" -#: ../libvips/mosaicing/im_lrmerge.c:735 -msgid "no overlap" +#: libvips/mosaicing/match.c:285 libvips/mosaicing/mosaic1.c:594 +msgid "Search to improve tie-points" msgstr "" -#: ../libvips/mosaicing/mosaic.c:176 -msgid "mosaic two images" +#: libvips/mosaicing/match.c:291 libvips/mosaicing/mosaic1.c:600 +#: libvips/resample/affine.c:651 libvips/resample/mapim.c:561 +#: libvips/resample/quadratic.c:351 libvips/resample/resize.c:376 +#: libvips/resample/similarity.c:127 +msgid "Interpolate" msgstr "" -#: ../libvips/mosaicing/mosaic.c:199 ../libvips/mosaicing/mosaic1.c:508 -msgid "Horizontal or vertcial mosaic" +#: libvips/mosaicing/match.c:292 libvips/mosaicing/mosaic1.c:601 +#: libvips/resample/affine.c:652 libvips/resample/mapim.c:562 +#: libvips/resample/resize.c:377 libvips/resample/similarity.c:128 +msgid "Interpolate pixels with this" msgstr "" -#: ../libvips/mosaicing/mosaic.c:205 -msgid "xref" +#: libvips/mosaicing/matrixinvert.c:312 libvips/mosaicing/matrixinvert.c:328 +#: libvips/mosaicing/matrixinvert.c:353 libvips/resample/transform.c:60 +msgid "singular or near-singular matrix" msgstr "" -#: ../libvips/mosaicing/mosaic.c:206 ../libvips/mosaicing/mosaic.c:213 -msgid "Position of reference tie-point" +#: libvips/mosaicing/matrixinvert.c:406 +msgid "non-square matrix" msgstr "" -#: ../libvips/mosaicing/mosaic.c:212 -msgid "yref" +#: libvips/mosaicing/matrixinvert.c:439 +msgid "invert an matrix" msgstr "" -#: ../libvips/mosaicing/mosaic.c:219 -msgid "xsec" +#: libvips/mosaicing/matrixinvert.c:444 +msgid "An square matrix" msgstr "" -#: ../libvips/mosaicing/mosaic.c:220 ../libvips/mosaicing/mosaic.c:227 -msgid "Position of secondary tie-point" +#: libvips/mosaicing/matrixinvert.c:450 +msgid "Output matrix" msgstr "" -#: ../libvips/mosaicing/mosaic.c:226 -msgid "ysec" +#: libvips/mosaicing/merge.c:116 +msgid "merge two images" msgstr "" -#: ../libvips/mosaicing/mosaic.c:233 ../libvips/mosaicing/match.c:278 -#: ../libvips/mosaicing/mosaic1.c:570 -msgid "hwindow" +#: libvips/mosaicing/merge.c:141 +msgid "Horizontal or vertical merge" msgstr "" -#: ../libvips/mosaicing/mosaic.c:234 ../libvips/mosaicing/match.c:279 -#: ../libvips/mosaicing/mosaic1.c:571 -msgid "Half window size" +#: libvips/mosaicing/merge.c:147 +msgid "dx" msgstr "" -#: ../libvips/mosaicing/mosaic.c:240 ../libvips/mosaicing/match.c:285 -#: ../libvips/mosaicing/mosaic1.c:577 -msgid "harea" +#: libvips/mosaicing/merge.c:148 +msgid "Horizontal displacement from sec to ref" msgstr "" -#: ../libvips/mosaicing/mosaic.c:241 ../libvips/mosaicing/match.c:286 -#: ../libvips/mosaicing/mosaic1.c:578 -msgid "Half area size" +#: libvips/mosaicing/merge.c:154 +msgid "dy" msgstr "" -#: ../libvips/mosaicing/mosaic.c:254 ../libvips/mosaicing/mosaic1.c:604 -msgid "Search band" +#: libvips/mosaicing/merge.c:155 +msgid "Vertical displacement from sec to ref" msgstr "" -#: ../libvips/mosaicing/mosaic.c:255 ../libvips/mosaicing/mosaic1.c:605 -msgid "Band to search for features on" +#: libvips/mosaicing/merge.c:161 libvips/mosaicing/mosaic1.c:606 +#: libvips/mosaicing/mosaic.c:246 +msgid "Max blend" msgstr "" -#: ../libvips/mosaicing/mosaic.c:261 ../libvips/mosaicing/mosaic.c:268 -msgid "Integer offset" +#: libvips/mosaicing/merge.c:162 libvips/mosaicing/mosaic1.c:607 +#: libvips/mosaicing/mosaic.c:247 +msgid "Maximum blend size" msgstr "" -#: ../libvips/mosaicing/mosaic.c:262 ../libvips/mosaicing/mosaic.c:269 -msgid "Detected integer offset" +#: libvips/mosaicing/mosaic1.c:494 +msgid "first-order mosaic of two images" msgstr "" -#: ../libvips/mosaicing/mosaic.c:276 -msgid "Detected scale" +#: libvips/mosaicing/mosaic1.c:517 libvips/mosaicing/mosaic.c:198 +msgid "Horizontal or vertical mosaic" msgstr "" -#: ../libvips/mosaicing/mosaic.c:283 -msgid "Detected rotation" +#: libvips/mosaicing/mosaic1.c:613 libvips/mosaicing/mosaic.c:253 +msgid "Search band" msgstr "" -#: ../libvips/mosaicing/mosaic.c:289 ../libvips/mosaicing/mosaic.c:296 -msgid "First-order displacement" +#: libvips/mosaicing/mosaic1.c:614 libvips/mosaicing/mosaic.c:254 +msgid "Band to search for features on" msgstr "" -#: ../libvips/mosaicing/mosaic.c:290 ../libvips/mosaicing/mosaic.c:297 -msgid "Detected first-order displacement" +#: libvips/mosaicing/mosaic.c:175 +msgid "mosaic two images" msgstr "" -#: ../libvips/mosaicing/im_clinear.c:137 -msgid "im_invmat failed" +#: libvips/mosaicing/mosaic.c:204 +msgid "xref" msgstr "" -#: ../libvips/mosaicing/match.c:200 -msgid "first-order match of two images" +#: libvips/mosaicing/mosaic.c:205 libvips/mosaicing/mosaic.c:212 +msgid "Position of reference tie-point" msgstr "" -#: ../libvips/mosaicing/match.c:222 ../libvips/mosaicing/mosaic1.c:514 -msgid "xr1" +#: libvips/mosaicing/mosaic.c:211 +msgid "yref" msgstr "" -#: ../libvips/mosaicing/match.c:223 ../libvips/mosaicing/match.c:230 -#: ../libvips/mosaicing/mosaic1.c:515 ../libvips/mosaicing/mosaic1.c:522 -msgid "Position of first reference tie-point" +#: libvips/mosaicing/mosaic.c:218 +msgid "xsec" msgstr "" -#: ../libvips/mosaicing/match.c:229 ../libvips/mosaicing/mosaic1.c:521 -msgid "yr1" +#: libvips/mosaicing/mosaic.c:219 libvips/mosaicing/mosaic.c:226 +msgid "Position of secondary tie-point" msgstr "" -#: ../libvips/mosaicing/match.c:236 ../libvips/mosaicing/mosaic1.c:528 -msgid "xs1" +#: libvips/mosaicing/mosaic.c:225 +msgid "ysec" msgstr "" -#: ../libvips/mosaicing/match.c:237 ../libvips/mosaicing/match.c:244 -#: ../libvips/mosaicing/mosaic1.c:529 ../libvips/mosaicing/mosaic1.c:536 -msgid "Position of first secondary tie-point" +#: libvips/mosaicing/mosaic.c:260 libvips/mosaicing/mosaic.c:267 +msgid "Integer offset" msgstr "" -#: ../libvips/mosaicing/match.c:243 ../libvips/mosaicing/mosaic1.c:535 -msgid "ys1" +#: libvips/mosaicing/mosaic.c:261 libvips/mosaicing/mosaic.c:268 +msgid "Detected integer offset" msgstr "" -#: ../libvips/mosaicing/match.c:250 ../libvips/mosaicing/mosaic1.c:542 -msgid "xr2" +#: libvips/mosaicing/mosaic.c:275 +msgid "Detected scale" msgstr "" -#: ../libvips/mosaicing/match.c:251 ../libvips/mosaicing/match.c:258 -#: ../libvips/mosaicing/mosaic1.c:543 ../libvips/mosaicing/mosaic1.c:550 -msgid "Position of second reference tie-point" +#: libvips/mosaicing/mosaic.c:282 +msgid "Detected rotation" msgstr "" -#: ../libvips/mosaicing/match.c:257 ../libvips/mosaicing/mosaic1.c:549 -msgid "yr2" +#: libvips/mosaicing/mosaic.c:288 libvips/mosaicing/mosaic.c:295 +msgid "First-order displacement" msgstr "" -#: ../libvips/mosaicing/match.c:264 ../libvips/mosaicing/mosaic1.c:556 -msgid "xs2" +#: libvips/mosaicing/mosaic.c:289 libvips/mosaicing/mosaic.c:296 +msgid "Detected first-order displacement" msgstr "" -#: ../libvips/mosaicing/match.c:265 ../libvips/mosaicing/match.c:272 -#: ../libvips/mosaicing/mosaic1.c:557 ../libvips/mosaicing/mosaic1.c:564 -msgid "Position of second secondary tie-point" +#: libvips/mosaicing/remosaic.c:89 +#, c-format +msgid "file \"%s\" not found" msgstr "" -#: ../libvips/mosaicing/match.c:271 ../libvips/mosaicing/mosaic1.c:563 -msgid "ys2" +#: libvips/mosaicing/remosaic.c:117 +#, c-format +msgid "substitute image \"%s\" is not the same size as \"%s\"" msgstr "" -#: ../libvips/mosaicing/match.c:292 ../libvips/mosaicing/mosaic1.c:584 -msgid "search" +#: libvips/mosaicing/remosaic.c:160 +msgid "rebuild an mosaiced image" msgstr "" -#: ../libvips/mosaicing/match.c:293 ../libvips/mosaicing/mosaic1.c:585 -msgid "Search to improve tie-points" +#: libvips/mosaicing/remosaic.c:176 +msgid "old_str" msgstr "" -#: ../libvips/mosaicing/match.c:299 ../libvips/mosaicing/mosaic1.c:591 -#: ../libvips/resample/affine.c:568 ../libvips/resample/mapim.c:418 -#: ../libvips/resample/resize.c:384 ../libvips/resample/quadratic.c:354 -#: ../libvips/resample/similarity.c:185 -msgid "Interpolate" +#: libvips/mosaicing/remosaic.c:177 +msgid "Search for this string" msgstr "" -#: ../libvips/mosaicing/match.c:300 ../libvips/mosaicing/mosaic1.c:592 -#: ../libvips/resample/affine.c:569 ../libvips/resample/mapim.c:419 -#: ../libvips/resample/resize.c:385 ../libvips/resample/similarity.c:186 -msgid "Interpolate pixels with this" +#: libvips/mosaicing/remosaic.c:183 +msgid "new_str" msgstr "" -#: ../libvips/mosaicing/mosaic1.c:485 -msgid "first-order mosaic of two images" +#: libvips/mosaicing/remosaic.c:184 +msgid "And swap for this string" msgstr "" -#: ../libvips/resample/affine.c:486 +#: libvips/resample/affine.c:516 msgid "output coordinates out of range" msgstr "" -#: ../libvips/resample/affine.c:557 +#: libvips/resample/affine.c:640 msgid "affine transform of an image" msgstr "" -#: ../libvips/resample/affine.c:561 +#: libvips/resample/affine.c:644 msgid "Matrix" msgstr "" -#: ../libvips/resample/affine.c:562 +#: libvips/resample/affine.c:645 msgid "Transformation matrix" msgstr "" -#: ../libvips/resample/affine.c:574 +#: libvips/resample/affine.c:657 msgid "Output rect" msgstr "" -#: ../libvips/resample/affine.c:575 +#: libvips/resample/affine.c:658 msgid "Area of output to generate" msgstr "" -#: ../libvips/resample/affine.c:581 ../libvips/resample/affine.c:588 -#: ../libvips/resample/similarity.c:191 ../libvips/resample/similarity.c:198 +#: libvips/resample/affine.c:664 libvips/resample/affine.c:671 +#: libvips/resample/similarity.c:140 libvips/resample/similarity.c:147 msgid "Output offset" msgstr "" -#: ../libvips/resample/affine.c:582 ../libvips/resample/similarity.c:192 +#: libvips/resample/affine.c:665 libvips/resample/similarity.c:141 msgid "Horizontal output displacement" msgstr "" -#: ../libvips/resample/affine.c:589 ../libvips/resample/similarity.c:199 +#: libvips/resample/affine.c:672 libvips/resample/similarity.c:148 msgid "Vertical output displacement" msgstr "" -#: ../libvips/resample/affine.c:595 ../libvips/resample/affine.c:602 -#: ../libvips/resample/resize.c:368 ../libvips/resample/resize.c:375 -#: ../libvips/resample/similarity.c:205 ../libvips/resample/similarity.c:212 +#: libvips/resample/affine.c:678 libvips/resample/affine.c:685 +#: libvips/resample/resize.c:360 libvips/resample/resize.c:367 +#: libvips/resample/similarity.c:154 libvips/resample/similarity.c:161 msgid "Input offset" msgstr "" -#: ../libvips/resample/affine.c:596 ../libvips/resample/resize.c:369 -#: ../libvips/resample/similarity.c:206 +#: libvips/resample/affine.c:679 libvips/resample/resize.c:361 +#: libvips/resample/similarity.c:155 msgid "Horizontal input displacement" msgstr "" -#: ../libvips/resample/affine.c:603 ../libvips/resample/resize.c:376 -#: ../libvips/resample/similarity.c:213 +#: libvips/resample/affine.c:686 libvips/resample/resize.c:368 +#: libvips/resample/similarity.c:162 msgid "Vertical input displacement" msgstr "" -#: ../libvips/resample/shrinkv.c:344 ../libvips/resample/shrinkh.c:246 -msgid "shrink factors should be >= 1" +#: libvips/resample/bicubic.cpp:629 +msgid "bicubic interpolation (Catmull-Rom)" msgstr "" -#: ../libvips/resample/shrinkv.c:424 ../libvips/resample/reducev.cpp:895 -msgid "shrink an image vertically" +#: libvips/resample/interpolate.c:185 +msgid "VIPS interpolators" msgstr "" -#: ../libvips/resample/shrinkv.c:430 ../libvips/resample/reduce.c:141 -#: ../libvips/resample/shrink.c:137 ../libvips/resample/reducev.cpp:901 -msgid "Vshrink" +#: libvips/resample/interpolate.c:361 +msgid "nearest-neighbour interpolation" msgstr "" -#: ../libvips/resample/shrinkv.c:431 ../libvips/resample/shrinkv.c:440 -#: ../libvips/resample/reduce.c:142 ../libvips/resample/reduce.c:172 -#: ../libvips/resample/shrink.c:138 ../libvips/resample/shrink.c:161 -#: ../libvips/resample/reducev.cpp:902 ../libvips/resample/reducev.cpp:925 -msgid "Vertical shrink factor" +#: libvips/resample/interpolate.c:579 +msgid "bilinear interpolation" msgstr "" -#: ../libvips/resample/shrinkv.c:439 ../libvips/resample/reduce.c:171 -#: ../libvips/resample/shrink.c:160 ../libvips/resample/reducev.cpp:924 -msgid "Yshrink" +#: libvips/resample/lbb.cpp:872 +msgid "reduced halo bicubic" msgstr "" -#: ../libvips/resample/mapim.c:408 -msgid "resample with an mapim image" +#: libvips/resample/mapim.c:551 +msgid "resample with a map image" msgstr "" -#: ../libvips/resample/mapim.c:413 +#: libvips/resample/mapim.c:556 msgid "Index pixels with this" msgstr "" -#: ../libvips/resample/resize.c:331 -msgid "resize an image" -msgstr "" - -#: ../libvips/resample/resize.c:337 -msgid "Scale factor" -msgstr "" - -#: ../libvips/resample/resize.c:338 -msgid "Scale image by this factor" +#: libvips/resample/nohalo.cpp:1551 +msgid "edge sharpening resampler with halo reduction" msgstr "" -#: ../libvips/resample/resize.c:344 -msgid "Vertical scale factor" +#: libvips/resample/quadratic.c:269 +msgid "coefficient matrix must have width 2" msgstr "" -#: ../libvips/resample/resize.c:345 -msgid "Vertical scale image by this factor" +#: libvips/resample/quadratic.c:291 +msgid "coefficient matrix must have height 1, 3, 4 or 6" msgstr "" -#: ../libvips/resample/resize.c:351 ../libvips/resample/reduce.c:148 -#: ../libvips/resample/reduceh.cpp:575 ../libvips/resample/reducev.cpp:908 -msgid "Kernel" +#: libvips/resample/quadratic.c:341 +msgid "resample an image with a quadratic transform" msgstr "" -#: ../libvips/resample/resize.c:352 ../libvips/resample/reduce.c:149 -#: ../libvips/resample/reduceh.cpp:576 ../libvips/resample/reducev.cpp:909 -msgid "Resampling kernel" +#: libvips/resample/quadratic.c:345 +msgid "Coeff" msgstr "" -#: ../libvips/resample/resize.c:358 ../libvips/resample/reduce.c:155 -#: ../libvips/resample/reduceh.cpp:582 ../libvips/resample/reducev.cpp:915 -msgid "Centre" +#: libvips/resample/quadratic.c:346 +msgid "Coefficient matrix" msgstr "" -#: ../libvips/resample/resize.c:359 ../libvips/resample/reduce.c:156 -#: ../libvips/resample/reduceh.cpp:583 ../libvips/resample/reducev.cpp:916 -msgid "Use centre sampling convention" +#: libvips/resample/quadratic.c:352 +msgid "Interpolate values with this" msgstr "" -#: ../libvips/resample/reduce.c:128 +#: libvips/resample/reduce.c:199 msgid "reduce an image" msgstr "" -#: ../libvips/resample/reduce.c:134 ../libvips/resample/shrinkh.c:326 -#: ../libvips/resample/shrink.c:144 ../libvips/resample/reduceh.cpp:568 +#: libvips/resample/reduce.c:205 libvips/resample/reduceh.cpp:586 +#: libvips/resample/shrink.c:149 libvips/resample/shrinkh.c:353 msgid "Hshrink" msgstr "" -#: ../libvips/resample/reduce.c:135 ../libvips/resample/reduce.c:165 -#: ../libvips/resample/shrinkh.c:327 ../libvips/resample/shrinkh.c:336 -#: ../libvips/resample/shrink.c:145 ../libvips/resample/shrink.c:154 -#: ../libvips/resample/reduceh.cpp:569 ../libvips/resample/reduceh.cpp:592 +#: libvips/resample/reduce.c:206 libvips/resample/reduce.c:236 +#: libvips/resample/reduceh.cpp:587 libvips/resample/reduceh.cpp:610 +#: libvips/resample/shrink.c:150 libvips/resample/shrink.c:166 +#: libvips/resample/shrinkh.c:354 libvips/resample/shrinkh.c:370 msgid "Horizontal shrink factor" msgstr "" -#: ../libvips/resample/reduce.c:164 ../libvips/resample/shrinkh.c:335 -#: ../libvips/resample/shrink.c:153 ../libvips/resample/reduceh.cpp:591 -msgid "Xshrink" -msgstr "" - -#: ../libvips/resample/shrinkh.c:320 ../libvips/resample/reduceh.cpp:562 -msgid "shrink an image horizontally" -msgstr "" - -#: ../libvips/resample/resample.c:128 -msgid "resample operations" -msgstr "" - -#: ../libvips/resample/quadratic.c:270 -msgid "coefficient matrix must have width 2" -msgstr "" - -#: ../libvips/resample/quadratic.c:292 -msgid "coefficient matrix must have height 1, 3, 4 or 6" -msgstr "" - -#: ../libvips/resample/quadratic.c:344 -msgid "resample an image with a quadratic transform" +#: libvips/resample/reduce.c:212 libvips/resample/reducev.cpp:1070 +#: libvips/resample/shrink.c:142 libvips/resample/shrinkv.c:427 +msgid "Vshrink" msgstr "" -#: ../libvips/resample/quadratic.c:348 -msgid "Coeff" +#: libvips/resample/reduce.c:213 libvips/resample/reduce.c:243 +#: libvips/resample/reducev.cpp:1071 libvips/resample/reducev.cpp:1094 +#: libvips/resample/shrink.c:143 libvips/resample/shrink.c:173 +#: libvips/resample/shrinkv.c:428 libvips/resample/shrinkv.c:444 +msgid "Vertical shrink factor" msgstr "" -#: ../libvips/resample/quadratic.c:349 -msgid "Coefficient matrix" +#: libvips/resample/reduce.c:219 libvips/resample/reduceh.cpp:593 +#: libvips/resample/reducev.cpp:1077 libvips/resample/resize.c:343 +msgid "Kernel" msgstr "" -#: ../libvips/resample/quadratic.c:355 -msgid "Interpolate values with this" +#: libvips/resample/reduce.c:220 libvips/resample/reduceh.cpp:594 +#: libvips/resample/reducev.cpp:1078 libvips/resample/resize.c:344 +msgid "Resampling kernel" msgstr "" -#: ../libvips/resample/thumbnail.c:436 -#, c-format -msgid "unable to import with embedded profile: %s" +#: libvips/resample/reduce.c:226 libvips/resample/reduceh.cpp:600 +#: libvips/resample/reducev.cpp:1084 libvips/resample/resize.c:350 +msgid "Gap" msgstr "" -#: ../libvips/resample/thumbnail.c:516 -msgid "thumbnail generation" +#: libvips/resample/reduce.c:227 libvips/resample/reduceh.cpp:601 +#: libvips/resample/reducev.cpp:1085 libvips/resample/resize.c:351 +msgid "Reducing gap" msgstr "" -#: ../libvips/resample/thumbnail.c:526 -msgid "Target width" +#: libvips/resample/reduce.c:235 libvips/resample/reduceh.cpp:609 +#: libvips/resample/shrink.c:165 libvips/resample/shrinkh.c:369 +msgid "Xshrink" msgstr "" -#: ../libvips/resample/thumbnail.c:527 -msgid "Size to this width" +#: libvips/resample/reduce.c:242 libvips/resample/reducev.cpp:1093 +#: libvips/resample/shrink.c:172 libvips/resample/shrinkv.c:443 +msgid "Yshrink" msgstr "" -#: ../libvips/resample/thumbnail.c:533 -msgid "Target height" +#: libvips/resample/reduce.c:251 libvips/resample/reduceh.cpp:618 +#: libvips/resample/reducev.cpp:1102 libvips/resample/resize.c:384 +msgid "Centre" msgstr "" -#: ../libvips/resample/thumbnail.c:534 -msgid "Size to this height" +#: libvips/resample/reduce.c:252 libvips/resample/reduceh.cpp:619 +#: libvips/resample/reducev.cpp:1103 libvips/resample/resize.c:385 +msgid "Use centre sampling convention" msgstr "" -#: ../libvips/resample/thumbnail.c:540 -msgid "size" +#: libvips/resample/reduceh.cpp:414 libvips/resample/reducev.cpp:848 +msgid "reduce factor should be >= 1.0" msgstr "" -#: ../libvips/resample/thumbnail.c:541 -msgid "Only upsize, only downsize, or both" +#: libvips/resample/reduceh.cpp:437 libvips/resample/reducev.cpp:870 +msgid "reduce gap should be >= 1.0" msgstr "" -#: ../libvips/resample/thumbnail.c:547 -msgid "Auto rotate" +#: libvips/resample/reduceh.cpp:467 libvips/resample/reducev.cpp:900 +msgid "reduce factor too large" msgstr "" -#: ../libvips/resample/thumbnail.c:548 -msgid "Use orientation tags to rotate image upright" +#: libvips/resample/reduceh.cpp:580 libvips/resample/shrinkh.c:347 +msgid "shrink an image horizontally" msgstr "" -#: ../libvips/resample/thumbnail.c:554 -msgid "Crop" +#: libvips/resample/reducev.cpp:1064 libvips/resample/shrinkv.c:421 +msgid "shrink an image vertically" msgstr "" -#: ../libvips/resample/thumbnail.c:555 -msgid "Reduce to fill target rectangle, then crop" +#: libvips/resample/resample.c:136 +msgid "resample operations" msgstr "" -#: ../libvips/resample/thumbnail.c:561 -msgid "Linear" +#: libvips/resample/resize.c:323 +msgid "resize an image" msgstr "" -#: ../libvips/resample/thumbnail.c:562 -msgid "Reduce in linear light" +#: libvips/resample/resize.c:329 +msgid "Scale factor" msgstr "" -#: ../libvips/resample/thumbnail.c:568 -msgid "Import profile" +#: libvips/resample/resize.c:330 +msgid "Scale image by this factor" msgstr "" -#: ../libvips/resample/thumbnail.c:569 -msgid "Fallback import profile" +#: libvips/resample/resize.c:336 +msgid "Vertical scale factor" msgstr "" -#: ../libvips/resample/thumbnail.c:575 -msgid "Export profile" +#: libvips/resample/resize.c:337 +msgid "Vertical scale image by this factor" msgstr "" -#: ../libvips/resample/thumbnail.c:576 -msgid "Fallback export profile" +#: libvips/resample/shrink.c:133 +msgid "shrink an image" msgstr "" -#: ../libvips/resample/thumbnail.c:663 -msgid "generate thumbnail from file" +#: libvips/resample/shrink.c:156 libvips/resample/shrinkh.c:360 +#: libvips/resample/shrinkv.c:434 +msgid "Ceil" msgstr "" -#: ../libvips/resample/thumbnail.c:670 -msgid "Filename to read from" +#: libvips/resample/shrink.c:157 libvips/resample/shrinkh.c:361 +#: libvips/resample/shrinkv.c:435 +msgid "Round-up output dimensions" msgstr "" -#: ../libvips/resample/thumbnail.c:830 -msgid "generate thumbnail from buffer" +#: libvips/resample/shrinkh.c:283 libvips/resample/shrinkv.c:327 +msgid "shrink factors should be >= 1" msgstr "" -#: ../libvips/resample/shrink.c:128 -msgid "shrink an image" +#: libvips/resample/similarity.c:123 +msgid "base similarity transform" msgstr "" -#: ../libvips/resample/similarity.c:167 +#: libvips/resample/similarity.c:197 msgid "similarity transform of an image" msgstr "" -#: ../libvips/resample/similarity.c:172 +#: libvips/resample/similarity.c:201 msgid "Scale by this factor" msgstr "" -#: ../libvips/resample/similarity.c:179 -msgid "Rotate anticlockwise by this many degrees" +#: libvips/resample/similarity.c:208 libvips/resample/similarity.c:277 +msgid "Rotate clockwise by this many degrees" msgstr "" -#: ../libvips/resample/interpolate.c:183 -msgid "VIPS interpolators" -msgstr "" - -#: ../libvips/resample/interpolate.c:359 -msgid "nearest-neighbour interpolation" +#: libvips/resample/similarity.c:273 +msgid "rotate an image by a number of degrees" msgstr "" -#: ../libvips/resample/interpolate.c:556 -msgid "bilinear interpolation" +#: libvips/resample/thumbnail.c:959 +msgid "thumbnail generation" msgstr "" -#: ../libvips/video/im_video_test.c:52 -msgid "error requested" +#: libvips/resample/thumbnail.c:974 +msgid "Target width" msgstr "" -#: ../tools/vips.c:154 -#, c-format -msgid "'%s' is not the name of a vips class" +#: libvips/resample/thumbnail.c:975 +msgid "Size to this width" msgstr "" -#: ../tools/vips.c:170 -msgid "list objects" +#: libvips/resample/thumbnail.c:981 +msgid "Target height" msgstr "" -#: ../tools/vips.c:171 -msgid "BASE-NAME" +#: libvips/resample/thumbnail.c:982 +msgid "Size to this height" msgstr "" -#: ../tools/vips.c:173 -msgid "load PLUGIN" +#: libvips/resample/thumbnail.c:989 +msgid "Only upsize, only downsize, or both" msgstr "" -#: ../tools/vips.c:174 -msgid "PLUGIN" +#: libvips/resample/thumbnail.c:995 +msgid "No rotate" msgstr "" -#: ../tools/vips.c:176 -msgid "print version" +#: libvips/resample/thumbnail.c:996 +msgid "Don't use orientation tags to rotate image upright" msgstr "" -#: ../tools/vips.c:219 -#, c-format -msgid "no package or function \"%s\"" +#: libvips/resample/thumbnail.c:1002 +msgid "Crop" msgstr "" -#: ../tools/vips.c:1000 -msgid "list classes|packages|all|package-name|operation-name" +#: libvips/resample/thumbnail.c:1003 +msgid "Reduce to fill target rectangle, then crop" msgstr "" -#: ../tools/vips.c:1002 -msgid "generate headers for C++ binding" +#: libvips/resample/thumbnail.c:1009 +msgid "Linear" msgstr "" -#: ../tools/vips.c:1004 -msgid "generate bodies for C++ binding" +#: libvips/resample/thumbnail.c:1010 +msgid "Reduce in linear light" msgstr "" -#: ../tools/vips.c:1006 -msgid "generate links for vips/bin" +#: libvips/resample/thumbnail.c:1016 +msgid "Import profile" msgstr "" -#: ../tools/vips.c:1008 -msgid "list possible actions" +#: libvips/resample/thumbnail.c:1017 +msgid "Fallback import profile" msgstr "" -#: ../tools/vips.c:1027 -msgid "execute vips operation OPER" +#: libvips/resample/thumbnail.c:1023 +msgid "Export profile" msgstr "" -#: ../tools/vips.c:1070 -msgid "Operation help" +#: libvips/resample/thumbnail.c:1024 +msgid "Fallback export profile" msgstr "" -#: ../tools/vips.c:1116 -msgid "[ACTION] [OPTIONS] [PARAMETERS] - VIPS driver program" +#: libvips/resample/thumbnail.c:1050 +msgid "Auto rotate" msgstr "" -#: ../tools/vips.c:1300 -#, c-format -msgid "unknown action \"%s\"" +#: libvips/resample/thumbnail.c:1051 +msgid "Use orientation tags to rotate image upright" msgstr "" -#: ../tools/vipsedit.c:83 -msgid "tag file as big or little-endian" +#: libvips/resample/thumbnail.c:1192 +msgid "generate thumbnail from file" msgstr "" -#: ../tools/vipsedit.c:85 -msgid "set width to N pixels" +#: libvips/resample/thumbnail.c:1199 +msgid "Filename to read from" msgstr "" -#: ../tools/vipsedit.c:87 -msgid "set height to N pixels" +#: libvips/resample/thumbnail.c:1439 +msgid "generate thumbnail from buffer" msgstr "" -#: ../tools/vipsedit.c:89 -msgid "set Bands to N" -msgstr "" +#: libvips/resample/thumbnail.c:1452 libvips/resample/thumbnail.c:1665 +#, fuzzy +msgid "Extra options" +msgstr "colour operations" -#: ../tools/vipsedit.c:91 -msgid "set BandFmt to F (eg. uchar, float)" +#: libvips/resample/thumbnail.c:1453 libvips/resample/thumbnail.c:1666 +msgid "Options that are passed on to the underlying loader" msgstr "" -#: ../tools/vipsedit.c:93 -msgid "set interpretation to I (eg. xyz)" +#: libvips/resample/thumbnail.c:1652 +msgid "generate thumbnail from source" msgstr "" -#: ../tools/vipsedit.c:95 -msgid "set Coding to C (eg. labq)" +#: libvips/resample/thumbnail.c:1776 +msgid "generate thumbnail from image" msgstr "" -#: ../tools/vipsedit.c:97 -msgid "set Xres to R pixels/mm" +#: libvips/resample/vsqbs.cpp:378 +msgid "B-Splines with antialiasing smoothing" msgstr "" -#: ../tools/vipsedit.c:99 -msgid "set Yres to R pixels/mm" +#: tools/vips.c:166 +#, c-format +msgid "'%s' is not the name of a vips class" msgstr "" -#: ../tools/vipsedit.c:101 -msgid "set Xoffset to N pixels" +#: tools/vips.c:282 +#, c-format +msgid "'%s' is not the name of a vips operation" msgstr "" -#: ../tools/vipsedit.c:103 -msgid "set Yoffset to N pixels" +#: tools/vips.c:355 +#, c-format +msgid "no package or function \"%s\"" msgstr "" -#: ../tools/vipsedit.c:105 -msgid "replace extension block with stdin" +#: tools/vips.c:584 +msgid "execute vips operation OPER" msgstr "" -#: ../tools/vipsedit.c:107 -msgid "set Xsize to N (deprecated, use width)" +#: tools/vips.c:627 +msgid "Operation help" msgstr "" -#: ../tools/vipsedit.c:109 -msgid "set Ysize to N (deprecated, use height)" +#: tools/vips.c:706 +msgid "[ACTION] [OPTIONS] [PARAMETERS] - VIPS driver program" msgstr "" -#: ../tools/vipsedit.c:111 -msgid "set Type to T (deprecated, use interpretation)" +#: tools/vips.c:916 +#, c-format +msgid "unknown action \"%s\"" msgstr "" -#: ../tools/vipsedit.c:122 +#: tools/vipsedit.c:129 #, c-format msgid "'%s' is not a positive integer" msgstr "" -#: ../tools/vipsedit.c:135 +#: tools/vipsedit.c:142 msgid "unable to start VIPS" msgstr "" -#: ../tools/vipsedit.c:147 +#: tools/vipsedit.c:165 msgid "vipsedit - edit vips file header" msgstr "" -#: ../tools/vipsedit.c:175 +#: tools/vipsedit.c:193 #, c-format msgid "usage: %s [OPTION...] vips-file\n" msgstr "" -#: ../tools/vipsedit.c:182 +#: tools/vipsedit.c:200 #, c-format msgid "could not open image %s" msgstr "" -#: ../tools/vipsedit.c:185 +#: tools/vipsedit.c:206 #, c-format msgid "could not read VIPS header for %s" msgstr "" -#: ../tools/vipsedit.c:194 +#: tools/vipsedit.c:216 #, c-format msgid "bad endian-ness %s, should be 'big' or 'little'" msgstr "" -#: ../tools/vipsedit.c:207 +#: tools/vipsedit.c:230 #, c-format msgid "bad format %s" msgstr "" -#: ../tools/vipsedit.c:215 +#: tools/vipsedit.c:244 #, c-format msgid "bad interpretation %s" msgstr "" -#: ../tools/vipsedit.c:223 +#: tools/vipsedit.c:254 #, c-format msgid "bad coding %s" msgstr "" -#: ../tools/vipsedit.c:236 +#: tools/vipsedit.c:268 #, c-format msgid "could not seek on %s" msgstr "" -#: ../tools/vipsedit.c:239 +#: tools/vipsedit.c:271 #, c-format msgid "could not write to %s" msgstr "" -#: ../tools/vipsedit.c:246 +#: tools/vipsedit.c:278 msgid "could not get ext data" msgstr "" -#: ../tools/vipsedit.c:255 +#: tools/vipsedit.c:287 msgid "could not set extension" msgstr "" -#: ../tools/vipsheader.c:88 -msgid "show all fields" -msgstr "" - -#: ../tools/vipsheader.c:90 -msgid "" -"print value of FIELD (\"getext\" reads extension block, \"Hist\" reads image " -"history)" -msgstr "" - -#: ../tools/vipsheader.c:181 +#: tools/vipsheader.c:221 msgid "- print image header" msgstr "" -#: ../tools/vipsthumbnail.c:136 -msgid "shrink to SIZE or to WIDTHxHEIGHT" -msgstr "" - -#: ../tools/vipsthumbnail.c:137 -msgid "SIZE" -msgstr "" - -#: ../tools/vipsthumbnail.c:140 -msgid "set output to FORMAT" -msgstr "" - -#: ../tools/vipsthumbnail.c:141 ../tools/vipsthumbnail.c:145 -msgid "FORMAT" -msgstr "" - -#: ../tools/vipsthumbnail.c:144 -msgid "set output format string to FORMAT" -msgstr "" - -#: ../tools/vipsthumbnail.c:148 -msgid "export with PROFILE" -msgstr "" - -#: ../tools/vipsthumbnail.c:149 ../tools/vipsthumbnail.c:153 -msgid "PROFILE" +#: tools/vipsthumbnail.c:447 +msgid "bad geometry spec" msgstr "" -#: ../tools/vipsthumbnail.c:152 -msgid "import untagged images with PROFILE" -msgstr "" - -#: ../tools/vipsthumbnail.c:156 -msgid "process in linear space" -msgstr "" - -#: ../tools/vipsthumbnail.c:159 -msgid "crop exactly to SIZE" -msgstr "" - -#: ../tools/vipsthumbnail.c:162 -msgid "auto-rotate" -msgstr "" - -#: ../tools/vipsthumbnail.c:165 -msgid "delete profile from exported image" -msgstr "" - -#: ../tools/vipsthumbnail.c:169 ../tools/vipsthumbnail.c:172 -#: ../tools/vipsthumbnail.c:175 ../tools/vipsthumbnail.c:178 -#: ../tools/vipsthumbnail.c:181 -msgid "(deprecated, does nothing)" -msgstr "" - -#: ../tools/vipsthumbnail.c:375 +#: tools/vipsthumbnail.c:516 msgid "- thumbnail generator" msgstr "" -#: ../tools/vipsthumbnail.c:406 -msgid "auto-rotate disabled: libvips built without exif support" -msgstr "" - -#: ../libvips/resample/reduceh.cpp:457 -msgid "reduce factors should be >= 1" -msgstr "" - -#: ../libvips/resample/reduceh.cpp:471 ../libvips/resample/reducev.cpp:850 -msgid "reduce factor too large" -msgstr "" - -#: ../libvips/resample/bicubic.cpp:639 -msgid "bicubic interpolation (Catmull-Rom)" -msgstr "" - -#: ../libvips/resample/vsqbs.cpp:405 -msgid "B-Splines with antialiasing smoothing" -msgstr "" - -#: ../libvips/resample/nohalo.cpp:1586 -msgid "edge sharpening resampler with halo reduction" -msgstr "" - -#: ../libvips/resample/lbb.cpp:865 -msgid "reduced halo bicubic" -msgstr "" - -#: ../libvips/resample/reducev.cpp:839 -msgid "reduce factor should be >= 1" -msgstr "" +#~ msgid "Neither global nor local color map" +#~ msgstr "Neither global nor local colour map" diff --git a/po/malkovich.po b/po/malkovich.po index b3ac40294b..25dcebc88b 100644 --- a/po/malkovich.po +++ b/po/malkovich.po @@ -386,10 +386,6 @@ msgstr "" msgid "can only pyramid LABQ and non-complex images" msgstr "" -#: libsrc/conversion/im_vips2tiff.c:1372 -msgid "can't have 1-bit JPEG -- disabling JPEG" -msgstr "" - #: libsrc/conversion/im_vips2tiff.c:1529 #, fuzzy msgid "unknown coding type" diff --git a/suppressions/lsan.supp b/suppressions/lsan.supp index 5e6298de26..6eba8040cc 100644 --- a/suppressions/lsan.supp +++ b/suppressions/lsan.supp @@ -21,6 +21,3 @@ leak:___kmp_allocate # TODO: Does this requires calling heif_deinit()? leak:x265::x265_malloc leak:x265_12bit::x265_malloc - -# TODO: Remove after PR https://github.com/libvips/pyvips/pull/497 -leak:vips_filename_get_filename diff --git a/test/meson.build b/test/meson.build index 92b79d782e..90dc7e7779 100644 --- a/test/meson.build +++ b/test/meson.build @@ -89,3 +89,14 @@ test('webpsave_timeout', depends: test_timeout_webpsave, workdir: meson.current_build_dir(), ) + +test_timeout_gifsave = executable('test_timeout_gifsave', + 'test_timeout_gifsave.c', + dependencies: libvips_dep, +) + +test('gifsave_timeout', + test_timeout_gifsave, + depends: test_timeout_gifsave, + workdir: meson.current_build_dir(), +) diff --git a/test/test-suite/images/sample-xyb.jpg b/test/test-suite/images/sample-xyb.jpg index 6e802dc85b..376d92557b 100644 Binary files a/test/test-suite/images/sample-xyb.jpg and b/test/test-suite/images/sample-xyb.jpg differ diff --git a/test/test-suite/test_foreign.py b/test/test-suite/test_foreign.py index 57c8b79d1c..a1c65277f6 100644 --- a/test/test-suite/test_foreign.py +++ b/test/test-suite/test_foreign.py @@ -27,6 +27,14 @@ def setup_class(cls): im = pyvips.Image.new_from_file(GIF_FILE) cls.onebit = im[1] > 128 + all = [cls.mono, cls.colour, cls.cmyk] + # and alpha variants of all of them + alpha = [x.bandjoin(255) for x in all] + # and with a second alpha + alpha2 = [x.bandjoin(255) for x in alpha] + + cls.all = all + alpha + alpha2 + @classmethod def teardown_class(cls): shutil.rmtree(cls.tempdir, ignore_errors=True) @@ -35,6 +43,7 @@ def teardown_class(cls): cls.mono = None cls.cmyk = None cls.onebit = None + cls.all = None # we have test files for formats which have a clear standard def file_loader(self, loader, test_file, validate): @@ -148,6 +157,10 @@ def jpeg_valid(im): self.save_load_buffer("jpegsave_buffer", "jpegload_buffer", self.colour, 80) + for image in self.all: + target = pyvips.Target.new_to_memory() + image.jpegsave_target(target) + # see if we have exif parsing: our test image has this field x = pyvips.Image.new_from_file(JPEG_FILE) if x.get_typeof("exif-ifd0-Orientation") != 0: @@ -422,6 +435,10 @@ def png_valid(im): self.save_load_file(".png", "[interlace]", self.colour) self.save_load_file(".png", "[interlace]", self.mono) + for image in self.all: + target = pyvips.Target.new_to_memory() + image.pngsave_target(target) + def png_indexed_valid(im): a = im(10, 10) assert_almost_equal_objects(a, [148.0, 131.0, 109.0]) @@ -432,7 +449,8 @@ def png_indexed_valid(im): assert im.get("palette") == 1 self.file_loader("pngload", PNG_INDEXED_FILE, png_indexed_valid) - self.buffer_loader("pngload_buffer", PNG_INDEXED_FILE, png_indexed_valid) + self.buffer_loader("pngload_buffer", + PNG_INDEXED_FILE, png_indexed_valid) # size of a regular mono PNG len_mono = len(self.mono.write_to_buffer(".png")) @@ -482,7 +500,8 @@ def png_indexed_valid(im): "exif-ifd0-ImageDescription", "test description") im2 = pyvips.Image.new_from_buffer( im1.write_to_buffer(".png"), "") - assert im2.get("exif-ifd0-ImageDescription").startswith("test description") + assert im2.get("exif-ifd0-ImageDescription") \ + .startswith("test description") @skip_if_no("tiffload") def test_tiff(self): @@ -497,6 +516,10 @@ def tiff_valid(im): self.file_loader("tiffload", TIF_FILE, tiff_valid) self.buffer_loader("tiffload_buffer", TIF_FILE, tiff_valid) + for image in self.all: + target = pyvips.Target.new_to_memory() + image.tiffsave_target(target) + def tiff1_valid(im): a = im(127, 0) assert_almost_equal_objects(a, [0.0]) @@ -662,6 +685,15 @@ def tiff_subsampled_valid(im): assert x1.xres == 100 assert x1.yres == 200 + if sys.platform == "darwin": + with open(TIF2_FILE, 'rb') as f: + buf = bytearray(f.read()) + buf = buf[:-4] + source = pyvips.Source.new_from_memory(buf) + im = pyvips.Image.tiffload_source(source, fail_on="warning") + with pytest.raises(Exception) as e_info: + im.avg() > 0 + # OME support in 8.5 x = pyvips.Image.new_from_file(OME_FILE) assert x.width == 439 @@ -1003,6 +1035,7 @@ def nifti_valid(im): @skip_if_no("openslideload") def test_openslideload(self): + def openslide_valid(im): a = im(10, 10) assert_almost_equal_objects(a, [244, 250, 243, 255]) @@ -1058,7 +1091,9 @@ def gif_valid(im): assert x2.get("bits-per-sample") == 4 assert x2.get("palette") == 1 - x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1) + x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, + n=-1, + access="sequential") # our test gif has delay 0 for the first frame set in error assert x2.get("delay") == [0, 50, 50, 50, 50] assert x2.get("loop") == 32761 @@ -1189,12 +1224,22 @@ def svg_valid(im): assert im.width == 10 assert im.height == 10 + # Custom CSS stylesheet + im = pyvips.Image.new_from_file(SVG_FILE) + assert im.avg() < 5 + im = pyvips.Image.new_from_file(SVG_FILE, stylesheet=b'path{stroke:#f00;stroke-width:1em;}') + assert im.avg() > 5 + def test_csv(self): self.save_load("%s.csv", self.mono) def test_matrix(self): self.save_load("%s.mat", self.mono) + for image in self.all: + target = pyvips.Target.new_to_memory() + image.matrixsave_target(target) + @skip_if_no("ppmload") def test_ppm(self): self.save_load("%s.ppm", self.colour) @@ -1426,9 +1471,6 @@ def heif_valid(im): im = pyvips.Image.heifload(AVIF_FILE_HUGE) assert im.avg() == 0.0 - im = pyvips.Image.heifload(AVIF_FILE_HUGE, unlimited=True) - assert im.avg() == 0.0 - @skip_if_no("heifsave") def test_avifsave(self): self.save_load_buffer("heifsave_buffer", "heifload_buffer", diff --git a/test/test-suite/test_resample.py b/test/test-suite/test_resample.py index 55c92eb53c..6ac8704477 100644 --- a/test/test-suite/test_resample.py +++ b/test/test-suite/test_resample.py @@ -241,7 +241,7 @@ def test_thumbnail(self): @pytest.mark.skipif(not pyvips.at_least_libvips(8, 5), reason="requires libvips >= 8.5") def test_thumbnail_icc(self): - im = pyvips.Image.thumbnail(JPEG_FILE_XYB, 442, export_profile="srgb", intent="perceptual") + im = pyvips.Image.thumbnail(JPEG_FILE_XYB, 442, output_profile="srgb") assert im.width == 290 assert im.height == 442 @@ -250,7 +250,7 @@ def test_thumbnail_icc(self): # the colour distance should not deviate too much # (i.e. the embedded profile should not be ignored) im_orig = pyvips.Image.new_from_file(JPEG_FILE) - assert im_orig.de00(im).max() < 11 + assert im_orig.de00(im).max() < 10 def test_similarity(self): im = pyvips.Image.new_from_file(JPEG_FILE) diff --git a/test/test_timeout_gifsave.c b/test/test_timeout_gifsave.c new file mode 100644 index 0000000000..7fa1253411 --- /dev/null +++ b/test/test_timeout_gifsave.c @@ -0,0 +1,47 @@ +#include + +#define TIMEOUT_SECONDS 2 + +static void +eval_callback(VipsImage *image, VipsProgress *progress, gboolean *is_killed) +{ + if (progress->run >= TIMEOUT_SECONDS) { + *is_killed = TRUE; + vips_image_set_kill(image, TRUE); + } +} + +int +main(int argc, char **argv) +{ + VipsImage *im; + void *buf; + size_t len; + gboolean is_killed = FALSE; + + if (VIPS_INIT(argv[0])) + vips_error_exit(NULL); + + if (!vips_type_find("VipsOperation", "gifsave")) + /* gifsave not available, skip test with return code 77. + */ + return 77; + + if (vips_gaussnoise(&im, 8192, 8192, NULL)) + vips_error_exit(NULL); + + vips_image_set_progress(im, TRUE); + g_signal_connect(im, "eval", + G_CALLBACK(eval_callback), &is_killed); + + buf = NULL; + if (vips_gifsave_buffer(im, &buf, &len, NULL)) + printf("error return from vips_gifsave_buffer()\n"); + + g_object_unref(im); + if (buf) + g_free(buf); + g_assert(is_killed); + + return 0; +} diff --git a/tools/vips.c b/tools/vips.c index 5abc6193a1..a8fa16c43d 100644 --- a/tools/vips.c +++ b/tools/vips.c @@ -312,7 +312,7 @@ static GOptionEntry main_option[] = { { NULL } }; -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED typedef void *(*map_name_fn)(im_function *); /* Loop over a package. @@ -379,7 +379,7 @@ list_function(im_function *func) static int print_list(int argc, char **argv) { -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED if (!argv[0] || strcmp(argv[0], "packages") == 0) im_map_packages((VSListMap2Fn) list_package, NULL); else if (strcmp(argv[0], "classes") == 0) @@ -394,7 +394,7 @@ print_list(int argc, char **argv) list_class, NULL); } else { -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED if (map_name(argv[0], list_function)) vips_error_exit("unknown package \"%s\"", argv[0]); #else @@ -405,7 +405,7 @@ print_list(int argc, char **argv) return 0; } -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED /* Print "ln -s" lines for this package. */ static void * @@ -457,7 +457,7 @@ isvips(const char *name) return vips_isprefix("vips", name); } -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED /* Print a usage string from an im_function descriptor. */ static void @@ -552,13 +552,13 @@ static GOptionEntry empty_options[] = { }; static ActionEntry actions[] = { -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED { "list", N_("list classes|packages|all|package-name|operation-name"), #else { "list", N_("list classes|all|operation-name"), #endif &empty_options[0], print_list }, -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED { "links", N_("generate links for vips/bin"), &empty_options[0], print_links }, #endif @@ -661,7 +661,7 @@ main(int argc, char **argv) GOptionGroup *main_group; GOptionGroup *group; VipsOperation *operation; -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED im_function *fn; #endif int i, j; @@ -760,8 +760,8 @@ main(int argc, char **argv) ; if (main_option_plugin) { -#if ENABLE_MODULES -#if ENABLE_DEPRECATED +#ifdef ENABLE_MODULES +#ifdef ENABLE_DEPRECATED if (!im_load_plugin(main_option_plugin)) vips_error_exit(NULL); #else /*!ENABLE_DEPRECATED*/ @@ -774,8 +774,8 @@ main(int argc, char **argv) } #endif /*ENABLE_DEPRECATED*/ #else /*!ENABLE_MODULES*/ - g_warning("%s", _("plugin load disabled: " - "libvips built without modules support")); + g_warning("plugin load disabled: " + "libvips built without modules support"); #endif /*ENABLE_MODULES*/ } @@ -843,7 +843,7 @@ main(int argc, char **argv) break; } -#if ENABLE_DEPRECATED +#ifdef ENABLE_DEPRECATED /* Could be a vips7 im_function. We need to test for vips7 first, * since we don't want to use the vips7 compat wrappers in vips8 * unless we have to. They don't support all args types. diff --git a/tools/vipsthumbnail.c b/tools/vipsthumbnail.c index ce90bee00a..852cde250c 100644 --- a/tools/vipsthumbnail.c +++ b/tools/vipsthumbnail.c @@ -105,6 +105,8 @@ * 2/10/20 * - support "stdin" as a magic input filename for thumbnail_source * - support ".suffix" as a magic output format for stdout write + * 30/4/25 + * - rename import/export profile args as input/oputput */ #ifdef HAVE_CONFIG_H @@ -131,8 +133,8 @@ static int thumbnail_width = 128; static int thumbnail_height = 128; static VipsSize size_restriction = VIPS_SIZE_BOTH; static char *output_format = "tn_%s.jpg"; -static char *export_profile = NULL; -static char *import_profile = NULL; +static char *output_profile = NULL; +static char *input_profile = NULL; static gboolean linear_processing = FALSE; static gboolean crop_image = FALSE; static gboolean no_rotate_image = FALSE; @@ -159,12 +161,12 @@ static GOptionEntry options[] = { G_OPTION_ARG_STRING, &output_format, N_("output to FORMAT"), N_("FORMAT") }, - { "export-profile", 'e', 0, - G_OPTION_ARG_FILENAME, &export_profile, + { "output-profile", 0, 0, + G_OPTION_ARG_FILENAME, &output_profile, N_("export with PROFILE"), N_("PROFILE") }, - { "import-profile", 'i', 0, - G_OPTION_ARG_FILENAME, &import_profile, + { "input-profile", 0, 0, + G_OPTION_ARG_FILENAME, &input_profile, N_("import untagged images with PROFILE"), N_("PROFILE") }, { "linear", 'a', 0, @@ -187,18 +189,28 @@ static GOptionEntry options[] = { { "version", 'v', 0, G_OPTION_ARG_NONE, &version, N_("print version"), NULL }, - { "format", 'f', G_OPTION_FLAG_HIDDEN, - G_OPTION_ARG_STRING, &output_format, - N_("set output format string to FORMAT"), - N_("FORMAT") }, + /* All deprecated. + */ + { "export-profile", 'e', G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_FILENAME, &output_profile, + N_("export with PROFILE"), + N_("PROFILE") }, + { "import-profile", 'i', G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_FILENAME, &input_profile, + N_("import untagged images with PROFILE"), + N_("PROFILE") }, { "eprofile", 0, G_OPTION_FLAG_HIDDEN, - G_OPTION_ARG_FILENAME, &export_profile, + G_OPTION_ARG_FILENAME, &output_profile, N_("export with PROFILE"), N_("PROFILE") }, { "iprofile", 0, G_OPTION_FLAG_HIDDEN, - G_OPTION_ARG_FILENAME, &import_profile, + G_OPTION_ARG_FILENAME, &input_profile, N_("import untagged images with PROFILE"), N_("PROFILE") }, + { "format", 'f', G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_STRING, &output_format, + N_("set output format string to FORMAT"), + N_("FORMAT") }, { "rotate", 't', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &rotate_image, N_("(deprecated, does nothing)"), NULL }, @@ -321,8 +333,8 @@ thumbnail_process(VipsObject *process, const char *name) "no-rotate", no_rotate_image, "crop", interesting, "linear", linear_processing, - "import-profile", import_profile, - "export-profile", export_profile, + "import-profile", input_profile, + "output-profile", output_profile, "intent", intent, NULL)) { VIPS_UNREF(source); @@ -337,8 +349,8 @@ thumbnail_process(VipsObject *process, const char *name) "no-rotate", no_rotate_image, "crop", interesting, "linear", linear_processing, - "import-profile", import_profile, - "export-profile", export_profile, + "import-profile", input_profile, + "output-profile", output_profile, "intent", intent, NULL)) return -1; @@ -546,9 +558,8 @@ main(int argc, char **argv) #ifndef HAVE_EXIF if (rotate_image) - g_warning("%s", - _("auto-rotate disabled: " - "libvips built without exif support")); + g_warning("auto-rotate disabled: " + "libvips built without exif support"); #endif /*!HAVE_EXIF*/ result = 0;