From 244ab301f799e558aec3ccaad8c7f3af6bd6569a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 11 Feb 2015 17:01:02 +0000 Subject: [PATCH] start final push for vips 8 --- ChangeLog | 7 + TODO | 44 +- bootstrap.sh | 19 +- configure.ac | 15 +- doc/Makefile.am | 190 ++++- doc/{reference => }/binding.xml | 0 doc/{reference => }/extending.xml | 0 doc/{reference => }/file-format.xml | 0 doc/{reference => }/function-list.xml | 0 doc/{reference => }/gen-function-list.py | 0 doc/gtk-doc.make | 289 +++++++ doc/{reference => }/images/interconvert.png | Bin doc/{reference => }/images/interconvert.svg | 0 doc/libvips-docs.xml | 98 +++ doc/{reference => }/libvips-docs.xml.in | 0 doc/reference/Makefile.am | 187 ---- doc/src/Makefile | 67 -- doc/src/applintro.tex | 51 -- doc/src/cppintro.tex | 108 --- doc/src/figs/arch.png | Bin 32167 -> 0 bytes doc/src/figs/arch.svg | 385 --------- doc/src/figs/arch8.svg | 705 ---------------- doc/src/figs/interconvert.png | Bin 26322 -> 0 bytes doc/src/figs/interconvert.svg | 505 ----------- doc/src/fileformat.tex | 173 ---- doc/src/format.tex | 133 --- doc/src/func.tex | 697 --------------- doc/src/html.cfg | 17 - doc/src/interpolate.tex | 162 ---- doc/src/iosys.tex | 836 ------------------ doc/src/ipio.tex | 56 -- doc/src/mydefs.tex | 113 --- doc/src/object.tex | 134 --- doc/src/operintro.tex | 100 --- doc/src/packages.tex | 889 -------------------- doc/src/pio.tex | 854 ------------------- doc/src/refintro.tex | 114 --- doc/src/vdisplay.tex | 75 -- doc/src/verror.tex | 76 -- doc/src/vimage.tex | 372 -------- doc/src/vipsmanual.tex | 95 --- doc/src/vmask.tex | 175 ---- doc/src/wio.tex | 363 -------- doc/{reference => }/using-C.xml | 0 doc/{reference => }/using-command-line.xml | 0 doc/{reference => }/using-cpp.xml | 0 doc/{reference => }/using-python.xml | 0 libvips/colour/colour.c | 1 + libvips/colour/colourspace.c | 25 +- libvips/conversion/cast.c | 75 +- tools/Makefile.am | 4 +- tools/vips-8.0 | 129 +++ 52 files changed, 858 insertions(+), 7480 deletions(-) rename doc/{reference => }/binding.xml (100%) rename doc/{reference => }/extending.xml (100%) rename doc/{reference => }/file-format.xml (100%) rename doc/{reference => }/function-list.xml (100%) rename doc/{reference => }/gen-function-list.py (100%) create mode 100644 doc/gtk-doc.make rename doc/{reference => }/images/interconvert.png (100%) rename doc/{reference => }/images/interconvert.svg (100%) create mode 100644 doc/libvips-docs.xml rename doc/{reference => }/libvips-docs.xml.in (100%) delete mode 100644 doc/reference/Makefile.am delete mode 100644 doc/src/Makefile delete mode 100644 doc/src/applintro.tex delete mode 100644 doc/src/cppintro.tex delete mode 100644 doc/src/figs/arch.png delete mode 100644 doc/src/figs/arch.svg delete mode 100644 doc/src/figs/arch8.svg delete mode 100644 doc/src/figs/interconvert.png delete mode 100644 doc/src/figs/interconvert.svg delete mode 100644 doc/src/fileformat.tex delete mode 100644 doc/src/format.tex delete mode 100644 doc/src/func.tex delete mode 100644 doc/src/html.cfg delete mode 100644 doc/src/interpolate.tex delete mode 100644 doc/src/iosys.tex delete mode 100644 doc/src/ipio.tex delete mode 100644 doc/src/mydefs.tex delete mode 100644 doc/src/object.tex delete mode 100644 doc/src/operintro.tex delete mode 100644 doc/src/packages.tex delete mode 100644 doc/src/pio.tex delete mode 100644 doc/src/refintro.tex delete mode 100644 doc/src/vdisplay.tex delete mode 100644 doc/src/verror.tex delete mode 100644 doc/src/vimage.tex delete mode 100644 doc/src/vipsmanual.tex delete mode 100644 doc/src/vmask.tex delete mode 100644 doc/src/wio.tex rename doc/{reference => }/using-C.xml (100%) rename doc/{reference => }/using-command-line.xml (100%) rename doc/{reference => }/using-cpp.xml (100%) rename doc/{reference => }/using-python.xml (100%) create mode 100755 tools/vips-8.0 diff --git a/ChangeLog b/ChangeLog index e39cf239..81b990c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +11/2/15 started 8.0 +- remove old doc stuff +- add fliphor(), flipver(), rot90(), rot180(), rot270() convenience methods to + Python +- add shift option to cast +- better alpha handling for 16 <-> 8 bit colour conversions + 6/2/15 started 7.42.3 - bump version for back-compat ABI change - added vips_image_memory(), an alias for vips_image_new_memory() diff --git a/TODO b/TODO index 65241e87..b5257557 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,41 @@ +- at the moment we have a policy of just ignoring extra bands + + we are proposing to change this to modify band 2, 4 or 5, if present, when + going to and from RGB16 or GREY16 + + if we make this change, we must support it for all transforms of this type, + not just for a couple, or it'll be incredibly confusing + + vips_process_n() could use cast(shift = TRUE) + + vips_colour_build() could use cast shift too + + + + +- use vips_sRGB2RGB16() + + +- check vips_sRGB2scRGB() with a 16-bit source ... what does it do for alpha? + + alpha is untouched ... rgb->0-1, alpha stays at 0-65535 + + maybe should move everything to 0-1? otherwise when we do scRGB2sRGB we'll + (effectively) do alpha * 256 + + but what if we then do scRGB -> XYZ (for example), should alpha stay 0 - 1? + + + + + + +- we have + + im.flip("horizontal") + + maybe add fliphor() and flipver() as convenience functions, cf. .sin() etc. + - why can't we do im = Vips.Image.new_from_file(sys.argv[1], access = "sequential") @@ -8,11 +46,11 @@ im.embed(10, 10, 100, 100, extend = "copy") + what about -- msb in colour should not touch alpha channel + im = Vips.Image.jpegload(sys.argv[1], access = "sequential") - ... or should it? should converting RGBA from 8 to 16-bit touch alpha too? - probably + nope, fails too diff --git a/bootstrap.sh b/bootstrap.sh index fb677233..824d93e9 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -13,15 +13,14 @@ rm -f swig/vipsCC/*.cxx rm -f swig/vipsCC/VImage.h rm -f swig/vipsCC/VImage.py python/vipsCC/VError.py python/vipsCC/VMask.py python/vipsCC/Display.py rm -f benchmark/temp* -( cd doc ; \ - mkdir poop ; \ - mv reference/libvips-docs.xml.in poop ; \ - mv reference/Makefile.am poop ; \ - mv reference/images poop ; \ - mv reference/*.xml poop ; \ - mv reference/*.py poop ; \ - rm -rf reference/* ; \ - mv poop/* reference ; \ +( mkdir poop ; \ + mv doc/libvips-docs.xml.in poop ; \ + mv doc/Makefile.am poop ; \ + mv doc/images poop ; \ + mv doc/*.xml poop ; \ + mv doc/*.py poop ; \ + rm -rf doc/* ; \ + mv poop/* doc ; \ rmdir poop \ ) @@ -45,7 +44,7 @@ cp $ACDIR/lcmessage.m4 m4 cp $ACDIR/progtest.m4 m4 cp $ACDIR/introspection.m4 m4 -gtkdocize --copy --docdir doc/reference --flavour no-tmpl || exit 1 +gtkdocize --copy --docdir doc --flavour no-tmpl || exit 1 # some systems need libtoolize, some glibtoolize ... how annoying echo testing for glibtoolize ... diff --git a/configure.ac b/configure.ac index 01ca4928..cc79065f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # also update the version number in the m4 macros below -AC_INIT([vips], [7.42.3], [vipsip@jiscmail.ac.uk]) +AC_INIT([vips], [8.0.0], [vipsip@jiscmail.ac.uk]) # required for gobject-introspection AC_PREREQ(2.62) @@ -16,9 +16,9 @@ AC_CONFIG_HEADERS(config.h) AC_CONFIG_MACRO_DIR([m4]) # user-visible library versioning -m4_define([vips_major_version], [7]) -m4_define([vips_minor_version], [42]) -m4_define([vips_micro_version], [3]) +m4_define([vips_major_version], [8]) +m4_define([vips_minor_version], [0]) +m4_define([vips_micro_version], [0]) m4_define([vips_version], [vips_major_version.vips_minor_version.vips_micro_version]) @@ -38,7 +38,7 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date` # binary interface changes not backwards compatible?: reset age to 0 LIBRARY_CURRENT=41 -LIBRARY_REVISION=0 +LIBRARY_REVISION=1 LIBRARY_AGE=1 # patched into include/vips/version.h @@ -59,7 +59,7 @@ GOBJECT_INTROSPECTION_CHECK([1.30.0]) # gir needs a list of source files to scan for introspection # # build with a glob and a list of files to exclude from scanning -# see also IGNORE_HFILES in doc/reference/Makefile.am +# see also IGNORE_HFILES in doc/Makefile.am introspection_sources=$(cd libvips ; find . -name "*.c") filter_list="deprecated " @@ -839,8 +839,7 @@ AC_OUTPUT([ swig/vipsCC/Makefile man/Makefile doc/Makefile - doc/reference/Makefile - doc/reference/libvips-docs.xml + doc/libvips-docs.xml po/Makefile.in ]) diff --git a/doc/Makefile.am b/doc/Makefile.am index 64e9e534..9e8da204 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,7 +1,187 @@ +## Process this file with automake to produce Makefile.in -SUBDIRS = reference +# We require automake 1.6 at least. +AUTOMAKE_OPTIONS = 1.6 -EXTRA_DIST = \ - html \ - pdf \ - src +# This is a blank Makefile.am for using gtk-doc. +# Copy this to your project's API docs directory and modify the variables to +# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples +# of using the various options. + +# The name of the module, e.g. 'glib'. +DOC_MODULE=libvips + +# Uncomment for versioned docs and specify the version of the module, e.g. '2'. +#DOC_MODULE_VERSION=2 + + +# The top-level XML file (SGML in the past). You can change this if you want to. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml + +# Directories containing the source code. +# gtk-doc will search all .c and .h files beneath these paths +# for inline comments documenting functions and macros. +# e.g. DOC_SOURCE_DIR=$(top_srcdir)/gtk $(top_srcdir)/gdk +DOC_SOURCE_DIR=$(top_srcdir)/libvips + +# Extra options to pass to gtkdoc-scangobj. Not normally needed. +SCANGOBJ_OPTIONS= + +# Extra options to supply to gtkdoc-scan. +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +SCAN_OPTIONS=--rebuild-types + +# Extra options to supply to gtkdoc-mkdb. +# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml +MKDB_OPTIONS=--xml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +# e.g. MKTMPL_OPTIONS=--only-section-tmpl +MKTMPL_OPTIONS= + +# Extra options to supply to gtkdoc-mkhtml +MKHTML_OPTIONS= + +# Extra options to supply to gtkdoc-fixref. Not normally needed. +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html +FIXXREF_OPTIONS= + +# Used for dependencies. The docs will be rebuilt if any of these change. +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c +HFILE_GLOB=$(top_srcdir)/libvips/include/vips/*.h +CFILE_GLOB=$(top_srcdir)/libvips/*/*.c + +# Extra header to include when scanning, which are not under DOC_SOURCE_DIR +# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h +EXTRA_HFILES= + +# Header files or dirs to ignore when scanning. Use base file/dir names +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code + +IGNORE_VIPS_INCLUDE = \ + almostdeprecated.h \ + cimg_funcs.h \ + deprecated.h \ + vips7compat.h \ + dispatch.h \ + enumtypes.h \ + internal.h \ + thread.h \ + intl.h \ + format.h \ + mask.h \ + private.h \ + video.h + +# ignore all .h files in libvips/*, these are internal +IGNORE_VIPS_C = \ + binary.h \ + hough.h \ + nary.h \ + parithmetic.h \ + statistic.h \ + unaryconst.h \ + unary.h \ + CImg.h \ + pcolour.h \ + bandary.h \ + pconversion.h \ + correlation.h \ + pconvolution.h \ + pcreate.h \ + pmask.h \ + point.h \ + drawink.h \ + pdraw.h \ + analyze2vips.h \ + csv.h \ + dbh.h \ + fits.h \ + jpeg.h \ + magick.h \ + matlab.h \ + openexr2vips.h \ + openslide2vips.h \ + ppm.h \ + radiance.h \ + tiff.h \ + vipsjpeg.h \ + vipspng.h \ + webp.h \ + pfreqfilt.h \ + hist_unary.h \ + phistogram.h \ + base64.h \ + sink.h \ + vipsmarshal.h \ + pmorphology.h \ + global_balance.h \ + pmosaicing.h \ + presample.h \ + templates.h + +IGNORE_HFILES = $(IGNORE_VIPS_INCLUDE) $(IGNORE_VIPS_C) + +# Images to copy into HTML directory. +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png +HTML_IMAGES = \ + $(top_srcdir)/doc/images/interconvert.png + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml +content_files = \ + using-command-line.xml \ + using-C.xml \ + using-python.xml \ + using-cpp.xml \ + extending.xml \ + function-list.xml \ + file-format.xml \ + binding.xml + +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# These files must be listed here *and* in content_files +# e.g. expand_content_files=running.sgml +expand_content_files = \ + using-command-line.xml \ + using-C.xml \ + using-python.xml \ + using-cpp.xml \ + extending.xml \ + function-list.xml \ + file-format.xml \ + binding.xml + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +# Only needed if you are using gtkdoc-scangobj to dynamically query widget +# signals and properties. +# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) +GTKDOC_CFLAGS = @VIPS_CFLAGS@ @VIPS_INCLUDES@ +GTKDOC_LIBS = @VIPS_CFLAGS@ ${top_builddir}/libvips/libvips.la @VIPS_LIBS@ + +# This includes the standard gtk-doc make rules, copied by gtkdocize. +include gtk-doc.make + +# Other files to distribute +# e.g. EXTRA_DIST += version.xml.in +EXTRA_DIST += \ + images \ + gen-function-list.py + +# Files not to distribute +# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types +# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt +DISTCLEANFILES = libvips.types + +# Comment this out if you want 'make check' to test you doc status +# and run some sanity checks +if ENABLE_GTK_DOC +TESTS_ENVIRONMENT = \ + DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \ + SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir) +#TESTS = $(GTKDOC_CHECK) +endif + +-include $(top_srcdir)/git.mk diff --git a/doc/reference/binding.xml b/doc/binding.xml similarity index 100% rename from doc/reference/binding.xml rename to doc/binding.xml diff --git a/doc/reference/extending.xml b/doc/extending.xml similarity index 100% rename from doc/reference/extending.xml rename to doc/extending.xml diff --git a/doc/reference/file-format.xml b/doc/file-format.xml similarity index 100% rename from doc/reference/file-format.xml rename to doc/file-format.xml diff --git a/doc/reference/function-list.xml b/doc/function-list.xml similarity index 100% rename from doc/reference/function-list.xml rename to doc/function-list.xml diff --git a/doc/reference/gen-function-list.py b/doc/gen-function-list.py similarity index 100% rename from doc/reference/gen-function-list.py rename to doc/gen-function-list.py diff --git a/doc/gtk-doc.make b/doc/gtk-doc.make new file mode 100644 index 00000000..e7916563 --- /dev/null +++ b/doc/gtk-doc.make @@ -0,0 +1,289 @@ +# -*- mode: makefile -*- + +#################################### +# Everything below here is generic # +#################################### + +if GTK_DOC_USE_LIBTOOL +GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = $(LIBTOOL) --mode=execute +else +GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = +endif + +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE) + +SETUP_FILES = \ + $(content_files) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_MODULE)-sections.txt \ + $(DOC_MODULE)-overrides.txt + +EXTRA_DIST = \ + $(HTML_IMAGES) \ + $(SETUP_FILES) + +DOC_STAMPS=setup-build.stamp scan-build.stamp sgml-build.stamp \ + html-build.stamp pdf-build.stamp \ + sgml.stamp html.stamp pdf.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +gtkdoc-check.test: Makefile + $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ + echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ + chmod +x $@ + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test + +if GTK_DOC_BUILD_HTML +HTML_BUILD_STAMP=html-build.stamp +else +HTML_BUILD_STAMP= +endif +if GTK_DOC_BUILD_PDF +PDF_BUILD_STAMP=pdf-build.stamp +else +PDF_BUILD_STAMP= +endif + +all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) +.PHONY: all-gtk-doc + +if ENABLE_GTK_DOC +all-local: all-gtk-doc +endif + +docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) + +$(REPORT_FILES): sgml-build.stamp + +#### setup #### + +GTK_DOC_V_SETUP=$(GTK_DOC_V_SETUP_$(V)) +GTK_DOC_V_SETUP_=$(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_SETUP_0=@echo " DOC Preparing build"; + +setup-build.stamp: + -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + files=`echo $(SETUP_FILES) $(expand_content_files) $(DOC_MODULE).types`; \ + if test "x$$files" != "x" ; then \ + for file in $$files ; do \ + destdir=`dirname $(abs_builddir)/$$file`; \ + test -d "$$destdir" || mkdir -p "$$destdir"; \ + test -f $(abs_srcdir)/$$file && \ + cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ + done; \ + fi; \ + fi + $(AM_V_at)touch setup-build.stamp + + +#### scan #### + +GTK_DOC_V_SCAN=$(GTK_DOC_V_SCAN_$(V)) +GTK_DOC_V_SCAN_=$(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_SCAN_0=@echo " DOC Scanning header files"; + +GTK_DOC_V_INTROSPECT=$(GTK_DOC_V_INTROSPECT_$(V)) +GTK_DOC_V_INTROSPECT_=$(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_INTROSPECT_0=@echo " DOC Introspecting gobjects"; + +scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) + $(GTK_DOC_V_SCAN)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) + $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ + scanobj_options=""; \ + gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$(?)" = "0"; then \ + if test "x$(V)" = "x1"; then \ + scanobj_options="--verbose"; \ + fi; \ + fi; \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ + else \ + for i in $(SCANOBJ_FILES) ; do \ + test -f $$i || touch $$i ; \ + done \ + fi + $(AM_V_at)touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +#### xml #### + +GTK_DOC_V_XML=$(GTK_DOC_V_XML_$(V)) +GTK_DOC_V_XML_=$(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_XML_0=@echo " DOC Building XML"; + +sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) + $(GTK_DOC_V_XML)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) + $(AM_V_at)touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +#### html #### + +GTK_DOC_V_HTML=$(GTK_DOC_V_HTML_$(V)) +GTK_DOC_V_HTML_=$(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_HTML_0=@echo " DOC Building HTML"; + +GTK_DOC_V_XREF=$(GTK_DOC_V_XREF_$(V)) +GTK_DOC_V_XREF_=$(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_XREF_0=@echo " DOC Fixing cross-references"; + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ + mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$(?)" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + if test "$(?)" = "0"; then \ + mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) + -@test "x$(HTML_IMAGES)" = "x" || \ + for file in $(HTML_IMAGES) ; do \ + if test -f $(abs_srcdir)/$$file ; then \ + cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ + fi; \ + if test -f $(abs_builddir)/$$file ; then \ + cp $(abs_builddir)/$$file $(abs_builddir)/html; \ + fi; \ + done; + $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + $(AM_V_at)touch html-build.stamp + +#### pdf #### + +GTK_DOC_V_PDF=$(GTK_DOC_V_PDF_$(V)) +GTK_DOC_V_PDF_=$(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_PDF_0=@echo " DOC Building PDF"; + +pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ + mkpdf_options=""; \ + gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$(?)" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkpdf_options="$$mkpdf_options --verbose"; \ + fi; \ + fi; \ + if test "x$(HTML_IMAGES)" != "x"; then \ + for img in $(HTML_IMAGES); do \ + part=`dirname $$img`; \ + echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ + if test $$? != 0; then \ + mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ + fi; \ + done; \ + fi; \ + gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) + $(AM_V_at)touch pdf-build.stamp + +############## + +clean-local: + @rm -f *~ *.bak + @rm -rf .libs + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ + rm -f $(DOC_MODULE).types; \ + fi + +distclean-local: + @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(SETUP_FILES) $(expand_content_files) $(DOC_MODULE).types; \ + fi + +maintainer-clean-local: + @rm -rf xml html + +install-data-local: + @installfiles=`echo $(builddir)/html/*`; \ + if test "$$installfiles" = '$(builddir)/html/*'; \ + then echo 1>&2 'Nothing to install' ; \ + else \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + $(mkinstalldirs) $${installdir} ; \ + for i in $$installfiles; do \ + echo ' $(INSTALL_DATA) '$$i ; \ + $(INSTALL_DATA) $$i $${installdir}; \ + done; \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ + $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ + fi; \ + $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ + fi + +uninstall-local: + @if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + rm -rf $${installdir} + +# +# Require gtk-doc when making dist +# +if HAVE_GTK_DOC +dist-check-gtkdoc: docs +else +dist-check-gtkdoc: + @echo "*** gtk-doc is needed to run 'make dist'. ***" + @echo "*** gtk-doc was not found when 'configure' ran. ***" + @echo "*** please install gtk-doc and rerun 'configure'. ***" + @false +endif + +dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local + @mkdir $(distdir)/html + @cp ./html/* $(distdir)/html + @-cp ./$(DOC_MODULE).pdf $(distdir)/ + @-cp ./$(DOC_MODULE).types $(distdir)/ + @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ + @cd $(distdir) && rm -f $(DISTCLEANFILES) + @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs diff --git a/doc/reference/images/interconvert.png b/doc/images/interconvert.png similarity index 100% rename from doc/reference/images/interconvert.png rename to doc/images/interconvert.png diff --git a/doc/reference/images/interconvert.svg b/doc/images/interconvert.svg similarity index 100% rename from doc/reference/images/interconvert.svg rename to doc/images/interconvert.svg diff --git a/doc/libvips-docs.xml b/doc/libvips-docs.xml new file mode 100644 index 00000000..5a5769a6 --- /dev/null +++ b/doc/libvips-docs.xml @@ -0,0 +1,98 @@ + + + +]> + + + VIPS Reference Manual + + For VIPS 7.42.3. + The latest version of this documentation can be found on the + VIPS website. + + + + + VIPS Overview + + VIPS 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. VIPS is released under the GNU Library + General Public License (GNU LGPL). + + + + + + + + + + + + + + Core VIPS API + + + + + + + + + + + + + + + + + + VIPS operation API by section + + + + + + + + + + + + + + + + + Other API (no gtkdoc comments yet) + + + + + + + + Object Hierarchy + + + + + API Index + + + + + + diff --git a/doc/reference/libvips-docs.xml.in b/doc/libvips-docs.xml.in similarity index 100% rename from doc/reference/libvips-docs.xml.in rename to doc/libvips-docs.xml.in diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am deleted file mode 100644 index c1c0da84..00000000 --- a/doc/reference/Makefile.am +++ /dev/null @@ -1,187 +0,0 @@ -## Process this file with automake to produce Makefile.in - -# We require automake 1.6 at least. -AUTOMAKE_OPTIONS = 1.6 - -# This is a blank Makefile.am for using gtk-doc. -# Copy this to your project's API docs directory and modify the variables to -# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples -# of using the various options. - -# The name of the module, e.g. 'glib'. -DOC_MODULE=libvips - -# Uncomment for versioned docs and specify the version of the module, e.g. '2'. -#DOC_MODULE_VERSION=2 - - -# The top-level XML file (SGML in the past). You can change this if you want to. -DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml - -# Directories containing the source code. -# gtk-doc will search all .c and .h files beneath these paths -# for inline comments documenting functions and macros. -# e.g. DOC_SOURCE_DIR=$(top_srcdir)/gtk $(top_srcdir)/gdk -DOC_SOURCE_DIR=$(top_srcdir)/libvips - -# Extra options to pass to gtkdoc-scangobj. Not normally needed. -SCANGOBJ_OPTIONS= - -# Extra options to supply to gtkdoc-scan. -# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" -SCAN_OPTIONS=--rebuild-types - -# Extra options to supply to gtkdoc-mkdb. -# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml -MKDB_OPTIONS=--xml-mode --output-format=xml - -# Extra options to supply to gtkdoc-mktmpl -# e.g. MKTMPL_OPTIONS=--only-section-tmpl -MKTMPL_OPTIONS= - -# Extra options to supply to gtkdoc-mkhtml -MKHTML_OPTIONS= - -# Extra options to supply to gtkdoc-fixref. Not normally needed. -# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html -FIXXREF_OPTIONS= - -# Used for dependencies. The docs will be rebuilt if any of these change. -# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h -# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c -HFILE_GLOB=$(top_srcdir)/libvips/include/vips/*.h -CFILE_GLOB=$(top_srcdir)/libvips/*/*.c - -# Extra header to include when scanning, which are not under DOC_SOURCE_DIR -# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h -EXTRA_HFILES= - -# Header files or dirs to ignore when scanning. Use base file/dir names -# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code - -IGNORE_VIPS_INCLUDE = \ - almostdeprecated.h \ - cimg_funcs.h \ - deprecated.h \ - vips7compat.h \ - dispatch.h \ - enumtypes.h \ - internal.h \ - thread.h \ - intl.h \ - format.h \ - mask.h \ - private.h \ - video.h - -# ignore all .h files in libvips/*, these are internal -IGNORE_VIPS_C = \ - binary.h \ - hough.h \ - nary.h \ - parithmetic.h \ - statistic.h \ - unaryconst.h \ - unary.h \ - CImg.h \ - pcolour.h \ - bandary.h \ - pconversion.h \ - correlation.h \ - pconvolution.h \ - pcreate.h \ - pmask.h \ - point.h \ - drawink.h \ - pdraw.h \ - analyze2vips.h \ - csv.h \ - dbh.h \ - fits.h \ - jpeg.h \ - magick.h \ - matlab.h \ - openexr2vips.h \ - openslide2vips.h \ - ppm.h \ - radiance.h \ - tiff.h \ - vipsjpeg.h \ - vipspng.h \ - webp.h \ - pfreqfilt.h \ - hist_unary.h \ - phistogram.h \ - base64.h \ - sink.h \ - vipsmarshal.h \ - pmorphology.h \ - global_balance.h \ - pmosaicing.h \ - presample.h \ - templates.h - -IGNORE_HFILES = $(IGNORE_VIPS_INCLUDE) $(IGNORE_VIPS_C) - -# Images to copy into HTML directory. -# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png -HTML_IMAGES = \ - $(top_srcdir)/doc/reference/images/interconvert.png - -# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). -# e.g. content_files=running.sgml building.sgml changes-2.0.sgml -content_files = \ - using-command-line.xml \ - using-C.xml \ - using-python.xml \ - using-cpp.xml \ - extending.xml \ - function-list.xml \ - file-format.xml \ - binding.xml - -# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded -# These files must be listed here *and* in content_files -# e.g. expand_content_files=running.sgml -expand_content_files = \ - using-command-line.xml \ - using-C.xml \ - using-python.xml \ - using-cpp.xml \ - extending.xml \ - function-list.xml \ - file-format.xml \ - binding.xml - -# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. -# Only needed if you are using gtkdoc-scangobj to dynamically query widget -# signals and properties. -# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) -# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) -GTKDOC_CFLAGS = @VIPS_CFLAGS@ @VIPS_INCLUDES@ -GTKDOC_LIBS = @VIPS_CFLAGS@ ${top_builddir}/libvips/libvips.la @VIPS_LIBS@ - -# This includes the standard gtk-doc make rules, copied by gtkdocize. -include gtk-doc.make - -# Other files to distribute -# e.g. EXTRA_DIST += version.xml.in -EXTRA_DIST += \ - images \ - gen-function-list.py - -# Files not to distribute -# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types -# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt -DISTCLEANFILES = libvips.types - -# Comment this out if you want 'make check' to test you doc status -# and run some sanity checks -if ENABLE_GTK_DOC -TESTS_ENVIRONMENT = \ - DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \ - SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir) -#TESTS = $(GTKDOC_CHECK) -endif - --include $(top_srcdir)/git.mk diff --git a/doc/src/Makefile b/doc/src/Makefile deleted file mode 100644 index c2c1a952..00000000 --- a/doc/src/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -# - -PDF = vipsmanual.pdf -SRC = \ - applintro.tex \ - cppintro.tex \ - fileformat.tex \ - func.tex \ - format.tex \ - iosys.tex \ - ipio.tex \ - mydefs.tex \ - operintro.tex \ - packages.tex \ - pio.tex \ - refintro.tex \ - vdisplay.tex \ - verror.tex \ - vimage.tex \ - vipsmanual.tex \ - vmask.tex \ - wio.tex - -destdir = ../ - -all: $(PDF) html - -install: all $(PDF) html - -rm -rf ${destdir}/pdf/*.pdf - -rm -rf ${destdir}/html/vips* - -rm -rf ${destdir}/html/figs - -mkdir -p ${destdir}/pdf - -mkdir -p ${destdir}/html - -cp $(PDF) ${destdir}/pdf - -cp -r vipsmanual/* ${destdir}/html - -$(PDF): $(SRC) - pdflatex vipsmanual.tex - pdflatex vipsmanual.tex - -.PHONY: html -html: - -rm -rf vipsmanual - mkdir vipsmanual - htlatex vipsmanual.tex html.cfg,3 "" -dvipsmanual/ - cp -r figs vipsmanual - -rm vipsmanual/figs/*.svg - -rm vipsmanual/*.png - -.PHONY: clean -clean: - -rm -f *.4ct - -rm -f *.4tc - -rm -f *.log - -rm -f *.xref - -rm -f *.tmp - -rm -f *.html - -rm -f *.css - -rm -f *.lg - -rm -f *.idv - -rm -f *.aux - -rm -f *.dvi - -rm -f *.lof - -rm -f *.lot - -rm -f *.toc - -rm -f *.pdf - -rm -rf vipsmanual diff --git a/doc/src/applintro.tex b/doc/src/applintro.tex deleted file mode 100644 index f1bb3de4..00000000 --- a/doc/src/applintro.tex +++ /dev/null @@ -1,51 +0,0 @@ -\section{Introduction} -\mylabel{sec:appl} - -This chapter explains how to call VIPS functions from C programs. It does not -explain how to write new image processing operations (see \pref{sec:oper}), -only how to call the ones that VIPS provides. If you want to call VIPS -functions from C++ programs, you can either use the interface described here -or you can try out the much nicer C++ interface described in \pref{sec:cpp}. - -See \pref{sec:ref} for an introduction to the image processing operations -available in the library. \fref{fg:architecture} tries to show -an overview of this structure. - -\begin{fig2} -\figw{5in}{arch.png} -\caption{VIPS software architecture} -\label{fg:architecture} -\end{fig2} - -VIPS includes a set of UNIX manual pages. Enter (for example): - -\begin{verbatim} -example% man im_extract -\end{verbatim} - -\noindent -to get an explanation of the \verb+im_extract()+ function. - -All the command-line VIPS operations will print help text too. For example: - -\begin{verbatim} -example% vips im_extract -usage: vips im_extract input output - left top width height band -where: - input is of type "image" - output is of type "image" - left is of type "integer" - top is of type "integer" - width is of type "integer" - height is of type "integer" - band is of type "integer" -extract area/band, from package - "conversion" -flags: (PIO function) - (coordinate transformer) - (area operation) - (result can be cached) -vips: error calling function -im_run_command: too few arguments -\end{verbatim} diff --git a/doc/src/cppintro.tex b/doc/src/cppintro.tex deleted file mode 100644 index 20bea9b9..00000000 --- a/doc/src/cppintro.tex +++ /dev/null @@ -1,108 +0,0 @@ -\section{Introduction} -\mylabel{sec:cpp} - -This chapter describes the C++ API for the VIPS image processing library. -The C++ API is as efficient as the C interface to VIPS, but is -far easier to use: almost all creation, destruction and error handling issues -are handled for you automatically. - -The Python interface is a very simple wrapping of this C++ API generated -automatically with SWIG. It adds a few utility methods noted below, but -otherwise the two interfaces are identical other than language -syntax. - -\subsection{If you've used the C API} - -To show how much easier the VIPS C++ API is to use, compare \fref{fg:negative} -to \fref{fg:invert-c++}. \fref{fg:invert-py} is the same thing in Python. - -A typical build line for the C++ program might be: - -\begin{verbatim} -g++ invert.cc \ - `pkg-config vipsCC-7.18 \ - --cflags --libs` -\end{verbatim} - -The key points are: - -\begin{itemize} - -\item -You just include \verb++ --- this then gets all of the -other includes you need. Everything is in the \verb+vips+ namespace. - -\item -The C++ API replaces all of the VIPS C types --- \verb+IMAGE+ becomes -\verb+VImage+ and so on. The C++ API also includes \verb+VDisplay+, -\verb+VMask+ and \verb+VError+. - -\item -Image processing operations are member functions of the \verb+VImage+ class ---- here, \verb+VImage( argv[1] )+ creates a new \verb+VImage+ object using -the first argument to initialise it (the input filename). It then calls the -member function \verb+invert()+, which inverts the \verb+VImage+ and returns a -new \verb+VImage+. Finally it calls the member function \verb+write()+, which -writes the result image to the named file. - -\item -The VIPS C++ API uses exceptions --- the \verb+VError+ class is covered -later. If you run this program with a bad input file, for example, you get the -following output: - -\begin{verbatim} -$ invert jim fred -invert: VIPS error: format_for_file: - file "jim" not found -\end{verbatim} - -\end{itemize} - -\begin{fig2} -\begin{verbatim} -#include -#include - -int -main (int argc, char **argv) -{ - if (argc != 3) - { - std::cerr << "usage: " << argv[0] << " infile outfile\n"; - return (1); - } - - try - { - vips::VImage fred (argv[1]); - - fred.invert ().write (argv[2]); - } - catch (vips::VError e) - { - e.perror (argv[0]); - } - - return (0); -} -\end{verbatim} -\caption{\texttt{invert} program in C++} -\label{fg:invert-c++} -\end{fig2} - -\begin{fig2} -\begin{verbatim} -#!/usr/bin/python - -import sys -from vipsCC import * - -try: - a = VImage.VImage (sys.argv[1]) - a.invert ().write (sys.argv[2]) -except VError.VError, e: - e.perror (sys.argv[0]) -\end{verbatim} -\caption{\texttt{invert} program in Python} -\label{fg:invert-py} -\end{fig2} diff --git a/doc/src/figs/arch.png b/doc/src/figs/arch.png deleted file mode 100644 index 2719aea86dfaad9a05e0293eff25c2854a68dc8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32167 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 AXaE2J diff --git a/doc/src/figs/arch.svg b/doc/src/figs/arch.svg deleted file mode 100644 index 6e44ee30..00000000 --- a/doc/src/figs/arch.svg +++ /dev/null @@ -1,385 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - Python binding - - - - C++ binding - - - VIPS imageprocessingoperations - User imageprocessingoperations - - VIPS IO system - Function dispatch - - - - Command-lineinterface - - - - diff --git a/doc/src/figs/arch8.svg b/doc/src/figs/arch8.svg deleted file mode 100644 index 6ff90ceb..00000000 --- a/doc/src/figs/arch8.svg +++ /dev/null @@ -1,705 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - VipsObject - - - - GObject - - - - VipsRegion - - - - VipsImage - - - - VipsOperation - - - - VipsArithmetic - - - - VipsBinary - - - - VipsAdd - - - - - - - GObjectintrospection - - - - - - Python - - - - Python - - - - - Ruby - - - - JS - - - - - nip2 - - - - C++ - - - - CLI - - - - - - - - - - - diff --git a/doc/src/figs/interconvert.png b/doc/src/figs/interconvert.png deleted file mode 100644 index bc98d461178640ece6845fc8898a6c3c42e75694..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26322 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - Lab - - - - XYZ - - - - LCh - - - - disp - - - - Yxy - - - - UCS - - - - LabQ - - - - LabS - - - - ICC - - - - - - - - - - Any VIPS RGB space - Any device withan ICC profile - - diff --git a/doc/src/fileformat.tex b/doc/src/fileformat.tex deleted file mode 100644 index a8fabbe6..00000000 --- a/doc/src/fileformat.tex +++ /dev/null @@ -1,173 +0,0 @@ -\section{The VIPS file format} - -VIPS has its own very simple file format. It is used inside VIPS to hold -images during computation. You can save images in VIPS format if you want, -but the VIPS format is not widely used and you may have problems reading -your images into other packages. - -If you intend to keep an image, it's much better to save it as TIFF, -JPEG, PNG, PBM/PGM/PPM or HDR. VIPS can transparently read and write all -these formats. - -\subsection{VIPS file header} -\label{sec:header} - -All VIPS image files start with a 64-byte header giving basic information -about the image dimensions, see \tref{fg:header}. This is followed by the -image data. This is usually just the pixel values in native format (ie. the -byte order used by the machine that wrote the file) laid out left-to-right and -top-to-bottom. After the image data comes a block of optional XML which holds -extra image metadata, such as ICC profiles and image history. -You can use the command-line program \verb+header+ to extract the XML from an -image and \verb+edvips+ to replace it, see the man pages. - -The \ct{Type} field, the \ct{Xres}/\ct{Yres} fields, and the -\ct{Xoffset}/\ct{Yoffset} fields are advisory. VIPS maintains their value -(if you convert an image to \cielab{} colour space with \ct{im\_XYZ2Lab()}, -for example, VIPS will set \ct{Type} to be \ct{IM\_TYPE\_LAB}), but never -uses these values itself in determining the action of an image processing -function. These fields are to help the user and to help application -programs built on VIPS which are trying to present image data to the user -in a meaningful way. - -The \ct{BandFmt}, \ct{Coding} and \ct{Type} fields can take the values -shown in tables~\ref{fg:bandfmt}, \ref{fg:coding} and \ref{fg:type}. The C++ -and Python names for these values are slightly different, for historical -reasons. - -\begin{tab2} -\begin{center} -\begin{tabular}{|l|l|l|} -\hline -Bytes & Represent & VIPS name \\ -\hline -0--3 & VIPS magic number (in hex, 08 f2 f6 b6) & \\ -4--7 & Number of pels per horizontal line (integer) & \ct{Xsize} \\ -8--11 & Number of horizontal lines (integer) & \ct{Ysize} \\ -12--15 & Number of bands (integer) & \ct{Bands} \\ -16--19 & Unused (legacy) & \ct{Bbits} \\ -20--23 & Band format (eg. \ct{IM\_BANDFMT\_USHORT}) & \ct{BandFmt} \\ -24--27 & Coding type (eg. \ct{IM\_CODING\_NONE}) & \ct{Coding} \\ -28--31 & Type (eg. \ct{IM\_TYPE\_LAB}) & \ct{Type} \\ -32--35 & Horizontal resolution (float, pixels mm$^{-1}$) & \ct{Xres} \\ -36--39 & Vertical resolution (float, pixels mm$^{-1}$) & \ct{Yres} \\ -40--43 & Unused (legacy) & \ct{Length} \\ -44--45 & Unused (legacy) & \ct{Compression} \\ -46--47 & Unused (legacy) & \ct{Level} \\ -48--51 & Horizontal offset of origin & \ct{Xoffset} \\ -52--55 & Vertical offset of origin & \ct{Yoffset} \\ -56--63 & For future expansion (all zeros for now) & \\ -\hline -\end{tabular} -\end{center} -\caption{VIPS header\label{fg:header}} -\end{tab2} - -\begin{tab2} -\begin{center} -\begin{tabular}{|l|l|l|l|} -\hline -\ct{BandFmt} & C++ and Python name & Value & Meaning \\ -\hline -\ct{IM\_BANDFMT\_NOTSET} & \ct{FMTNOTSET} & -1 & \\ -\ct{IM\_BANDFMT\_UCHAR} & \ct{FMTUCHAR} & 0 & Unsigned 8-bit int \\ -\ct{IM\_BANDFMT\_CHAR} & \ct{FMTCHAR} & 1 & Signed 8-bit int \\ -\ct{IM\_BANDFMT\_USHORT} & \ct{FMTUSHORT} & 2 & Unsigned 16-bit int \\ -\ct{IM\_BANDFMT\_SHORT} & \ct{FMTSHORT} & 3 & Signed 16-bit int \\ -\ct{IM\_BANDFMT\_UINT} & \ct{FMTUINT} & 4 & Unsigned 32-bit int \\ -\ct{IM\_BANDFMT\_INT} & \ct{FMTINT} & 5 & Signed 32-bit int \\ -\ct{IM\_BANDFMT\_FLOAT} & \ct{FMTFLOAT} & 6 & 32-bit IEEE float \\ -\ct{IM\_BANDFMT\_COMPLEX} & \ct{FMTCOMPLEX} & 7 & Complex (2 floats) \\ -\ct{IM\_BANDFMT\_DOUBLE} & \ct{FMTDOUBLE} & 8 & 64-bit IEEE double \\ -\ct{IM\_BANDFMT\_DPCOMPLEX} & \ct{FMTDPCOMPLEX} & 9 & Complex (2 doubles) \\ -\hline -\end{tabular} -\end{center} -\caption{Possible values for \ct{BandFmt}\label{fg:bandfmt}} -\end{tab2} - -\begin{tab2} -\begin{center} -\begin{tabular}{|l|l|l|l|} -\hline -\ct{Coding} & C++ and Python name & Value & Meaning \\ -\hline -\ct{IM\_CODING\_NONE} & \ct{NOCODING} & 0 & VIPS computation format \\ -\ct{IM\_CODING\_LABQ} & \ct{LABQ} & 2 & LABQ storage format \\ -\ct{IM\_CODING\_RAD} & \ct{RAD} & 6 & Radiance storage format \\ -\hline -\end{tabular} -\end{center} -\caption{Possible values for \texttt{Coding}\label{fg:coding}} -\end{tab2} - -\begin{tab2} -\begin{center} -\begin{tabular}{|l|l|l|l|} -\hline -\ct{Type} & C++ and Python name & Value & Meaning \\ -\hline -\ct{IM\_TYPE\_MULTIBAND} & \ct{MULTIBAND} & 0 & Some multiband image \\ -\ct{IM\_TYPE\_B\_W} & \ct{B\_W} & 1 & Some single band image \\ -\ct{IM\_TYPE\_HISTOGRAM} & \ct{HISTOGRAM} & 10 & Histogram or LUT \\ -\ct{IM\_TYPE\_FOURIER} & \ct{FOURIER} & 24 & Image in Fourier space \\ -\ct{IM\_TYPE\_XYZ} & \ct{XYZ} & 12 & \ciexyz{} colour space \\ -\ct{IM\_TYPE\_LAB} & \ct{LAB} & 13 & \cielab{} colour space \\ -\ct{IM\_TYPE\_CMYK} & \ct{CMYK} & 15 & \ct{im\_icc\_export()} \\ -\ct{IM\_TYPE\_LABQ} & \ct{LABQ} & 16 & 32-bit \cielab{} \\ -\ct{IM\_TYPE\_RGB} & \ct{RGB} & 17 & Some RGB \\ -\ct{IM\_TYPE\_UCS} & \ct{UCS} & 18 & \cieucs{} colour space \\ -\ct{IM\_TYPE\_LCH} & \ct{LCH} & 19 & \cielch{} colour space \\ -\ct{IM\_TYPE\_LABS} & \ct{LABS} & 21 & 48-bit \cielab{} \\ -\ct{IM\_TYPE\_sRGB} & \ct{sRGB} & 22 & sRGB colour space \\ -\ct{IM\_TYPE\_YXY} & \ct{YXY} & 23 & \cieyxy{} colour space \\ -\ct{IM\_TYPE\_RGB16} & \ct{RGB16} & 25 & 16-bit RGB \\ -\ct{IM\_TYPE\_GREY16} & \ct{GREY16} & 26 & 16-bit monochrome \\ -\hline -\end{tabular} -\end{center} -\caption{Possible values for \texttt{Type}\label{fg:type}} -\end{tab2} - -\subsection{Computation formats} - -This type of image has \ct{Coding} set to \ct{IM\_CODING\_NONE}. The -header is then followed by a large array of pixels, laid out left-to-right, -top-to-bottom. Each pixel contains the specified number of bands. Each band -has the specified band format, which may be an 8-, 16- or 32-bit integer -(either signed or unsigned), a single or double precision IEEE floating -point number, or a pair of single or double precision floats forming a -complex number. - -All values are stored in the host-machine's native number representation (that -is, either most-significant first, as in SPARC and 680x0 machines, or -least-significant first, for Intel and DEC machines). If necessary, the VIPS -library will automatically byte-swap for you during read. - -\subsection{Storage formats} - -All storage formats have other values for the \ct{Coding} field. This -release supports \ct{IM\_CODING\_LABQ} and \ct{IM\_CODING\_RAD}. - -\ct{IM\_CODING\_LABQ} stores $L^{*}$, $a^{*}$ and $b^{*}$ for each pixel, -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. - -This format is a little awkward to process. Some VIPS functions can work -directly on \ct{IM\_CODING\_LABQ} images (\ct{im\_extract\_area()}, for -example), but most will require you to unpack the image to one of the -computation formats (for example with \ct{im\_LabQ2Lab()}) first. - -\ct{IM\_CODING\_RAD} stores $RGB$ or $XYZ$ float images as 8 bytes of mantissa -and then 8 bytes 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. This style of image is generated when you load an HDR -image. - -This format is a little awkward to process. Some VIPS functions can work -directly on \ct{IM\_CODING\_RAD} images (\ct{im\_extract\_area()}, for -example), but most will require you to unpack the image to one of the -computation formats with \ct{im\_rad2float()} first. - diff --git a/doc/src/format.tex b/doc/src/format.tex deleted file mode 100644 index b175c8d8..00000000 --- a/doc/src/format.tex +++ /dev/null @@ -1,133 +0,0 @@ -\section{Image formats} -\label{sec:format} - -VIPS has a simple system for adding support for new image file formats. -You can ask VIPS to find a format to load a file with or to select a image -file writer based on a filename. Convenience functions copy a file to an -\verb+IMAGE+, or an \verb+IMAGE+ to a file. New formats may be added to -VIPS by simply defining a new subclass of \verb+VipsFormat+. - -This is a parallel API to \verb+im_open()+, see \pref{sec:open}. The -format system is useful for images which are large or slow to open, -because you pass a descriptor to write to and so control how and where -the decompressed image is held. \verb+im_open()+ is useful for images in -formats which can be directly read from disc, since you will avoid a copy -operation and can directly control the disc file. The inplace operations -(see \pref{sec:inplace}), for example, will only work directly on disc -images if you use \verb+im_open()+. - -\subsection{How a format is represented} - -See the man page for \verb+VipsFormat+ for full details, but briefly, an image -format consists of the following items: - -\begin{itemize} -\item -A name, a name that can be shows to the user, and a list of possible filename -suffixes (\verb+.tif+, for example) - -\item -A function which tests for a file being in that format, a function which loads -just the header of the file (that is, it reads properties like width and -height and does not read any pixel data) and a function which loads the pixel -data - -\item -A function which will write an \verb+IMAGE+ to a file in the format - -\item -And finally a function which examines a file in the format and returns flags -indicating how VIPS should deal with the file. The only flag in the current -version is one indicating that the file can be opened lazily - -\end{itemize} - -\subsection{The format class} - -The interface to the format system is defined by the abstract base class -\verb+VipsFormat+. Formats subclass this and implement some or all of the -methods. Any of the functions may be left NULL and VIPS will try to make do -with what you do supply. Of course a format with all functions as NULL will -not be very useful. - -As an example, \fref{fg:newformat} shows how to register a new format in a -plugin. - -\begin{fig2} -\begin{verbatim} -static const char *my_suffs[] = { ".me", NULL }; - -static int -is_myformat( const char *filename ) -{ - unsigned char buf[2]; - - if( im__get_bytes( filename, buf, 2 ) && - (int) buf[0] == 0xff && - (int) buf[1] == 0xd8 ) - return( 1 ); - - return( 0 ); -} - -// This format adds no new members. -typedef VipsFormat VipsFormatMyformat; -typedef VipsFormatClass VipsFormatMyformatClass; - -static void -vips_format_myformat_class_init( VipsFormatMyformatClass *class ) -{ - VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsFormatClass *format_class = (VipsFormatClass *) class; - - object_class->nickname = "myformat"; - object_class->description = _( "My format" ); - - format_class->is_a = is_myformat; - format_class->header = my_header; - format_class->load = my_read; - format_class->save = my_write; - format_class->get_flags = my_get_flags; - format_class->priority = 100; - format_class->suffs = my_suffs; -} - -static void -vips_format_myformat_init( VipsFormatMyformat *object ) -{ -} - -G_DEFINE_TYPE( VipsFormatMyformat, vips_format_myformat, VIPS_TYPE_FORMAT ); - -char * -g_module_check_init( GModule *self ) -{ - // register the type - vips_format_myformat_get_type(); -} -\end{verbatim} -\caption{Registering a format in a plugin} -\label{fg:newformat} -\end{fig2} - -\subsection{Finding a format} - -You can loop over the subclasses of \verb+VipsFormat+ in order of priority -with \verb+vips_format_map()+. Like all the map functions in VIPS, this take -a function and applies it to every element in the table until the function -returns non-zero or until the table ends. - -You find an \verb+VipsFormatClass+ to use to open a file with -\verb+vips_format_for_file()+. This finds the first format whose \verb+is_a()+ -function returns true or whose suffix list matches the suffix of the filename, -setting an error message and returning NULL if no format is found. - -You find a format to write a file with \verb+vips_format_for_name()+. This -returns the first format with a save function whose suffix list matches the -suffix of the supplied filename. - -\subsection{Convenience functions} - -A pair of convenience functions, \verb+vips_format_write()+ and -\verb+vips_format_read()+, will copy an image to and from disc using the -appropriate format. diff --git a/doc/src/func.tex b/doc/src/func.tex deleted file mode 100644 index e83ac2d9..00000000 --- a/doc/src/func.tex +++ /dev/null @@ -1,697 +0,0 @@ -\section{Function dispatch and plug-ins} - -(This chapter is on the verge of being deprecated. We have started building a -replacement based on \verb+GObject+, see \pref{sec:object}.) - -As image processing libraries increase in size it becomes progressively more -difficult to build applications which present the operations the library -offers to the user. Every time a new operation is added, every user interface -needs to be adapted --- a job which can rapidly become unmanageable. - -To address this problem VIPS includes a simple database which stores an -abstract description of every image processing operation. User interfaces, -rather than having special code wired into them for each operation, can -simply interrogate the database and present what they find to the user. - -The operation database is extensible. You can define new operations, and even -new types, and add them to VIPS. These new operations will then automatically -appear in all VIPS user interfaces with no extra programming effort. Plugins -can extend the database at runtime: when VIPS starts, it loads all the plugins -in the VIPS library area. - -\subsection{Simple plugin example} - -As an example, consider this function: - -\begin{verbatim} -#include - -#include - -/* The function we define. Call this - * from other parts of your C - * application. - */ -int -double_integer( int in ) -{ - return( in * 2 ); -} -\end{verbatim} - -\noindent -The source for all the example code in this section is in the vips-examples -package. - -The first step is to make a layer over this function which will make it -look like a standard VIPS function. VIPS insists on the following pattern: - -\begin{itemize} - -\item -The function should be int-valued, and return 0 for success and non-zero -for error. It should set \verb+im_error()+. - -\item -The function should take a single argument: a pointer to a -\verb+NULL+-terminated array of \verb+im_objects+. - -\item -Each \verb+im_object+ represents one argument to the function (either output -or input) in the form specified by the corresponding entry in the function's -argument descriptor. - -\end{itemize} - -The argument descriptor is an array of structures, each describing one -argument. For this example, it is: - -\begin{verbatim} -/* Describe the type of our function. - * One input int, and one output int. - */ -static im_arg_desc arg_types[] = { - IM_INPUT_INT( "in" ), - IM_OUTPUT_INT( "out" ) -}; -\end{verbatim} - -\verb+IM_INPUT_INT()+ and \verb+IM_OUTPUT_INT()+ are macros defined in -\verb++ which make argument types easy to define. Other -macros available are listed in table~\ref{tab:type}. - -\begin{tab2} -\begin{center} -\begin{tabular}{|l|l|l|} -\hline -Macro & Meaning & - \texttt{im\_object} has type \\ -\hline -\texttt{IM\_INPUT\_INT} & Input int & - \texttt{int *} \\ -\texttt{IM\_INPUT\_INTVEC} & Input vector of int & - \texttt{im\_intvec\_object *} \\ -\texttt{IM\_INPUT\_IMASK} & Input int array & - \texttt{im\_mask\_object *} \\ - -\texttt{IM\_OUTPUT\_INT} & Output int & - \texttt{int *} \\ -\texttt{IM\_INPUT\_INTVEC} & Output vector of int & - \texttt{im\_intvec\_object *} \\ -\texttt{IM\_OUTPUT\_IMASK} & Output int array to file & - \texttt{im\_mask\_object *} \\ - -\texttt{IM\_INPUT\_DOUBLE} & Input double & - \texttt{double *} \\ -\texttt{IM\_INPUT\_DOUBLEVEC} & Input vector of double & - \texttt{im\_realvec\_object *} \\ -\texttt{IM\_INPUT\_DMASK} & Input double array & - \texttt{im\_mask\_object *} \\ - -\texttt{IM\_OUTPUT\_DOUBLE} & Output double & - \texttt{double *} \\ -\texttt{IM\_OUTPUT\_DOUBLEVEC} & Output vector of double & - \texttt{im\_realvec\_object *} \\ -\texttt{IM\_OUTPUT\_DMASK} & Output double array to file & - \texttt{im\_mask\_object *} \\ -\texttt{IM\_OUTPUT\_DMASK\_STATS}& Output double array to screen & - \\ - -\texttt{IM\_OUTPUT\_COMPLEX} & Output complex & - \texttt{double *} \\ - -\texttt{IM\_INPUT\_STRING} & Input string & - \texttt{char *} \\ -\texttt{IM\_OUTPUT\_STRING} & Output string & - \texttt{char *} \\ - -\texttt{IM\_INPUT\_IMAGE} & Input image & - \texttt{IMAGE *} \\ -\texttt{IM\_INPUT\_IMAGEVEC} & Vector of input images & - \texttt{IMAGE **} \\ -\texttt{IM\_OUTPUT\_IMAGE} & Output image & - \texttt{IMAGE *} \\ -\texttt{IM\_RW\_IMAGE} & Read-write image & - \texttt{IMAGE *} \\ - -\texttt{IM\_INPUT\_DISPLAY} & Input display & - \texttt{im\_col\_display *} \\ -\texttt{IM\_OUTPUT\_DISPLAY} & Output display & - \texttt{im\_col\_display *} \\ - - -\texttt{IM\_INPUT\_GVALUE} & Input GValue & - \texttt{GValue *} \\ -\texttt{IM\_OUTPUT\_GVALUE} & Output GValue & - \texttt{GValue *} \\ - -\texttt{IM\_INPUT\_INTERPOLATE} & Input VipsInterpolate & - \texttt{VipsInterpolate *} \\ -\hline -\end{tabular} -\end{center} -\caption{Argument type macros\label{tab:type}} -\end{tab2} - -The argument to the type macro is the name of the argument. These names -are used by user-interface programs to provide feedback, and sometimes as -variable names. The order in which you list the arguments is the order in -which user-interfaces will present them to the user. You should use the -following conventions when selecting names and an order for your arguments: - -\begin{itemize} - -\item -Names should be entirely in lower-case and contain no special characters, -apart from the digits 0-9 and the underscore character `\_'. - -\item -Names should indicate the function of the argument. For example, -\verb+im_add()+ has the following argument names: - -\begin{verbatim} -example% vips -help im_add -vips: args: in1 in2 out -where: - in1 is of type "image" - in2 is of type "image" - out is of type "image" -add two images, from package - "arithmetic" -flags: - (PIO function) - (no coordinate transformation) - (point-to-point operation) -\end{verbatim} - -\item -You should order arguments with large input objects first, then output -objects, then any extra arguments or options. For example, \verb+im_extract()+ -has the following sequence of arguments: - -\begin{verbatim} -example% vips -help im_extract -vips: args: input output left top - width height channel -where: - input is of type "image" - output is of type "image" - left is of type "integer" - top is of type "integer" - width is of type "integer" - height is of type "integer" - channel is of type "integer" -extract area/band, from package - "conversion" -flags: - (PIO function) - (no coordinate transformation) - (point-to-point operation) -\end{verbatim} - -\end{itemize} - -This function sits over \verb+double_integer()+, providing VIPS with an -interface which it can call: - -\begin{verbatim} -/* Call our function via a VIPS - * im_object vector. - */ -static int -double_vec( im_object *argv ) -{ - int *in = (int *) argv[0]; - int *out = (int *) argv[1]; - - *out = double_integer( *in ); - - /* Always succeed. - */ - return( 0 ); -} -\end{verbatim} - -Finally, these two pieces of information (the argument description and -the VIPS-style function wrapper) can be gathered together into a function -description. - -\begin{verbatim} -/* Description of double_integer. - */ -static im_function double_desc = { - "double_integer", - "double an integer", - 0, - double_vec, - IM_NUMBER( arg_types ), - arg_types -}; -\end{verbatim} -\label{sec:number} - -\verb+IM_NUMBER()+ is a macro which returns the number of elements in a -static array. The \verb+flags+ field contains hints which user-interfaces -can use for various optimisations. At present, the possible values are: - -\begin{description} - -\item[\texttt{IM\_FN\_PIO}] -This function uses the VIPS PIO system (see \pref{sec:pio}). - -\item[\texttt{IM\_FN\_TRANSFORM}] -This the function transforms coordinates. - -\item[\texttt{IM\_FN\_PTOP}] -This is a point-to-point operation, that is, it can be replaced with a -look-up table. - -\item[\texttt{IM\_FN\_NOCACHE}] -This operation has side effects and should not be cached. Useful for video -grabbers, for example. - -\end{description} - -This function description now needs to be added to the VIPS function database. -VIPS groups sets of related functions together in packages. There is only -a single function in this example, so we can just write: - -\begin{verbatim} -/* Group up all the functions in this - * file. - */ -static im_function - *function_list[] = { - &double_desc -}; - -/* Define the package_table symbol. - * This is what VIPS looks for when - * loading the plugin. - */ -im_package package_table = { - "example", - IM_NUMBER( function_list ), - function_list -}; -\end{verbatim} - -The package has to be named \verb+package_table+, and has to be exported -from the file (that is, not a static). VIPS looks for a symbol of this name -when it opens your object file. - -This file needs to be made into a dynamically loadable object. On my machine, -I can do this with: - -\begin{verbatim} -example% gcc -fPIC -DPIC -c - `pkg-config vips-7.12 --cflags` - plug.c -o plug.o -example% gcc -shared plug.o - -o double.plg -\end{verbatim} - -You can now use \verb+double.plg+ with any of the VIPS applications which -support function dispatch. For example: - -\begin{verbatim} -example% vips -plugin double.plg \ - double_integer 12 -24 -example% -\end{verbatim} - -When VIPS starts up, it looks for a directory in the library directory called -\verb+vips-+, with the vips major and minor versions numbers as extensions, -and loads all files in there with the suffix \verb+.plg+. So for example, on -my machine, the plugin directory is \verb+/usr/lib/vips-7.16+ and any plugins -in that directory are automatically loaded into any VIPS programs on startup. - -\subsection{A more complicated example} - -This section lists the source for \verb+im_extract()+'s function -description. Almost all functions in the VIPS library have descriptors --- -if you are not sure how to write a description, it's usually easiest to -copy one from a similar function in the library. - -\begin{verbatim} -/* Args to im_extract. - */ -static im_arg_desc - extract_args[] = { - IM_INPUT_IMAGE( "input" ), - IM_OUTPUT_IMAGE( "output" ), - IM_INPUT_INT( "left" ), - IM_INPUT_INT( "top" ), - IM_INPUT_INT( "width" ), - IM_INPUT_INT( "height" ), - IM_INPUT_INT( "channel" ) -}; - -/* Call im_extract via arg vector. - */ -static int -extract_vec( im_object *argv ) -{ - IMAGE_BOX box; - - box.xstart = *((int *) argv[2]); - box.ystart = *((int *) argv[3]); - box.xsize = *((int *) argv[4]); - box.ysize = *((int *) argv[5]); - box.chsel = *((int *) argv[6]); - - return( im_extract( - argv[0], argv[1], &box ) ); -} - -/* Description of im_extract. - */ -static im_function - extract_desc = { - "im_extract", - "extract area/band", - IM_FN_PIO | IM_FN_TRANSFORM, - extract_vec, - NUMBER( extract_args ), - extract_args -}; -\end{verbatim} - -\subsection{Adding new types} - -The VIPS type mechanism is extensible. User plug-ins can add new types -and user-interfaces can (to a certain extent) provide interfaces to these -user-defined types. - -Here is the definition of \verb+im_arg_desc+: - -\begin{verbatim} -/* Describe a VIPS command argument. - */ -typedef struct { - char *name; - im_type_desc *desc; - im_print_obj_fn print; -} im_arg_desc; -\end{verbatim} - -The \verb+name+ field is the argument name above. The \verb+desc+ field -points to a structure defining the argument type, and the \verb+print+ field -is an (optionally \verb+NULL+) pointer to a function which VIPS will call -for output arguments after your function successfully completes and before -the object is destroyed. It can be used to print results to the terminal, -or to copy results into a user-interface layer. - -\begin{verbatim} -/* Success on an argument. This is - * called if the image processing - * function succeeds and should be - * used to (for example) print - * output. - */ -typedef int (*im_print_obj_fn) - ( im_object obj ); -\end{verbatim} - -\verb+im_type_desc+ is defined as: - -\begin{verbatim} -/* Describe a VIPS type. - */ -typedef struct { - im_arg_type type; - int size; - im_type_flags flags; - im_init_obj_fn init; - im_dest_obj_fn dest; -} im_type_desc; -\end{verbatim} - -Where \verb+im_arg_type+ is defined as - -\begin{verbatim} -/* Type names. You may define your - * own, but if you use one of these, - * then you should use the built-in - * VIPS type converters. - */ -#define IM_TYPE_IMAGEVEC "imagevec" -#define IM_TYPE_DOUBLEVEC "doublevec" -#define IM_TYPE_INTVEC "intvec" -#define IM_TYPE_DOUBLE "double" -#define IM_TYPE_INT "integer" -#define IM_TYPE_COMPLEX "complex" -#define IM_TYPE_STRING "string" -#define IM_TYPE_IMASK "intmask" -#define IM_TYPE_DMASK "doublemask" -#define IM_TYPE_IMAGE "image" -#define IM_TYPE_DISPLAY "display" -#define IM_TYPE_GVALUE "gvalue" -typedef char *im_arg_type; -\end{verbatim} - -In other words, it's just a string. When you add a new type, you just need -to choose a new unique string to name it. Be aware that the string is printed -to the user by various parts of VIPS, and so needs to be ``human-readable''. -The flags are: - -\begin{verbatim} -/* These bits are ored together to - * make the flags in a type - * descriptor. - * - * IM_TYPE_OUTPUT: set to indicate - * output, otherwise input. - * - * IM_TYPE_ARG: Two ways of making - * an im_object --- with and without - * a command-line string to help you - * along. Arguments with a string - * are thing like IMAGE descriptors, - * which require a filename to - * initialise. Arguments without are - * things like output numbers, where - * making the object simply involves - * allocating storage. - */ - -typedef enum { - IM_TYPE_OUTPUT = 0x1, - IM_TYPE_ARG = 0x2 -} im_type_flags; -\end{verbatim} - -And the \verb+init+ and \verb+destroy+ functions are: - -\begin{verbatim} -/* Initialise and destroy objects. - * The "str" argument to the init - * function will not be supplied - * if this is not an ARG type. - */ -typedef int (*im_init_obj_fn) - ( im_object *obj, char *str ); -typedef int (*im_dest_obj_fn) - ( im_object obj ); -\end{verbatim} - -As an example, here is the definition for a new type of unsigned -integers. First, we need to define the \verb+init+ and \verb+print+ -functions. These transform objects of the type to and from string -representation. - -\begin{verbatim} -/* Init function for unsigned int - * input. - */ -static int -uint_init( im_object *obj, char *str ) -{ - unsigned int *i = (int *) *obj; - - if( sscanf( str, "%d", i ) != 1 || - *i < 0 ) { - im_error( "uint_init", - "bad format" ); - return( -1 ); - } - - return( 0 ); -} - -/* Print function for unsigned int - * output. - */ -static int -uint_print( im_object obj ) -{ - unsigned int *i = - (unsigned int *) obj; - - printf( "%d\n", (int) *i ); - - return( 0 ); -} -\end{verbatim} - -Now we can define the type itself. We make two of these --- one for unsigned -int used as input, and one for output. - -\begin{verbatim} -/* Name our type. - */ -#define TYPE_UINT "uint" - -/* Input unsigned int type. - */ -static im_type_desc input_uint = { - TYPE_UINT, /* Its an int */ - sizeof( unsigned int ),/* Memory */ - IM_TYPE_ARG, /* Needs arg */ - uint_init, /* Init */ - NULL /* Destroy */ -}; - -/* Output unsigned int type. - */ -static im_type_desc output_uint = { - TYPE_UINT, /* It's an int */ - sizeof( unsigned int ),/* Memory */ - IM_TYPE_OUTPUT, /* It's output */ - NULL, /* Init */ - NULL /* Destroy */ -}; -\end{verbatim} - -Finally, we can define two macros to make structures of type -\verb+im_arg_desc+ for us. - -\begin{verbatim} -#define INPUT_UINT( S ) \ - { S, &input_uint, NULL } -#define OUTPUT_UINT( S ) \ - { S, &output_uint, uint_print } -\end{verbatim} - -For more examples, see the definitions for the built-in VIPS types. - -\subsection{Using function dispatch in your application} - -VIPS provides a set of functions for adding new image processing functions -to the VIPS function database, finding functions by name, and calling -functions. See the manual pages for full details. - -\subsubsection{Adding and removing functions} - -\begin{verbatim} -im_package *im_load_plugin( - const char *name ); -\end{verbatim} - -This function opens the named file, searches it for a symbol named -\verb+package_table+, and adds any functions it finds to the VIPS function -database. When you search for a function, any plug-ins are searched first, -so you can override standard VIPS function with your own code. - -The function returns a pointer to the package it added, or \verb+NULL+ -on error. - -\begin{verbatim} -int im_close_plugins( void ) -\end{verbatim} - -This function closes all plug-ins, removing then from the VIPS function -database. It returns non-zero on error. - -\subsubsection{Searching the function database} - -\begin{verbatim} -void *im_map_packages( - im_list_map_fn fn, void *a ) -\end{verbatim} - -This function applies the argument function \verb+fn+ to every package -in the database, starting with the most recently added package. As with -\verb+im_list_map()+, the argument function should return \verb+NULL+ -to continue searching, or non-\verb+NULL+ to terminate the search -early. \verb+im_map_packages()+ returns \verb+NULL+ if \verb+fn+ returned -\verb+NULL+ for all arguments. The extra argument \verb+a+ is carried around -by VIPS for your use. - -For example, this fragment of code prints the names of all loaded packages -to \verb+fd+: - -\begin{verbatim} -static void * -print_package_name( im_package *pack, - FILE *fp ) -{ - (void) fprintf( fp, - "package: \"%s\"\n", - pack->name ); - - /* Continue search. - */ - return( NULL ); -} - -static void -print_packages( FILE *fp ) -{ - (void) im_map_packages( - (im_list_map_fn) - print_package_name, fp ); -} -\end{verbatim} - -VIPS defines three convenience functions based on \verb+im_map_packages()+ -which simplify searching for specific functions: - -\begin{verbatim} -im_function * - im_find_function( char *name ) -im_package * - im_find_package( char *name ) -im_package * - im_package_of_function( char *name ) -\end{verbatim} - -\subsubsection{Building argument structures and running commands} - -\begin{verbatim} -int im_free_vargv( im_function *fn, - im_object *vargv ) -int im_allocate_vargv( - im_function *fn, - im_object *vargv ) -\end{verbatim} - -These two functions allocate space for and free VIPS argument lists. The -allocate function simply calls \verb+im_malloc()+ to allocate any store -that the types require (and also initializes it to zero). The free function -just calls \verb+im_free()+ for any storage that was allocated. - -Note that neither of these functions calls the \verb+init+, \verb+dest+ -or \verb+print+ functions for the types --- that's up to you. - -\begin{verbatim} -int im_run_command( char *name, - int argc, char **argv ) -\end{verbatim} - -This function does everything. In effect, - -\begin{verbatim} -im_run_command( "im_invert", 2, - { "fred.v", "fred2.v", NULL } ) -\end{verbatim} - -is exactly equivalent to - -\begin{verbatim} -system( "vips im_invert fred.v " - "fred2.v" ) -\end{verbatim} - -but no process is forked. diff --git a/doc/src/html.cfg b/doc/src/html.cfg deleted file mode 100644 index c8033ad9..00000000 --- a/doc/src/html.cfg +++ /dev/null @@ -1,17 +0,0 @@ -% configuration file for output of nipguide as html -\Preamble{html} -\begin{document} - -% stop the mono font shrinkage we do for paper output -\renewenvironment{ctd}{\begin{quote}\tt}{\end{quote}} - -% make a label -% in html, write an extra label which we can link to nip's help system -\renewcommand{\mylabel}[1]{ - \label{#1} - \HCode{} -} - -% supress " on page xx" if we're making HTML -\renewcommand{\onpage}[1]{} -\EndPreamble diff --git a/doc/src/interpolate.tex b/doc/src/interpolate.tex deleted file mode 100644 index 4478720a..00000000 --- a/doc/src/interpolate.tex +++ /dev/null @@ -1,162 +0,0 @@ -\section{Interpolators} -\label{sec:interpolate} - -VIPS has a general system for representing pixel interpolators. You can select -an interpolator to pass to other VIPS operations, such as \verb+im_affinei()+, -you can add new interpolators, and you can write operations which take a -general interpolator as a parameter. - -An interpolator is a function of the form: - -\begin{verbatim} -typedef void (*VipsInterpolateMethod)( VipsInterpolate *, - PEL *out, REGION *in, double x, double y ); -\end{verbatim} - -\noindent -given the set of input pixels \verb+in+, it has to calculate a value for the -fractional position $(x, y)$ and write this value to the memory pointed to by -\verb+out+. - -VIPS uses corner convention, so the value of pixel $(0, 0)$ is the value of -the surface the interpolator fits at the fractional position $(0.0, 0.0)$. - -\subsection{How an interpolator is represented} - -See the man page for \verb+VipsInterpolate+ for full details, but briefly, -an interpolator is a subclass of \verb+VipsInterpolate+ implementing the -following items: - -\begin{itemize} -\item -An interpolation method, with the type signature above. - -\item -A function \verb+get_window_size()+ which returns the size of the area of -pixels that the interpolator needs in order to calculate a value. For example, -a bilinear interpolator needs the four pixels surrounding the point to be -calculated, or a 2 by 2 window, so window size should be 2. - -\item -Or if the window size is constant, you can leave \verb+get_window_size()+ -NULL and just set the int value \verb+window_size+. - -\end{itemize} - -\subsection{A sample interpolator} - -As an example, \fref{fg:newinterpolator} shows how to register a new -interpolator in a plugin. - -\begin{fig2} -\begin{verbatim} -// This interpolator adds no new members. -typedef VipsInterpolate Myinterpolator; -typedef VipsInterpolateClass MyinterpolatorClass; - -G_DEFINE_TYPE( Myinterpolator, myinterpolator, VIPS_TYPE_INTERPOLATE ); - -static void -myinterpolator_interpolate( VipsInterpolate *interpolate, - PEL *out, REGION *in, double x, double y ) -{ - MyinterpolatorClass *class = - MYINTERPOLATOR_GET_CLASS( interpolate ); - - /* Nearest-neighbor. - */ - memcpy( out, - IM_REGION_ADDR( in, floor( x ), floor( y ) ), - IM_IMAGE_SIZEOF_PEL( in->im ) ); -} - -static void -myinterpolator_class_init( MyinterpolatorClass *class ) -{ - VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsInterpolateClass *interpolate_class = (VipsInterpolateClass *) class; - - object_class->nickname = "myinterpolator"; - object_class->description = _( "My interpolator" ); - - interpolate_class->interpolate = myinterpolator_interpolate; -} - -static void -myinterpolate_init( Myinterpolate *object ) -{ -} - -char * -g_module_check_init( GModule *self ) -{ - // register the type - myinterpolator_get_type(); -} -\end{verbatim} -\caption{Registering an interpolator in a plugin} -\label{fg:newinterpolator} -\end{fig2} - -\subsection{Writing a VIPS operation that takes an interpolator as an argument} - -Operations just take a \verb+VipsInterpolate+ as an argument, for example: - -\begin{verbatim} -int im_affinei_all( IMAGE *in, IMAGE *out, - VipsInterpolate *interpolate, - double a, double b, double c, double d, - double dx, double dy ); -\end{verbatim} - -To use the interpolator, use \verb+vips_interpolate()+: - -\begin{verbatim} -void vips_interpolate( VipsInterpolate *interpolate, - PEL *out, REGION *in, double x, double y ); -\end{verbatim} - -\noindent -This looks up the interpolate method for the object and calls it for you. - -You can save the cost of the lookup in an inner loop with -\verb+vips_interpolate_get_method()+: - -\begin{verbatim} -VipsInterpolateMethod - vips_interpolate_get_method( - VipsInterpolate *interpolate ); -\end{verbatim} - -\subsection{Passing an interpolator to a VIPS operation} - -You can build an instance of a \verb+VipsInterpolator+ with -the \verb+vips_object_*()+ family of functions, see \pref{sec:object}. - -Convenience functions return a static instance of one of the standard -interpolators: - -\begin{verbatim} -VipsInterpolate *vips_interpolate_nearest_static( void ); -VipsInterpolate *vips_interpolate_bilinear_static( void ); -\end{verbatim} - -\noindent -Don't free the result. - -Finally, \verb+vips_interpolate_new()+ makes a \verb+VipsInterpolate+ from a -nickname: - -\begin{verbatim} -VipsInterpolate *vips_interpolate_new( const char *nickname ); -\end{verbatim} - -For example: - -\begin{verbatim} -VipsInterpolate *interpolate = vips_interpolate_new( "nohalo" ); -\end{verbatim} - -\noindent -You must drop your ref after you're done with the object with -\verb+g_object_unref()+. diff --git a/doc/src/iosys.tex b/doc/src/iosys.tex deleted file mode 100644 index f79b797d..00000000 --- a/doc/src/iosys.tex +++ /dev/null @@ -1,836 +0,0 @@ -\section{Core C API} - -VIPS is built on top of several other libraries, two of which, glib and -gobject, are exposed at various points in the C API. - -You can read up on glib at the GTK+ website: - -\begin{verbatim} -http://www.gtk.org -\end{verbatim} - -There's also an excellent book by Matthias Warkus, \emph{The Official -GNOME 2 Developer's Guide}, which covers the same material in a tutorial -manner. - -\subsection{Startup} - -Before calling any VIPS function, you need to start VIPS up: - -\begin{verbatim} -int im_init_world( const char *argv0 ); -\end{verbatim} - -The \verb+argv0+ argument is the value of \verb+argv[0]+ your -program was passed by the host operating system. VIPS uses this with -\verb+im_guess_prefix()+ and \verb+im_guess_libdir()+ to try to find various -VIPS data files. - -If you don't call this function, VIPS will call it for you the first time you -use a VIPS function. But it won't be able to get the \verb+argv0+ value for -you, so it may not be able to find it's data files. - -VIPS also offers the optional: - -\begin{verbatim} -GOptionGroup *im_get_option_group( void ); -\end{verbatim} - -You can use this with GOption to parse your program's command-line arguments. -It adds several useful VIPS flags, including \verb+--vips-concurrency+. - -\fref{fg:hello} shows both these functions in use. Again, the GOption stuff is -optional and just lets VIPS add some flags to your program. You do need the -\verb+im_init_world()+ though. - -\begin{fig2} -\begin{verbatim} -#include -#include - -static gboolean print_stuff; - -static GOptionEntry options[] = { - { "print", 'p', 0, G_OPTION_ARG_NONE, &print_stuff, - "print \"hello world!\"", NULL }, - { NULL } -}; - -int -main( int argc, char **argv ) -{ - GOptionContext *context; - GError *error = NULL; - - if( im_init_world( argv[0] ) ) - error_exit( "unable to start VIPS" ); - - context = g_option_context_new( "- my program" ); - g_option_context_add_main_entries( context, - options, "main" ); - g_option_context_add_group( context, im_get_option_group() ); - if( !g_option_context_parse( context, &argc, &argv, &error ) ) { - if( error ) { - fprintf( stderr, "%s\n", error->message ); - g_error_free( error ); - } - error_exit( "try \"%s --help\"", g_get_prgname() ); - } - g_option_context_free( context ); - - if( print_stuff ) - printf( "hello, world!\n" ); - - return( 0 ); -} -\end{verbatim} -\caption{Hello World for VIPS} -\label{fg:hello} -\end{fig2} - -\subsection{Image descriptors} - -The base level of the VIPS I/O system provides \verb+IMAGE+ descriptors. -An image represented by a descriptor may be an image file on disc, an area -of memory that has been allocated for the image, an output file, a delayed -computation, and so on. Programs need (usually) only know that they have -a descriptor, they do not see many of the details. \fref{fg:image} -shows the definition of the \verb+IMAGE+ descriptor. - -\begin{fig2} -\begin{verbatim} -typedef struct { - /* Fields from image header. - */ - int Xsize; /* Pels per line */ - int Ysize; /* Lines */ - int Bands; /* Number of bands */ - int Bbits; /* Bits per band */ - int BandFmt; /* Band format */ - int Coding; /* Coding type */ - int Type; /* Type of file */ - float XRes; /* Horizontal res in pels/mm */ - float YRes; /* Vertical res in pels/mm */ - int Length; /* Obsolete (unused) */ - short Compression; /* Obsolete (unused) */ - short Level; /* Obsolete (unused) */ - int Xoffset; /* Position of origin */ - int Yoffset; - - /* Derived fields that may be read by the user. - */ - char *filename; /* File name */ - im_time_t *time; /* Timing for eval callback */ - int kill; /* Set to non-zero to block eval */ - - ... and lots of other private fields used by VIPS for - ... housekeeping. -} IMAGE; -\end{verbatim} -\caption{The \texttt{IMAGE} descriptor} -\label{fg:image} -\end{fig2} - -The first set of fields simply come from the image file header: -see \pref{sec:header} for a full description of all the fields. The next -set are maintained for you by the VIPS I/O system. \verb+filename+ is the -name of the file that this image came from. If you have attached an eval -callback to this image, \verb+time+ points to a set of timing statistics -which can be used by user-interfaces built on VIPS to provide feedback -about the progress of evaluation --- see \pref{sec:eval}. Finally, if you -set \verb+kill+ to non-zero, VIPS will block any pipelines which use this -descriptor as an intermediate. See \pref{sec:block}. - -The remaining fields are private and are used by VIPS for housekeeping. - -\subsection{Header fields} -\label{sec:fields} - -You can access header fields either directly (as \verb+im->Xsize+, for -example) or programmatically with \verb+im_header_int()+ and friends. For -example: - -\begin{verbatim} -int i; - -im_header_int( im, "Xsize", &i ); -\end{verbatim} - -There's also \verb+im_header_map()+ to loop over header fields, and -\verb+im_header_get_type+ to test the type of fields. These functions work for -image meta fields as well, see \pref{sec:meta}. - -\subsection{Opening and closing} -\label{sec:open} - -Descriptors are created with \verb+im_open()+. You can also read images with -the format system: see \pref{sec:format}. The two APIs are complimentary, -though \verb+im_open()+ is more useful. - -At the command-line, try: - -\begin{verbatim} -$ vips list classes -\end{verbatim} - -/noindent -to see a list of all the supported file formats. - -\verb+im_open()+ takes a file name and a string representing the mode with -which the descriptor is to be opened: - -\begin{verbatim} -IMAGE *im_open( const char *filename, - const char *mode ) -\end{verbatim} - -The possible values for mode are: - -\begin{description} - -\item[\texttt{"r"}] -The file is opened read-only. -If you open a non-VIPS image, or a VIPS image written on a machine with a -different byte ordering, \verb+im_open()+ will automatically convert it to -native VIPS format. If the underlying file does not support random access -(JPEG, for example), the entire file will be converted in memory. - -VIPS can read images in many file formats. You can control the details of -the conversion with extra characters embedded in the filename. For example: - -\begin{verbatim} -fred = im_open( "fred.tif:2", - "r" ); -\end{verbatim} - -\noindent -will read page 2 of a multi-page TIFF. See the man pages for details. - -\item[\texttt{"w"}] -An \verb+IMAGE+ descriptor is created which, when written to, will write -pixels to disc in the specified file. Any existing file of that name is -deleted. - -VIPS looks at the filename suffix to determine the save format. If there -is no suffix, or the filename ends in \verb+".v"+, the image is written -in VIPS native format. - -If you want to control the details of the conversion to the disc format (such -as setting the Q factor for a JPEG, for example), you embed extra control -characters in the filename. For example: - -\begin{verbatim} -fred = im_open( "fred.jpg:95", - "w" ); -\end{verbatim} - -\noindent -writes to \verb+fred+ will write a JPEG with Q 95. Again, see the man pages -for the conversion functions for details. - -\item[\texttt{"t"}] -As the \verb+"w"+ mode, but pels written to the descriptor will be saved -in a temporary memory buffer. - -\item[\texttt{"p"}] -This creates a special partial image. Partial images are used to join VIPS -operations together, see \pref{sec:joinup}. - -\item[\texttt{"rw"}] -As the \verb+"r"+ mode, but the image is mapped into the caller's address -space read-write. This mode is only provided for the use of paintbox-style -applications which need to directly modify an image. Most programs should -use the \verb+"w"+ mode for image output. - -\end{description} - -If an error occurs opening the image, \verb+im_open()+ calls -\verb+im_error()+ with a string describing the cause of the error and -returns \verb+NULL+. \verb+im_error()+ has type - -\begin{verbatim} -void im_error( const char *domain, - const char *format, ... ) -\end{verbatim} - -\noindent -The first argument is a string giving the name of the thing that raised -the error (just \verb+"im_open"+, for example). The format and subsequent -arguments work exactly as \verb+printf()+. It formats the message and -appends the string formed to the error log. You can get a pointer to the -error text with \verb+im_error_buffer()+. - -\begin{verbatim} -const char *im_error_buffer() -\end{verbatim} - -\noindent -Applications may display this string to give users feedback about the -cause of the error. The VIPS exit function, \verb+error_exit()+, prints -\verb+im_error_buffer()+ to \verb+stderr+ and terminates the program with an -error code of 1. - -\begin{verbatim} -void error_exit( const char *format, - ... ) -\end{verbatim} - -\noindent -There are other functions for handling errors: see the man page for -\verb+im_error()+. - -Descriptors are closed with \verb+im_close()+. It has type: - -\begin{verbatim} -int im_close( IMAGE *im ) -\end{verbatim} - -\verb+im_close()+ returns 0 on success and non-zero on error. - -\subsection{Examples} -\label{sec:examples} - -As an example, \fref{fg:widthheight} will print the width and height -of an image stored on disc. - -\begin{fig2} -\begin{verbatim} -#include -#include - -int -main( int argc, char **argv ) -{ - IMAGE *im; - - /* Check arguments. - */ - if( im_init_world( argv[0] ) ) - error_exit( "unable to start VIPS" ); - if( argc != 2 ) - error_exit( "usage: %s filename", argv[0] ); - - /* Open file. - */ - if( !(im = im_open( argv[1], "r" )) ) - error_exit( "unable to open %s for input", argv[1] ); - - /* Process. - */ - printf( "width = %d, height = %d\n", im->Xsize, im->Ysize ); - - /* Close. - */ - if( im_close( im ) ) - error_exit( "unable to close %s", argv[1] ); - - return( 0 ); -} -\end{verbatim} -\label{fg:widthheight} -\caption{Print width and height of an image} -\end{fig2} - -To compile this example, use: - -\begin{verbatim} -cc `pkg-config vips-7.14 \ - --cflags --libs` myfunc.c -\end{verbatim} - -As a slightly more complicated example, \fref{fg:negative} -will calculate the photographic negative of an image. - -\begin{fig2} -\begin{verbatim} -#include -#include - -int -main( int argc, char **argv ) -{ - IMAGE *in, *out; - - /* Check arguments. - */ - if( im_init_world( argv[0] ) ) - error_exit( "unable to start VIPS" ); - if( argc != 3 ) - error_exit( "usage: %s infile outfile", argv[0] ); - - /* Open images for read and write, invert, update the history with our - * args, and close. - */ - if( !(in = im_open( argv[1], "r" )) || - !(out = im_open( argv[2], "w" )) || - im_invert( in, out ) || - im_updatehist( out, argc, argv ) || - im_close( in ) || - im_close( out ) ) - error_exit( argv[0] ); - - return( 0 ); -} -\end{verbatim} -\label{fg:negative} -\caption{Find photographic negative} -\end{fig2} - -\subsection{Metadata} -\label{sec:meta} - -VIPS lets you attach arbitrary metadata to an IMAGE. For example, ICC -profiles, EXIF tags, image history, whatever you like. VIPS will efficiently -propagate metadata as images are processed (usually just by copying -pointers) and will automatically save and load metadata from VIPS files -(see \pref{sec:header}). - -A piece of metadata is a value and an identifying name. A set of -convenience functions let you set and get int, double, string and blob. For -example: - -\begin{verbatim} -int im_meta_set_int( IMAGE *, - const char *field, int ); -int im_meta_get_int( IMAGE *, - const char *field, int * ); -\end{verbatim} - -So you can do: - -\begin{verbatim} -if( im_meta_set_int( im, "poop", 42 ) ) - return( -1 ); -\end{verbatim} - -\noindent -to create an int called \verb+"poop"+, then at some later point (possibly much, -much later), in an image distantly derived from \verb+im+, you can use: - -\begin{verbatim} -int i; - -if( im_meta_get_int( im, "poop", &i ) ) - return( -1 ); -\end{verbatim} - -\noindent -And get the value 42 back. - -You can use \verb+im_meta_set()+ and \verb+im_meta_get()+ to attach arbitrary -\verb+GValue+ to images. See the man page for \verb+im_meta_set()+ for -full details. - -You can test for a field being present with \verb+im_meta_get_type()+ (you'll -get \verb+G_TYPE_INT+ back for \verb+"poop"+, for example, or 0 if it is not -defined for this image). - -\subsection{History} -\label{sec:history} - -VIPS tracks the history of an image, that is, the sequence of operations which -have led to the creation of an image. You can view a VIPS image's history with -the \verb+header+ command, or with \nip{}'s \ct{View Header} menu. Whenever an -application performs an action, it should append a line of shell script to the -history which would perform the same action. - -The call to \verb+im_updatehist()+ in \fref{fg:negative} adds a line to the -image history noting the invocation of this program, its arguments, and the -time and date at which it was run. You may also find \verb+im_histlin()+ -helpful. It has type: - -\begin{verbatim} -void im_histlin( IMAGE *im, - const char *fmt, ... ) -\end{verbatim} - -\noindent -It formats its arguments as \verb+printf()+ and appends the string formed -to the image history. - -You read an image's history with \verb+im_history_get()+. It returns the -entire history of an image, one action per line. No need to free the result. - -\begin{verbatim} -const char * - im_history_get( IMAGE *im ); -\end{verbatim} - -\subsection{Eval callbacks} -\label{sec:eval} - -VIPS lets you attach callbacks to image descriptors. These are functions -you provide which VIPS will call when certain events occur. See -\pref{sec:callback} for more detail. - -Eval callbacks are called repeatedly during evaluation and can be used by -user-interface programs to give feedback about the progress of evaluation. - -\subsection{Detailed rules for descriptors} - -These rules are intended to answer awkward questions. - -\begin{enumerate} - -\item -You can output to a descriptor only once. - -\item -You can use a descriptor as an input many times. - -\item -You can only output to a descriptor that was opened with modes \verb+"w"+, -\verb+"t"+ and \verb+"p"+. - -\item -You can only use a descriptor as input if it was opened with modes \verb+"r"+ -or \verb+"rw"+. - -\item -If you have output to a descriptor, you may subsequently use it as an -input. \verb+"w"+ descriptors are automatically changed to \verb+"r"+ -descriptors. - -If the function you are passing the descriptor to uses WIO (see -\pref{sec:limit}), then \verb+"p"+ descriptors become \verb+"t"+. -If the function you are passing the descriptor to uses PIO, then \verb+"p"+ -descriptors are unchanged. - -\end{enumerate} - -\subsection{Automatic resource deallocation} - -VIPS lets you allocate resources local to an image descriptor, that is, -when the descriptor is closed, all resources which were allocated local to -that descriptor are automatically released for you. - -\subsubsection{Local image descriptors} - -VIPS provides a function which will open a new image local to -an existing image. \verb+im_open_local()+ has type: - -\begin{verbatim} -IMAGE *im_open_local( IMAGE *im, - const char *filename, - const char *mode ) -\end{verbatim} - -It behaves exactly as \verb+im_open()+, except that you do not need to close -the descriptor it returns. It will be closed automatically when its parent -descriptor \verb+im+ is closed. - -\begin{fig2} -\begin{verbatim} -/* Add another image to the accumulated total. - */ -static int -sum1( IMAGE *acc, IMAGE **in, int nin, IMAGE *out ) -{ - IMAGE *t; - - if( nin == 0 ) - /* All done ... copy to out. - */ - return( im_copy( acc, out ) ); - - /* Make a new intermediate, and add to it.. - */ - return( !(t = im_open_local( out, "sum1:1", "p" )) || - im_add( acc, in[0], t ) || - sum1( t, in + 1, nin - 1, out ) ); -} - -/* Sum the array of images in[]. nin is the number of images in - * in[], out is the descriptor we write the final image to. - */ -int -total( IMAGE **in, int nin, IMAGE *out ) -{ - /* Check that we have at least one image. - */ - if( nin <= 0 ) { - im_error( "total", "nin should be > 0" ); - return( -1 ); - } - - /* More than 1, sum recursively. - */ - return( sum1( in[0], in + 1, nin - 1, out ) ); -} -\end{verbatim} -\caption{Sum an array of images} -\label{fg:addemup} -\end{fig2} - -\fref{fg:addemup} is a function which will sum an array of images. -We need never close any of the (unknown) number of intermediate images which -we open. They will all be closed for us by our caller, when our caller -finally closes \verb+out+. VIPS lets local images themselves have local -images and automatically makes sure that all are closed in the correct order. - -It is very important that these intermediate images are made local to -\verb+out+ rather than \verb+in+, for reasons which should become apparent -in the section on combining operations below. - -There's also \verb+im_open_local_array()+ for when you need a lot of local -descriptors, see the man page. - -\subsubsection{Local memory allocation} -\label{sec:malloc} - -VIPS includes a set of functions for memory allocation local to an image -descriptor. The base memory allocation function is \verb+im_malloc()+. It -has type: - -\begin{verbatim} -void *im_malloc( IMAGE *, size_t ) -\end{verbatim} - -It operates exactly as the standard \verb+malloc()+ C library function, -except that the area of memory it allocates is local to an image. -If \verb+im_malloc()+ is unable to allocate memory, it returns -\verb+NULL+. If you pass \verb+NULL+ instead of a valid image descriptor, -then \verb+im_malloc()+ allocates memory globally and you must free it -yourself at some stage. - -To free memory explicitly, use \verb+im_free()+: - -\begin{verbatim} -int im_free( void * ) -\end{verbatim} - -\noindent -\verb+im_free()+ always returns 0, so you can use it as an argument to a -callback. - -Three macros make memory allocation even easier. \verb+IM_NEW()+ allocates -a new object. You give it a descriptor and a type, and it returns a pointer -to enough space to hold an object of that type. It has type: - -\begin{verbatim} -type-name *IM_NEW( IMAGE *, type-name ) -\end{verbatim} - -The second macro, \verb+IM_ARRAY()+, is very similar, but allocates -space for an array of objects. Note that, unlike the usual \verb+calloc()+ -C library function, it does not initialise the array to zero. It has type: - -\begin{verbatim} -type-name *IM_ARRAY( IMAGE *, int, type-name ) -\end{verbatim} - -Finally, \verb+IM_NUMBER()+ returns the number of elements in an array of -defined size. See the man pages for a series of examples, or -see \pref{sec:number}. - -\subsubsection{Other local operations} - -The above facilities are implemented with the VIPS core function -\verb+im_add_close_callback()+. You can use this facility to make your own -local resource allocators for other types of object --- see the manual page -for more help. - -\subsection{Error handling} - -All VIPS operations return 0 on success and non-zero on error, setting -\verb+im_error()+. As a consequence, when a VIPS function fails, you do not -need to generate an error message --- you can simply propagate the error back -up to your caller. If however you detect some error yourself (for example, -the bad parameter in the example above), you must call \verb+im_error()+ -to let your caller know what the problem was. - -VIPS provides two more functions for error message handling: \verb+im_warn()+ -and \verb+im_diag()+. These are intended to be used for less serious -messages, as their names suggest. Currently, they simply format and print -their arguments to \verb+stderr+, optionally suppressed by the setting of an -environment variable. Future releases of VIPS may allow more sophisticated -trapping of these functions to allow their text to be easily presented to -the user by VIPS applications. See the manual pages. - -\subsection{Joining operations together} -\label{sec:joinup} - -VIPS lets you join image processing operations together so that they -behave as a single unit. \fref{fg:join} shows the definition of the -function \verb+im_Lab2disp()+ from the VIPS library. This function converts -an image in \cielab{} colour space to an RGB image for a monitor. The -monitor characteristics (gamma, phosphor type, etc.) are described by the -\verb+im_col_display+ structure, see the man page for \verb+im_col_XYZ2rgb()+. - -\begin{fig2} -\begin{verbatim} -int -im_Lab2disp( IMAGE *in, IMAGE *out, struct im_col_display *disp ) -{ - IMAGE *t1; - - if( !(t1 = im_open_local( out, "im_Lab2disp:1", "p" )) || - im_Lab2XYZ( in, t1 ) || - im_XYZ2disp( t1, out, disp ) ) - return( -1 ); - - return( 0 ); -} -\end{verbatim} -\caption{Two image-processing operations joined together} -\label{fg:join} -\end{fig2} - -The special \verb+"p"+ mode (for partial) used to open the image descriptor -used as the intermediate image in this function `glues' the two operations -together. When you use \verb+im_Lab2disp()+, the two operations inside it -will execute together and no extra storage is necessary for the intermediate -image (\verb+t1+ in this example). This is important if you want to process -images larger than the amount of RAM you have on your machine. - -As an added bonus, if you have more than one CPU in your computer, the work -will be automatically spread across the processors for you. You can control -this parallelization with the \verb+IM_CONCURRENCY+ environment variable, -\verb+im_concurrency_set()+, and with the \verb+--vips-concurrency+ -command-line switch. See the man page for \verb+im_generate()+. - -\subsubsection{How it works} - -When a VIPS function is asked to output to a \verb+"p"+ image descriptor, -all the fields in the descriptor are set (the output image size and type -are set, for example), but no image data is actually generated. Instead, -the function attaches callbacks to the image descriptor which VIPS can use -later to generate any piece of the output image that might be needed. - -When a VIPS function is asked to output to a \verb+"w"+ or a \verb+"t"+ -descriptor (a real disc file or a real memory buffer), it evaluates -immediately and its evaluation in turn forces the evaluation of any earlier -\verb+"p"+ images. - -In the example in \fref{fg:join}, whether or not any pixels are really -processed when \verb+im_Lab2disp()+ is called depends upon the mode in -which \verb+out+ was opened. If \verb+out+ is also a partial image, then -no pixels will be calculated --- instead, a pipeline of VIPS operations -will be constructed behind the scenes and attached to \verb+out+. - -Conversely, if \verb+out+ is a real image (that is, either \verb+"w"+ -or \verb+"t"+), then the final VIPS operation in the function -(\verb+im_XYZ2disp()+) will output the entire image to \verb+out+, causing -the earlier parts of \verb+im_Lab2disp()+ (and indeed possibly some earlier -pieces of program, if \verb+in+ was also a \verb+"p"+ image) to run. - -When a VIPS pipeline does finally evaluate, all of the functions in the -pipeline execute together, sucking image data through the system in small -pieces. As a consequence, no intermediate images are generated, large -amounts of RAM are not needed, and no slow disc I/O needs to be performed. - -Since VIPS partial I/O is demand-driven rather than data-driven this works -even if some of the operations perform coordinate transformations. We could, -for example, include a call to \verb+im_affine()+, which performs -arbitrary rotation and scaling, and everything would still work correctly. - -\subsubsection{Pitfalls with partials} - -To go with all of the benefits that partial image I/O brings, there are -also some problems. The most serious is that you are often not quite certain -when computation will happen. This can cause problems if you close an input -file, thinking that it is finished with, when in fact that file has not -been processed yet. Doing this results in dangling pointers and an almost -certain core-dump. - -You can prevent this from happening with careful use of -\verb+im_open_local()+. If you always open local to your output image, -you can be sure that the input will not be closed before the output has been -generated to a file or memory buffer. You do not need to be so careful with -non-image arguments. VIPS functions which take extra non-image arguments -(a matrix, perhaps) are careful to make their own copy of the object before -returning. - -\subsubsection{Non-image output} - -Some VIPS functions consume images, but make no image -output. \verb+im_stats()+ for example, scans an image calculating various -statistical values. When you use \verb+im_stats()+, it behaves as a data -sink, sucking image data through any earlier pipeline stages. - -\subsubsection{Calculating twice} - -In some circumstances, the same image data can be generated twice. -\fref{fg:thrmean} is a function which finds the mean value of an -image, and writes a new image in which pixels less than the mean are set to -0 and images greater than the mean are set to 255. - -\begin{fig2} -\begin{verbatim} -int -threshold_at_mean( IMAGE *in, IMAGE *out ) -{ - double mean; - - if( im_avg( in, &mean ) || - im_moreconst( in, out, mean ) ) - return( -1 ); - - return( 0 ); -} -\end{verbatim} -\caption{Threshold an image at the mean value} -\label{fg:thrmean} -\end{fig2} - -This seems straightforward --- but consider if image \verb+in+ were a -\verb+"p"+, and represented the output of a large pipeline of operations. The -call to \verb+im_avg()+ would force the evaluation of the entire pipeline, -and throw it all away, keeping only the average value. The subsequent call to -\verb+im_moreconst()+ will cause the pipeline to be evaluated a second time. - -When designing a program, it is sensible to pay attention to these -issues. It might be faster, in some cases, to output to a file before -calling \verb+im_avg()+, find the average of the disc file, and then run -\verb+im_moreconst()+ from that. There's also \verb+im_cache()+ which can keep -recent parts of a very large image. - -\subsubsection{Blocking computation} -\label{sec:block} - -\verb+IMAGE+ descriptors have a flag called \verb+kill+ which can be used -to block computation. If \verb+im->kill+ is set to a non-zero value, -then any VIPS pipelines which use \verb+im+ as an intermediate will fail -with an error message. This is useful for user-interface writers --- -suppose your interface is forced to close an image which many other images -are using as a source of data. You can just set the \verb+kill+ flag in all -of the deleted image's immediate children and prevent any dangling pointers -from being followed. - -\subsubsection{Limitations} -\label{sec:limit} - -Not all VIPS operations are partial-aware. These non-partial operations -use a pre-VIPS 7.0 I/O scheme in which the whole of the input image has to -be present at the same time. In some cases, this is because partial I/O -simply makes no sense --- for example, a Fourier Transform can produce no -output until it has seen all of the input. \verb+im_fwfft()+ is therefore -not a partial operation. In other cases, we have simply not got around to -rewriting the old non-partial operation in the newer partial style. - -You can mix partial and non-partial VIPS operations freely, without worrying -about which type they are. The only effect will be on the time your pipeline -takes to execute, and the memory requirements of the intermediate images. VIPS -uses the following rules when you mix the two styles of operation: - -\begin{enumerate} - -\item -When a non-partial operation is asked to output to a partial image descriptor, -the \verb+"p"+ descriptor is magically transformed into a \verb+"t"+ -descriptor. - -\item -When a non-partial operation is asked to read from a \verb+"p"+ descriptor, -the \verb+"p"+ descriptor is turned into a \verb+"t"+ type, and any earlier -stages in the pipeline forced to evaluate into that memory buffer. - -The non-partial operation then processes from the memory buffer. - -\end{enumerate} - -These rules have the consequence that you may only process very large images -if you only use partial operations. If you use any non-partial operations, -then parts of your pipelines will fall back to old whole-image I/O and you -will need to think carefully about where your intermediates should be stored. - diff --git a/doc/src/ipio.tex b/doc/src/ipio.tex deleted file mode 100644 index c0f39806..00000000 --- a/doc/src/ipio.tex +++ /dev/null @@ -1,56 +0,0 @@ -\section{Programming in-place functions} - -VIPS includes a little support for in-place functions --- functions -which operate directly on an image, both reading and writing from the same -descriptor via the data pointer. This is an extremely dangerous way to -handle IO, since any bugs in your program will trash your input image. - -Operations of this type should call \verb+im_rwcheck()+ instead of -\verb+im_incheck()+. \verb+im_rwcheck()+ tries to get a descriptor ready -for in-place writing. For example, a function which cleared an image to -black might be written as: - -\begin{verbatim} -#include -#include - -#include - -int -black_inplace( IMAGE *im ) -{ - /* Check that we can RW to im. - */ - if( im_rwcheck( im ) ) - return( -1 ); - - /* Zap the image! - */ - memset( im->data, 0, - IM_IMAGE_SIZEOF_LINE( im ) * - im->Ysize ); - - return( 0 ); -} -\end{verbatim} - -This function might be called from an application as: - -\begin{verbatim} -#include -#include - -#include - -void -zap( char *name ) -{ - IMAGE *im; - - if( !(im = im_open( name, "rw" )) || - black_inplace( im ) || - im_updatehist( im, "zap image" ) || - im_close( im ) ) - error_exit( "failure!" ); -} -\end{verbatim} diff --git a/doc/src/mydefs.tex b/doc/src/mydefs.tex deleted file mode 100644 index 5310b8ce..00000000 --- a/doc/src/mydefs.tex +++ /dev/null @@ -1,113 +0,0 @@ -% My defs - -% Computer Text, Computer text=>, Computer Text Display -\newcommand{\ct}[1]{\texttt{#1}} -\newcommand{\ctr}[1]{\ct{#1} / } - -\newenvironment{ctd}{\begin{quote}\footnotesize\tt}{\end{quote}} -\pagecolor{white} - -% abbreviations -\newcommand{\vips}{\ct{vips}} -\newcommand{\nip}{\ct{nip2}} -\newcommand{\bs}{$\backslash$} -\newcommand{\rtp}{\^{ }} -\newcommand{\cielab}{\emph{CIE~}$L^{*}a^{*}b^{*}$} -\newcommand{\ciexyz}{\emph{CIE XYZ}} -\newcommand{\cieyxy}{\emph{CIE Yxy}} -\newcommand{\cielch}{\emph{CIE LCh}} -\newcommand{\cieucs}{\emph{UCS(1:1)}} -\newcommand{\cross}{$\times{}$} - -% make a label ... override this for HTML output -\newcommand{\mylabel}[1]{\label{#1}} - -% generate " on page xx" if a label is referring to something on another page -% override this for HTML output -\newcounter{boink} -\newcommand{\onpage}[1]{% -\addtocounter{boink}{1}% -\label{atref\theboink{}}% -\ifthenelse{\pageref{atref\theboink{}}=\pageref{#1}}% -{}% -{ on page~\pageref{#1}}} - -% format a reference to a section .. "$3.11 on page 37" -\newcommand{\pref}[1]{\S\ref{#1}\onpage{#1}} -\newcommand{\tref}[1]{Table~\ref{#1}\onpage{#1}} -\newcommand{\fref}[1]{Figure~\ref{#1}\onpage{#1}} -\newcommand{\cref}[1]{Chapter~\ref{#1}\onpage{#1}} -\newcommand{\aref}[1]{Appendix~\ref{#1}\onpage{#1}} - -% Insert a file ... height and name. -\newcommand{\fig}[2]{ - \begin{center} - \includegraphics[height=#1]{figs/#2} - \end{center} -} - -% Insert a file ... width and name. -\newcommand{\figw}[2]{ - \begin{center} - \includegraphics[width=#1]{figs/#2} - \end{center} -} - -% make a 2-column figure ... define our own so we can easily override in html -% output -\newenvironment{fig2}{\begin{figure*}}{\end{figure*}} - -% same for 2-col tables -\newenvironment{tab2}{\begin{table*}}{\end{table*}} - -% environment for setting ip defs -\newenvironment{ipdef}{ -\par -\samepage -\begin{ctd} -\begin{tabular}{@{\hspace{0.2em}}ll@{\hspace{0.2em}}ll@{\hspace{0.2em}}ll@{\hspace{0.2em}}ll@{\hspace{0.2em}}ll@{\hspace{0.2em}}ll@{\hspace{0.2em}}ll@{\hspace{0.2em}}lllllllllllllllllllllllllllll} -~~~ & ~ & ~~~ & ~ & ~~~ & ~ & ~~~ & ~ & ~~~ & ~ & ~~~ & ~ & ~~~ & ~ & ~~~ & \\[-1.3em] -}{ -\end{tabular} -\end{ctd} -\par -} - -% causes problems for htlatex :-( -% make this a noop for now -% \newcommand{\dtxt}[1]{\multicolumn{25}{@{\hspace{0.2em}}l}{#1}} -\newcommand{\dtxt}[1]{#1} - -% Insert a blank page -\newcommand{\blankpage}{% -\newpage -~~~~ -\pagestyle{plain} -\newpage -% Another one necessary in twocolumn mode -~~~~ -\newpage -\pagestyle{fancy} -} - -%\addtolength{\headheight}{3pt} - -% Make text a bit wider, since we are two column. -\addtolength{\textwidth}{0.5in} -\addtolength{\oddsidemargin}{-0.25in} -\addtolength{\evensidemargin}{-0.25in} - -% twocolumn seems to remove the binding offset ... add it back -%\addtolength{\oddsidemargin}{-0.2in} -%\addtolength{\evensidemargin}{0.2in} - -% More space between headers and footers and the body -\addtolength{\topmargin}{-0.5em} -\addtolength{\headsep}{0.5em} -\addtolength{\footskip}{0.5em} - -% Swap left and right binding offsets -\newlength{\fred} -\setlength{\fred}{\oddsidemargin} -\setlength{\oddsidemargin}{\evensidemargin} -\setlength{\evensidemargin}{\fred} diff --git a/doc/src/object.tex b/doc/src/object.tex deleted file mode 100644 index 610c0953..00000000 --- a/doc/src/object.tex +++ /dev/null @@ -1,134 +0,0 @@ -\section{The VIPS base class: \texttt{VipsObject}} -\label{sec:object} - -VIPS is in the process of moving to an object system based on \verb+GObject+. -You can read about the \verb+GObjec+ library at the GTK+ website: - -\begin{verbatim} -http://www.gtk.org -\end{verbatim} - -We've implemented two new subsystems (\verb+VipsFormat+ and -\verb+VipsInterpolate+) on top of \verb+VipsObject+ but not yet moved the core -VIPS types over. As a result, \verb+VipsObject+ is still developing and is -likely to change in the next release. - -This section quickly summarises enough of the \verb+VipsObject+ system to let -you use the two derived APIs but that's all. Full documentation will come when -this system stabilises. - -\subsection{Properties} - -Like the rest of VIPS, \verb+VipsObject+ is a functional type. You can set -properties during object construction, but not after that point. You may read -properties at any time after construction, but not before. - -To enforce these rules, VIPS extends the standard \verb+GObject+ property -system and adds a new phase to object creation. An object has the following -stages in its life: - -\subsubsection{Lookup} - -\verb+vips_type_find()+ is a convenience function that looks up a type by its -nickname relative to a base class. For example: - -\begin{verbatim} -GType type = - vips_type_find( "VipsInterpolate", "bilinear" ); -\end{verbatim} - -\noindent -finds a subclass of \verb+VipsInterpolate+ nicknamed `bilinear'. You can look -up types by their full name of course, but these can be rather unwieldy -(\verb+VipsInterpolateBilinear+ in this case, for example). - -\subsubsection{Create} - -Build an instance with \verb+g_object_new()+. For example: - -\begin{verbatim} -VipsObject *object = - g_object_new( type, - "sharpness", 12.0, - NULL ); -\end{verbatim} - -You can set any of the object's properties in the constructor. You can -continue to set, but not read, any other properties, for example: - -\begin{verbatim} -g_object_set( object, - "sharpness", 12.0, - NULL ); -\end{verbatim} - -You can loop over an object's required and optional parameters with -\verb+vips_argument_map()+. - -\subsubsection{Build} - -Once all of the required any any of the optional object parameters have been -set, call \verb+vips_object_build()+: - -\begin{verbatim} -int vips_object_build( VipsObject *object ); -\end{verbatim} - -This function checks that all the parameters have been set correctly and -starts the object working. It returns non-zero on error, setting -\verb+im_error_string()+. - -\subsubsection{Use} - -The object is now fully working. You can read results from it, or pass it on -other objects. When you're finished with it, drop your reference to end its -life. - -\begin{verbatim} -g_object_unref( object ); -\end{verbatim} - -\subsection{Convenience functions} - -Two functions simplify building and printing objects. -\verb+vips_object_new_from_string()+ makes a new object which is a subclass of -a named base class. - -\begin{verbatim} -VipsObject * - vips_object_new_from_string( - const char *basename, const char *p ); -\end{verbatim} - -This is the function used by \verb+IM_INPUT_INTERPOLATE()+, for example, to -parse command-line arguments. The syntax is: - -\begin{verbatim} -nickname [ ( required-arg1, - ... - required-argn, - optional-arg-name = value, - ... - optional-argm-name = value ) ] -\end{verbatim} - -So values for all the required arguments, in the correct order, then name = -value for all the optional arguments you want to set. Parameters may be -enclosed in round or curly braces. - -\verb+vips_object_to_string()+ is the exact opposite: it generates the -construct string for any constructed -\verb+VipsObject+. - -\verb+vips_object_new()+ wraps up the business of creating and checking an -object. It makes the object, uses the supplied function to attach any -arguments, then builds the object and returns NULL on failure or the new -object on success. - -A switch to the \verb+vips+ command-line program is handy for listing subtypes -of \verb+VipsObject+. Try: - -\begin{verbatim} -$ vips list classes -\end{verbatim} - diff --git a/doc/src/operintro.tex b/doc/src/operintro.tex deleted file mode 100644 index 5d9ee25d..00000000 --- a/doc/src/operintro.tex +++ /dev/null @@ -1,100 +0,0 @@ -\section{Introduction} -\mylabel{sec:oper} - -This chapter explains how to write image processing operations using the -VIPS image I/O (input-output) system. For background, you should probably -take a look at \pref{sec:appl}. This is supposed to be a tutorial, if you -need detailed information on any particular function, use the on-line UNIX -manual pages. - -\subsection{Why use VIPS?} - -If you use the VIPS image I/O system, you get a number of benefits: - -\begin{description} - -\item[Threading] -If your computer has more than one CPU, the VIPS I/O system will automatically -split your image processing operation into separate threads (provided you -use PIO, see below). You should get an approximately linear speed-up as -you add more CPUs. - -\item[Pipelining] -Provided you use PIO (again, see below), VIPS can automatically join -operations together. A sequence of image processing operations will all -execute together, with image data flowing through the processing pipeline -in small pieces. This makes it possible to perform complex processing on -very large images with no need to worry about storage management. - -\item[Composition] -Because VIPS can efficiently compose image processing operations, you can -implement your new operation in small, reusable, easy-to-understand -pieces. VIPS already has a lot of these: many new operations can be -implemented by simply composing existing operations. - -\item[Large files] -Provided you use PIO and as long as the underlying OS supports large files -(that is, files larger than 2GB), VIPS operations can work on files larger -than can be addressed with 32 bits on a plain 32-bit machine. VIPS operations -only see 32 bit addresses; the VIPS I/O system transparently maps these to -64 bit operations for I/O. Large file support is included on most machines -after about 1998. - -\item[Abstraction] -VIPS operations see only arrays of numbers in native format. Details of -representation (big/little endian, VIPS/TIFF/JPEG file format, etc.) are -hidden from you. - -\item[Interfaces] -Once you have your image processing operation implemented, it automatically -appears in all of the VIPS interfaces. VIPS comes with a GUI (\nip{}), a -UNIX command-line interface (\vips{}) and a C++ and Python API. - -\item[Portability] -VIPS operations can be compiled on most unixes, Mac OS X and Windows NT, 2000 -and XP without modification. Mostly. - -\end{description} - -\subsection{I/O styles} - -The I/O system supports three styles of input-output. - -\begin{description} - -\item[Whole-image I/O (WIO)] -This style is a largely a left-over from VIPS 6.x. WIO image-processing -operations have all of the input image given to them in a large memory -array. They can read any of the input pels at will with simple pointer -arithmetic. - -\item[Partial-image I/O (PIO)] -In this style operations only have a small part of the input image available -to them at any time. When PIO operations are joined together into a pipeline, -images flow through them in small pieces, with all the operations in a -pipeline executing at the same time. - -\item[In-place] -The third style allows pels to be read and written anywhere in -the image at any time, and is used by the VIPS in-place operations, such -as \verb+im_fastline()+. You should only use it for operations which would -just be impossibly inefficient to write with either of the other two styles. - -\end{description} - -WIO operations are easy to program, but slow and inflexible when images -become large. PIO operations are harder to program, but scale well as images -become larger, and are automatically parallelized by the VIPS I/O system. - -If you can face it, and if your algorithm can be expressed in this way, you -should write your operations using PIO. Whichever you choose, applications -which call your operation will see no difference, except in execution speed. - -If your image processing operation performs no coordinate transformations, -that is, if your output image is the same size as your input image or images, -and if each output pixel depends only upon the pixel at the corresponding -position in the input images, then you can use the \verb+im_wrapone()+ -and \verb+im_wrapmany()+ operations. These take a simple buffer-processing -operation supplied by you and wrap it up as a full-blown PIO operation. -See~\pref{sec:wrapone}. - diff --git a/doc/src/packages.tex b/doc/src/packages.tex deleted file mode 100644 index f3fde6b1..00000000 --- a/doc/src/packages.tex +++ /dev/null @@ -1,889 +0,0 @@ -\section{VIPS packages} -\mylabel{sec:packages} - -\subsection{Arithmetic} - -See \fref{fg:arithmetic}. - -Arithmetic functions work on images as if each band element were a separate -number. All operations are point-to-point --- each output element depends -exactly upon the corresponding input element. All (except in a few cases -noted in the manual pages) will work with images of any type (or any mixture -of types), of any size and of any number of bands. - -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 \verb+IM_BANDFMT_UCHAR+ -images together, for example, produces a \verb+IM_BANDFMT_USHORT+ image, and -taking the \verb+im_costra()+ of a \verb+IM_BANDFMT_USHORT+ image produces -a \verb+IM_BANDFMT_FLOAT+ image. The details of the type conversions are -in the manual pages. - -\begin{fig2} -\begin{verbatim} -$ vips list arithmetic -im_abs - absolute value -im_acostra - acos of image (result in degrees) -im_add - add two images -im_asintra - asin of image (result in degrees) -im_atantra - atan of image (result in degrees) -im_avg - average value of image -im_point_bilinear - interpolate value at single point, linearly -im_bandmean - average image bands -im_ceil - round to smallest integal value not less than -im_cmulnorm - multiply two complex images, normalising output -im_costra - cos of image (angles in degrees) -im_cross_phase - phase of cross power spectrum of two complex images -im_deviate - standard deviation of image -im_divide - divide two images -im_exp10tra - 10^pel of image -im_expntra - x^pel of image -im_expntra_vec - [x,y,z]^pel of image -im_exptra - e^pel of image -im_fav4 - average of 4 images -im_floor - round to largest integal value not greater than -im_gadd - calculate a*in1 + b*in2 + c = outfile -im_invert - photographic negative -im_lintra - calculate a*in + b = outfile -im_linreg - pixelwise linear regression -im_lintra_vec - calculate a*in + b -> out, a and b vectors -im_litecor - calculate max(white)*factor*(in/white), if clip == 1 -im_log10tra - log10 of image -im_logtra - ln of image -im_max - maximum value of image -im_maxpos - position of maximum value of image -im_maxpos_avg - position of maximum value of image, averaging in case of draw -im_maxpos_vec - position and value of n maxima of image -im_measure - measure averages of a grid of patches -im_min - minimum value of image -im_minpos - position of minimum value of image -im_minpos_vec - position and value of n minima of image -im_multiply - multiply two images -im_powtra - pel^x ofbuildimage -im_powtra_vec - pel^[x,y,z] of image -im_remainder - remainder after integer division -im_remainderconst - remainder after integer division by a constant -im_remainderconst_vec - remainder after integer division by a vector of constants -im_rint - round to nearest integal value -im_sign - unit vector in direction of value -im_sintra - sin of image (angles in degrees) -im_stats - many image statistics in one pass -im_subtract - subtract two images -im_tantra - tan of image (angles in degrees) -\end{verbatim} -\caption{Arithmetic functions} -\label{fg:arithmetic} -\end{fig2} - -\subsection{Relational} - -See \fref{fg:relational}. - -Relational functions compare images to other images or to constants. They -accept any image or pair of images (provided they are the same size and -have the same number of bands --- their types may differ) and produce a -\verb+IM_BANDFMT_UCHAR+ image with the same number of bands as the input -image, with 255 in every band element for which the condition is true and -0 elsewhere. - -They may be combined with the boolean functions to form complex relational -conditions. Use \verb+im_max()+ (or \verb+im_min()+) to find out if a -condition is true (or false) for a whole image. - -\begin{fig2} -\begin{verbatim} -$ vips list relational -im_blend - use cond image to blend between images in1 and in2 -im_equal - two images equal in value -im_equal_vec - image equals doublevec -im_equalconst - image equals const -im_ifthenelse - use cond image to choose pels from image in1 or in2 -im_less - in1 less than in2 in value -im_less_vec - in less than doublevec -im_lessconst - in less than const -im_lesseq - in1 less than or equal to in2 in value -im_lesseq_vec - in less than or equal to doublevec -im_lesseqconst - in less than or equal to const -im_more - in1 more than in2 in value -im_more_vec - in more than doublevec -im_moreconst - in more than const -im_moreeq - in1 more than or equal to in2 in value -im_moreeq_vec - in more than or equal to doublevec -im_moreeqconst - in more than or equal to const -im_notequal - two images not equal in value -im_notequal_vec - image does not equal doublevec -im_notequalconst - image does not equal const -\end{verbatim} -\caption{Relational functions} -\label{fg:relational} -\end{fig2} - -\subsection{Boolean} - -See \fref{fg:boolean}. - -The boolean functions perform boolean arithmetic on pairs of -\verb+IM_BANDFMT_UCHAR+ images. They are useful for combining the results of -the relational and morphological functions. You can use -\verb+im_eorconst()+ with 255 as \verb+im_not()+. - -\begin{fig2} -\begin{verbatim} -$ vips list boolean -im_andimage - bitwise and of two images -im_andimageconst - bitwise and of an image with a constant -im_andimage_vec - bitwise and of an image with a vector constant -im_orimage - bitwise or of two images -im_orimageconst - bitwise or of an image with a constant -im_orimage_vec - bitwise or of an image with a vector constant -im_eorimage - bitwise eor of two images -im_eorimageconst - bitwise eor of an image with a constant -im_eorimage_vec - bitwise eor of an image with a vector constant -im_shiftleft - shift integer image n bits to left -im_shiftright - shift integer image n bits to right -\end{verbatim} -\caption{Boolean functions} -\label{fg:boolean} -\end{fig2} - -\subsection{Colour} -\label{sec:colour} - -See \fref{fg:colour}. - -The colour functions can be divided into two main types. First, functions to -transform images between the different colour spaces supported by VIPS: -\verb+RGB+ (also referred to as \verb+disp+), \verb+sRGB+, \verb+XYZ+, -\verb+Yxy+, \verb+Lab+, \verb+LabQ+, \verb+LabS+, \verb+LCh+ and -\verb+UCS+), and second, functions for calculating colour difference -metrics. Figure~\ref{fg:convert} shows how the VIPS colour spaces -interconvert. - -\begin{fig2} -\figw{5in}{interconvert.png} -\caption{VIPS colour space conversion} -\label{fg:convert} -\end{fig2} - -The colour spaces supported by VIPS are: - -\begin{description} - -\item[\texttt{LabQ}] -This is the principal VIPS colorimetric storage format. See the -man page for \verb+im_LabQ2Lab()+ for an explanation. You cannot perform -calculations on \verb+LabQ+ images. They are for storage only. Also refered -to as \verb+LABPACK+. - -\item[\texttt{LabS}] -This format represents coordinates in \cielab{} space as a three- -band \verb+IM_BANDFMT_SHORT+ image, scaled to fit the full range of bits. It is -the best format for computation, being relatively compact, quick, and -accurate. Colour values expressed in this way are hard to visualise. - -\item[\texttt{Lab}] -\verb+Lab+ colourspace represents \cielab{} colour values with a three-band -\verb+IM_BANDFMT_FLOAT+ image. This is the simplest format for general work: adding the -constant 50 to the L channel, for example, has the expected result. - -\item[\texttt{XYZ}] -\ciexyz{} colour space represented as a three-band \verb+IM_BANDFMT_FLOAT+ -image. - -\item[\texttt{XYZ}] -\cieyxy{} colour space represented as a three-band \verb+IM_BANDFMT_FLOAT+ -image. - -\item[\texttt{RGB}] -(also refered to as \verb+disp+) This format is similar to the RGB colour -systems used in other packages. If you want to export your image to a PC, -for example, convert your colorimetric image to \verb+RGB+, then turn it -to TIFF with \verb+im_vips2tiff()+. You need to supply a structure which -characterises your display. See the manual page for \verb+im_col_XYZ2rgb()+ -for hints on these guys. - -VIPS also supports \verb+sRGB+. This is a version of RGB with a carefully -defined and standard conversion from XYZ. See: - -\begin{verbatim} -http://www.color.org/ -\end{verbatim} - -\item[\texttt{LCh}] -Like \verb+Lab+, but rectangular $ab$ coordinates are replaced with polar $Ch$ -(Chroma and hue) coordinates. Hue angles are expressed in degrees. - -\item[\texttt{UCS}] -A colour space based on the CMC(1:1) colour difference measurement. This -is a highly uniform colour space, much better than \cielab{} for expressing -small differences. Conversions to and from \verb+UCS+ are extremely slow. - -\end{description} - -All VIPS colourspaces assume a D65 illuminant. - -The colour-difference functions calculate either $\Delta{}E$ \cielab{} (1976 -or 2000) or $\Delta{}E$ CMC(1:1) on two images in \verb+Lab+, \verb+XYZ+ -or \verb+disp+ colour space. - -\begin{fig2} -\begin{verbatim} -$ vips list colour -im_LCh2Lab - convert LCh to Lab -im_LCh2UCS - convert LCh to UCS -im_Lab2LCh - convert Lab to LCh -im_Lab2LabQ - convert Lab to LabQ -im_Lab2LabS - convert Lab to LabS -im_Lab2UCS - convert Lab to UCS -im_Lab2XYZ - convert D65 Lab to XYZ -im_Lab2XYZ_temp - convert Lab to XYZ, with a specified colour temperature -im_Lab2disp - convert Lab to displayable -im_LabQ2LabS - convert LabQ to LabS -im_LabQ2Lab - convert LabQ to Lab -im_LabQ2XYZ - convert LabQ to XYZ -im_LabQ2disp - convert LabQ to displayable -im_LabS2LabQ - convert LabS to LabQ -im_LabS2Lab - convert LabS to Lab -im_UCS2LCh - convert UCS to LCh -im_UCS2Lab - convert UCS to Lab -im_UCS2XYZ - convert UCS to XYZ -im_XYZ2Lab - convert D65 XYZ to Lab -im_XYZ2Lab_temp - convert XYZ to Lab, with a specified colour temperature -im_XYZ2UCS - convert XYZ to UCS -im_XYZ2Yxy - convert XYZ to Yxy -im_XYZ2disp - convert XYZ to displayble -im_XYZ2sRGB - convert XYZ to sRGB -im_Yxy2XYZ - convert Yxy to XYZ -im_dE00_fromLab - calculate delta-E CIE2000 for two Lab images -im_dECMC_fromLab - calculate delta-E CMC(1:1) for two Lab images -im_dECMC_fromdisp - calculate delta-E CMC(1:1) for two displayable images -im_dE_fromLab - calculate delta-E for two Lab images -im_dE_fromXYZ - calculate delta-E for two XYZ images -im_dE_fromdisp - calculate delta-E for two displayable images -im_disp2Lab - convert displayable to Lab -im_disp2XYZ - convert displayable to XYZ -im_float2rad - convert float to Radiance packed -im_icc_ac2rc - convert LAB from AC to RC using an ICC profile -im_icc_export - convert a float LAB to an 8-bit device image with an ICC profile -im_icc_export_depth - convert a float LAB to device space with an ICC profile -im_icc_import - convert a device image to float LAB with an ICC profile -im_icc_import_embedded - convert a device image to float LAB using the embedded profile -im_icc_present - test for presence of ICC library -im_icc_transform - convert between two device images with a pair of ICC profiles -im_lab_morph - morph colourspace of a LAB image -im_rad2float - convert Radiance packed to float -im_sRGB2XYZ - convert sRGB to XYZ -\end{verbatim} -\caption{Colour functions} -\label{fg:colour} -\end{fig2} - -\subsection{Conversion} - -See \fref{fg:conversion}. - -These functions may be split into three broad groups: functions which convert -between the VIPS numeric formats (\verb+im_clip2fmt()+, for example, converts -an image of any type to the specified \verb+IM_BANDFMT+), functions -supporting complex arithmetic (\verb+im_c2amph()+, for example, converts -a complex image from rectangular to polar co ordinates) and functions -which perform some simple geometric conversion (\verb+im_extract()+ forms -a sub-image). - -\verb+gbandjoin+ and the C function \verb+im_gbandjoin()+ will do a bandwise -join of many images at the same time. See the manual pages. - -\begin{fig2} -\begin{verbatim} -$ vips list conversion -im_bandjoin - bandwise join of two images -im_bernd - extract from pyramid as jpeg -im_black - generate black image -im_c2amph - convert real and imaginary to phase and amplitude -im_c2imag - extract imaginary part of complex image -im_c2ps - find power spectrum of complex image -im_c2real - extract real part of complex image -im_c2rect - convert phase and amplitude to real and imaginary -im_clip2c - convert to signed 8-bit integer -im_clip2cm - convert to complex -im_clip2d - convert to double-precision float -im_clip2dcm - convert to double complex -im_clip2f - convert to single-precision float -im_clip2fmt - convert image format to ofmt -im_clip2i - convert to signed 32-bit integer -im_clip2s - convert to signed 16-bit integer -im_clip2ui - convert to unsigned 32-bit integer -im_clip2us - convert to unsigned 16-bit integer -im_clip - convert to unsigned 8-bit integer -im_copy - copy image -im_copy_morph - copy image, setting pixel layout -im_copy_swap - copy image, swapping byte order -im_copy_set - copy image, setting informational fields -im_copy_set_meta - copy image, setting a meta field -im_extract_area - extract area -im_extract_areabands - extract area and bands -im_extract_band - extract band -im_extract_bands - extract several bands -im_extract - extract area/band -im_falsecolour - turn luminance changes into chrominance changes -im_fliphor - flip image left-right -im_flipver - flip image top-bottom -im_gbandjoin - bandwise join of many images -im_grid - chop a tall thin image into a grid of images -im_insert - insert sub-image into main image at position -im_insert_noexpand - insert sub-image into main image at position, no expansion -im_lrjoin - join two images left-right -im_mask2vips - convert DOUBLEMASK to VIPS image -im_msb - convert to uchar by discarding bits -im_msb_band - convert to single band uchar by discarding bits -im_print - print string to stdout -im_recomb - linear recombination with mask -im_replicate - replicate an image horizontally and vertically -im_ri2c - join two non-complex images to form complex -\end{verbatim} -\caption{Conversion functions} -\label{fg:conversion} -\end{fig2} - -\begin{fig2} -\begin{verbatim} -im_rot180 - rotate image 180 degrees -im_rot270 - rotate image 270 degrees clockwise -im_rot90 - rotate image 90 degrees clockwise -im_scale - scale image linearly to fit range 0-255 -im_scaleps - logarithmic scale of image to fit range 0-255 -im_rightshift_size - decrease size by a power-of-two factor -im_slice - slice an image using two thresholds -im_subsample - subsample image by integer factors -im_system - run command on image -im_tbjoin - join two images top-bottom -im_text - generate text image -im_thresh - slice an image at a threshold -im_vips2mask - convert VIPS image to DOUBLEMASK -im_wrap - shift image origin, wrapping at sides -im_zoom - simple zoom of an image by integer factors -\end{verbatim} -\caption{Conversion functions (cont.)} -\end{fig2} - -\subsection{Matricies} - -See \fref{fg:matricies}. - -VIPS uses matricies for morphological operations, for convolutions, and -for some colour-space conversions. There are two types of matrix: integer -(\verb+INTMASK+) and double precision floating point (\verb+DOUBLEMASK+). - -For convenience, both types are stored in files as ASCII. The first -line of the file should start with the matrix dimensions, width first, -then on the same line an optional scale and offset. The two size fields -should be integers; the scale and offset may be floats. Subsequent lines -should contain the matrix elements, one row per line. The scale and -offset are the conventional ones used to represent non-integer values in -convolution masks --- in other words: - -\[ -result = {value \over scale} + offset -\] - -If the scale and offset are missing, they default to 1.0 and 0.0. See the -sections on convolution for more on the use of these fields. So as an example, -a 4 by 4 identity matrix would be stored as: - -\begin{verbatim} -4 4 -1 0 0 0 -0 1 0 0 -0 0 1 0 -0 0 0 1 -\end{verbatim} - -And a 3 by 3 mask for block averaging with convolution might be stored as: - -\begin{verbatim} -3 3 9 0 -1 1 1 -1 1 1 -1 1 1 -\end{verbatim} - -\noindent -(in other words, sum all the pels in every 3 by 3 area, and divide by 9). - -This matrix contains only integer elements and so could be used as an -argument to functions expecting both \verb+INTMASK+ and \verb+DOUBLEMASK+ -matricies. However, masks containing floating-point values (such as the -output of \verb+im_matinv()+) can only be used as arguments to functions -expecting \verb+DOUBLEMASK+s. - -A set of functions for mask input and output are also available for -C-programmers --- see the manual pages for \verb+im_read_dmask()+. For -other matrix functions, see also the convolution sections and the arithmetic -sections. - -\begin{fig2} -\begin{verbatim} -$ vips list matrix -im_matcat - append matrix in2 to the end of matrix in1 -im_matinv - invert matrix -im_matmul - multiply matrix in1 by matrix in2 -im_mattrn - transpose matrix -\end{verbatim} -\caption{Matrix functions} -\label{fg:matricies} -\end{fig2} - -\subsection{Convolution} - -See \fref{fg:convolution}. - -The functions available in the convolution package can be split into five -main groups. - -First, are the convolution functions. The most useful function is -\verb+im_conv()+ which will convolve any non-complex type with an -\verb+INTMASK+ matrix. The output image will have the same size, type, and -number of bands as the input image. Of the other \verb+im_conv()+ functions, -functions whose name ends in \verb+_raw+ do not add a black border around the -output image, functions ending in \verb+f+ use a \verb+DOUBLEMASK+ matrix -and write float (or double) output, and functions containing \verb+sep+ -are for seperable convolutions. \verb+im_compass()+, \verb+im_lindetect()+ -and \verb+im_gradient()+ convolve with rotating masks. \verb+im_embed()+ -is used by the convolution functions to add the border to the output. - -Next, are the build functions. \verb+im_gauss_*mask()+ and its ilk -generate gaussian masks, \verb+im_log_*mask()+ generate logs of Laplacians. -\verb+im_addgnoise()+ and \verb+im_gaussnoise()+ create or add gaussian -noise to an image. - -Two functions do correlation: \verb+im_fastcor()+ does a quick and dirty -correlation, \verb+im_spcor()+ calculates true spatial correlation, and is -rather slow. - -Some functions are provided for analysing images: \verb+im_zerox()+ counts -zero-crossing points in an image, \verb+im_mpercent()+ finds a threshold -that will isolate a percentage of points in an image. - -Finally, \verb+im_resize_linear()+ and \verb+im_shrink()+ do as you would -expect. - -\begin{fig2} -\begin{verbatim} -$ vips list convolution -im_addgnoise - add gaussian noise with mean 0 and std. dev. sigma -im_compass - convolve with 8-way rotating integer mask -im_contrast_surface - find high-contrast points in an image -im_contrast_surface_raw - find high-contrast points in an image -im_conv - convolve -im_conv_raw - convolve, no border -im_convf - convolve, with DOUBLEMASK -im_convf_raw - convolve, with DOUBLEMASK, no border -im_convsep - seperable convolution -im_convsep_raw - seperable convolution, no border -im_convsepf - seperable convolution, with DOUBLEMASK -im_convsepf_raw - seperable convolution, with DOUBLEMASK, no border -im_convsub - convolve uchar to uchar, sub-sampling by xskip, yskip -im_dmask_xsize - horizontal size of a doublemask -im_dmask_ysize - vertical size of a doublemask -im_embed - embed in within a set of borders -im_fastcor - fast correlate in2 within in1 -im_fastcor_raw - fast correlate in2 within in1, no border -im_gauss_dmask - generate gaussian DOUBLEMASK -im_gauss_imask - generate gaussian INTMASK -im_gauss_imask_sep - generate separable gaussian INTMASK -im_gaussnoise - generate image of gaussian noise with specified statistics -im_grad_x - horizontal difference image -im_grad_y - vertical difference image -im_gradcor - non-normalised correlation of gradient of in2 within in1 -im_gradcor_raw - non-normalised correlation of gradient of in2 within in1, no padding -im_gradient - convolve with 2-way rotating mask -im_imask_xsize - horizontal size of an intmask -im_imask_ysize - vertical size of an intmask -im_rank_image - point-wise pixel rank -im_lindetect - convolve with 4-way rotating mask -im_log_dmask - generate laplacian of gaussian DOUBLEMASK -im_log_imask - generate laplacian of gaussian INTMASK -im_maxvalue - point-wise maximum value -im_mpercent - find threshold above which there are percent values -im_phasecor_fft - non-normalised correlation of gradient of in2 within in1 -im_rank - rank filter nth element of xsize/ysize window -im_rank_raw - rank filter nth element of xsize/ysize window, no border -im_read_dmask - read matrix of double from file -im_resize_linear - resize to X by Y pixels with linear interpolation -im_rotate_dmask45 - rotate DOUBLEMASK clockwise by 45 degrees -im_rotate_dmask90 - rotate DOUBLEMASK clockwise by 90 degrees -im_rotate_imask45 - rotate INTMASK clockwise by 45 degrees -im_rotate_imask90 - rotate INTMASK clockwise by 90 degrees -im_sharpen - sharpen high frequencies of L channel of LabQ -im_shrink - shrink image by xfac, yfac times -im_spcor - normalised correlation of in2 within in1 -im_spcor_raw - normalised correlation of in2 within in1, no black padding -im_stretch3 - stretch 3%, sub-pixel displace by xdisp/ydisp -im_zerox - find +ve or -ve zero crossings in image -\end{verbatim} -\caption{Convolution functions} -\label{fg:convolution} -\end{fig2} - -\subsection{In-place operations} -\label{sec:inplace} - -See \fref{fg:inplace}. - -A few of the in-place operations are available from the command-line. Most are -not. - -\begin{fig2} -\begin{verbatim} -$ vips list inplace -im_circle - plot circle on image -im_flood_blob_copy - flood while pixel == start pixel -im_insertplace - draw image sub inside image main at position (x,y) -im_line - draw line between points (x1,y1) and (x2,y2) -im_lineset - draw line between points (x1,y1) and (x2,y2) -\end{verbatim} -\caption{In-place operations} -\label{fg:inplace} -\end{fig2} - -\subsection{Frequency filtering} - -See \fref{fg:freq}. - -The basic Fourier functions are \verb+im_fwfft()+ and -\verb+im_invfft()+, which calculate the fast-fourier transform and inverse -transform of an image. Also \verb+im_invfftr()+, which just returns the real -part of the inverse transform. -The Fourier image has its origin at pel (0,0) --- -for viewing, use \verb+im_rotquad()+ to move the origin to the centre of -the image. - -Once an image is in the frequency domain, it can be filtered by multiplying -it with a mask image. The VIPS mask generator is \verb+im_create_fmask()+ -see the manual page for details of the arguments, but it will create low -pass, high pass, ring pass and band pass filters, which may each be ideal, -Gaussian or Butterworth. There is also a fractal mask option. - -The other functions in the package build on these base -facilities. \verb+im_freqflt()+ transforms an input image to -Fourier space, multiplies it by a mask image, and transforms it back -again. \verb+im_flt_image_freq()+ will create a mask image of the correct -size for you, and call \verb+im_freqflt()+. \verb+im_disp_ps()+ will call -the right combinations of functions to make a displayable power spectrum -for an image. - -\begin{fig2} -\begin{verbatim} -$ vips list freq_filt -im_create_fmask - create frequency domain filter mask -im_disp_ps - make displayable power spectrum -im_flt_image_freq - frequency domain filter image -im_fractsurf - generate a fractal surface of given dimension -im_freqflt - frequency-domain filter of in with mask -im_fwfft - forward fast-fourier transform -im_rotquad - rotate image quadrants to move origin to centre -im_invfft - inverse fast-fourier transform -im_invfftr - real part of inverse fast-fourier transform -\end{verbatim} -\caption{Fourier functions} -\label{fg:freq} -\end{fig2} - -\subsection{Histograms and LUTs} - -See \fref{fg:hist}. - -VIPS represents histograms and look-up tables in the same way --- as images. - -They should have either \verb+Xsize+ or \verb+Ysize+ set to 1, and the -other dimension set to the number of elements in the table. The table can be -of any size, have any band format, and have any number of bands. - -Use \verb+im_histgr()+ to find the histogram of an image. Use -\verb+im_histnD()+ to find the n-dimensional histogram of an n-band -image. Perform operations on histograms with \verb+im_histcum()+, -\verb+im_histnorm()+, \verb+im_histspec()+, \verb+im_invertlut()+. Visualise -histograms with \verb+im_histplot()+. Use a histogram (or LUT) to transform -an image with \verb+im_maplut()+. Build a histogram from scratch with -\verb+im_identity()+ or \verb+im_identity_ushort()+. - -Use \verb+im_lhist*()+ for local histogram equalisation, and -\verb+im_stdif*()+ for statisticaol differencing. The \verb+im_tone_*()+ -functions are for operations on the L channel of a LAB image. Other -functions are useful combinations of these basic operations. - -\begin{fig2} -\begin{verbatim} -$ vips list histograms_lut -im_gammacorrect - gamma-correct image -im_heq - histogram-equalise image -im_hist - find and graph histogram of image -im_histcum - turn histogram to cumulative histogram -im_histeq - form histogram equalistion LUT -im_histgr - find histogram of image -im_histnD - find 1D, 2D or 3D histogram of image -im_histnorm - form normalised histogram -im_histplot - plot graph of histogram -im_histspec - find histogram which will make pdf of in match ref -im_hsp - match stats of in to stats of ref -im_identity - generate identity histogram -im_identity_ushort - generate ushort identity histogram -im_ismonotonic - test LUT for monotonicity -im_lhisteq - local histogram equalisation -im_lhisteq_raw - local histogram equalisation, no border -im_invertlut - generate correction table from set of measures -im_buildlut - generate LUT table from set of x/y positions -im_maplut - map image through LUT -im_project - find horizontal and vertical projections of an image -im_stdif - statistical differencing -im_stdif_raw - statistical differencing, no border -im_tone_analyse - analyse in and create LUT for tone adjustment -im_tone_build - create LUT for tone adjustment of LabS images -im_tone_build_range - create LUT for tone adjustment -im_tone_map - map L channel of LabS or LabQ image through LUT -\end{verbatim} -\caption{Histogram/LUT functions} -\label{fg:hist} -\end{fig2} - -\subsection{Morphology} - -See \fref{fg:morph}. - -The morphological functions are used on one-band \verb+IM_BANDFMT_UCHAR+ binary -images (images containing only zero and not-zero). They 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 -(\verb+im_rotate_imask45()+, 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 on a black background. - -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: - -\begin{verbatim} -3 3 -128 255 128 -255 0 255 -128 255 128 -\end{verbatim} - -\noindent -applied to an image with \verb+im_erode()+, will find all black pixels -4-way connected with white pixels. Essentially, \verb+im_dilate()+ -sets pixels in the output if any part of the mask matches, whereas -\verb+im_erode()+ sets pixels only if all of the mask matches. - -The \verb+_raw()+ version of the functions do not add a black border to the -output. \verb+im_cntlines()+ and \verb+im_profile+ are occasionally useful for -analysing results. - -See the boolean operations \verb+im_and()+, \verb+im_or()+ and -\verb+im_eor()+ for analogues of the usual set difference and set -union operations. - -\begin{fig2} -\begin{verbatim} -$ vips list morphology -im_cntlines - count horizontal or vertical lines -im_dilate - dilate image with mask, adding a black border -im_dilate_raw - dilate image with mask -im_erode - erode image with mask, adding a black border -im_erode_raw - erode image with mask -im_profile - find first horizontal/vertical edge -\end{verbatim} -\caption{Morphological functions} -\label{fg:morph} -\end{fig2} - -\subsection{Mosaicing} - -See \fref{fg:mosaicing}. - -These functions are useful for joining many small images together to make one -large image. They can cope with unstable contrast, and arbitary sub-image -layout, but will not do any geometric correction. The mosaicing functions -can be grouped into layers: - -The lowest level functions are \verb+im_correl()+. and \verb+im_affine()+. -\verb+im_correl()+ searches a large image for a small sub-image, returning -the position of the best sub-image match. \verb+im_affine()+ performs -a general affine transform on an image: that is, any transform in which -parallel lines remain parallel. - -Next, \verb+im_lrmerge()+ and \verb+im_tbmerge()+ blend two images together -left-right or up-down. - -Next up are \verb+im_lrmosaic()+ and \verb+im_tbmosaic()+. These use the -two low-level merge operations to join two images given just an approximate -overlap as a start point. Optional extra parameters let you do 'balancing' -too: if your images have come from a source where there is no precise -control over the exposure (for example, images from a tube camera, or a -set of images scanned from photographic sources), \verb+im_lrmosaic()+ -and \verb+im_tbmosaic()+ will adjust the contrast of the left image to -match the right, the right to the left, or both to some middle value. - -The functions \verb+im_lrmosaic1()+ and \verb+im_tbmosaic1()+ are first-order -analogues of the basic mosaic functions: they take two tie-points and use -them to rotate and scale the right-hand or bottom image before starting to join. - -Finally, \verb+im_global_balance()+ can be used to re-balance a mosaic -which has been assembled with these functions. It will generally do a -better job than the low-level balancer built into \verb+im_lrmosaic()+ -and \verb+im_tbmosaic()+. See the man page. \verb+im_remosaic()+ uses the same -techniques, but will reassemble the image from a different set of source -images. - -\begin{fig2} -\begin{verbatim} -$ vips list mosaicing -im_align_bands - align the bands of an image -im_correl - search area around sec for match for area around ref -im__find_lroverlap - search for left-right overlap of ref and sec -im__find_tboverlap - search for top-bottom overlap of ref and sec -im_global_balance - automatically rebuild mosaic with balancing -im_global_balancef - automatically rebuild mosaic with balancing, float output -im_lrmerge - left-right merge of in1 and in2 -im_lrmerge1 - first-order left-right merge of ref and sec -im_lrmosaic - left-right mosaic of ref and sec -im_lrmosaic1 - first-order left-right mosaic of ref and sec -im_match_linear - resample ref so that tie-points match -im_match_linear_search - search sec, then resample so that tie-points match -im_maxpos_subpel - subpixel position of maximum of (phase correlation) image -im_remosaic - automatically rebuild mosaic with new files -im_tbmerge - top-bottom merge of in1 and in2 -im_tbmerge1 - first-order top-bottom merge of in1 and in2 -im_tbmosaic - top-bottom mosaic of in1 and in2 -im_tbmosaic1 - first-order top-bottom mosaic of ref and sec -\end{verbatim} -caption{Mosaic functions} -\label{fg:mosaicing} -\end{fig2} - -\subsection{CImg functions} - -See \fref{fg:cimg}. - -These operations wrap the anisotropic blur function from the CImg library. -They are useful for removing noise from images. - -\begin{fig2} -\begin{verbatim} -$ vips list cimg -im_greyc - noise-removing filter -im_greyc_mask - noise-removing filter, with a mask -\end{verbatim} -\caption{CImg functions} -\label{fg:cimg} -\end{fig2} - -\subsection{Other} - -See \fref{fg:other}. - -These functions generate various test images. You can combine them with -the arithmetic and rotate functions to build more complicated images. - -The \verb+im_benchmark*()+ operations are for testing the VIPS SMP system. - -\begin{fig2} -\begin{verbatim} -$ vips list other -im_benchmark - do something complicated for testing -im_benchmark2 - do something complicated for testing -im_benchmarkn - do something complicated for testing -im_eye - generate IM_BANDFMT_UCHAR [0,255] frequency/amplitude image -im_grey - generate IM_BANDFMT_UCHAR [0,255] grey scale image -im_feye - generate IM_BANDFMT_FLOAT [-1,1] frequency/amplitude image -im_fgrey - generate IM_BANDFMT_FLOAT [0,1] grey scale image -im_fzone - generate IM_BANDFMT_FLOAT [-1,1] zone plate image -im_make_xy - generate image with pixel value equal to coordinate -im_zone - generate IM_BANDFMT_UCHAR [0,255] zone plate image -\end{verbatim} -\caption{Other functions} -\label{fg:other} -\end{fig2} - -\subsection{IO functions} - -See \fref{fg:io}. - -These functions are related to the image IO system. - -\begin{fig2} -\begin{verbatim} -$ vips list iofuncs -im_binfile - open a headerless binary file -im_cache - cache results of an operation -im_guess_prefix - guess install area -im_guess_libdir - guess library area -im_header_get_type - return field type -im_header_int - extract int fields from header -im_header_double - extract double fields from header -im_header_string - extract string fields from header -im_version - VIPS version number -im_version_string - VIPS version string -\end{verbatim} -\caption{IO functions} -\label{fg:io} -\end{fig2} - -\subsection{Format functions} - -See \fref{fg:format}. - -These functions convert to and from various image formats. See -\pref{sec:format} for a nice API over these. VIPS can read more than these -formats, see the man page for \verb+VipsFormat+. - -\begin{fig2} -\begin{verbatim} -$ vips list format -im_csv2vips - read a file in csv format -im_jpeg2vips - convert from jpeg -im_magick2vips - load file with libMagick -im_png2vips - convert PNG file to VIPS image -im_exr2vips - convert an OpenEXR file to VIPS -im_ppm2vips - read a file in pbm/pgm/ppm format -im_analyze2vips - read a file in analyze format -im_tiff2vips - convert TIFF file to VIPS image -im_vips2csv - write an image in csv format -im_vips2jpeg - convert to jpeg -im_vips2mimejpeg - convert to jpeg as mime type on stdout -im_vips2png - convert VIPS image to PNG file -im_vips2ppm - write a file in pbm/pgm/ppm format -im_vips2tiff - convert VIPS image to TIFF file -\end{verbatim} -\caption{Format functions} -\label{fg:format} -\end{fig2} - -\subsection{Resample functions} - -See \fref{fg:resample}. - -These functions resample images with various interpolators. - -\begin{fig2} -\begin{verbatim} -$ vips list resample -im_affine - affine transform -im_affinei - affine transform -im_affinei_all - affine transform of whole image -im_similarity_area - output area xywh of similarity transformation -im_similarity - similarity transformation -\end{verbatim} -\caption{Resample functions} -\label{fg:resample} -\end{fig2} diff --git a/doc/src/pio.tex b/doc/src/pio.tex deleted file mode 100644 index f2e45e01..00000000 --- a/doc/src/pio.tex +++ /dev/null @@ -1,854 +0,0 @@ -\section{Programming PIO functions} -\label{sec:pio} - -The VIPS PIO system has a number of advantages over WIO, as summarised in -the introduction. On the other hand, they are a bit more complicated. - -\subsection{Easy PIO with \texttt{im\_wrapone()} and \texttt{im\_wrapmany()}} -\label{sec:wrapone} - -PIO is a very general image IO system, and because of this flexibility, -can be complicated to program. As a convenience, VIPS offers an easy-to-use -layer over PIO with the funtions \verb+im_wrapone()+ and \verb+im_wrapmany()+. - -If your image processing function is uninterested in coordinates, that is, -if your input and output images are the same size, and each output pixel -depends only upon the value of the corresponding pixel in the input image -or images, then these functions are for you. - -Consider the \verb+invert()+ function of figure~\ref{fg:invert}. First, -we have to write the core of this as a buffer-processing function: - -\begin{verbatim} -#include -#include - -#include - -/* p points to a buffer of pixels which - * need inverting, q points to the buffer - * we should write the result to, and n - * is the number of pels present. - */ -static void -invert_buffer( unsigned char *p, - unsigned char *q, int n ) -{ - int i; - - for( i = 0; i < n; i++ ) - q[i] = 255 - p[i]; -} -\end{verbatim} - -Now we have to wrap up this very primitive expression of the invert operation -as a PIO function. We use \verb+im_wrapone()+ to do this. It has type: - -\begin{verbatim} -int -im_wrapone( IMAGE *in, IMAGE *out, - im_wrapone_fn fn, void *a, void *b ) -\end{verbatim} - -\noindent -where: - -\begin{verbatim} -void -(*im_wrapone_fn)(void *in, void *out, - int n, void *a, void *b ) -\end{verbatim} - -\noindent -almost the same type as our buffer-processing function above. The values -\verb+a+ and \verb+b+ are carried around by VIPS for whatever use you -fancy. \verb+invert()+ can now be written as: - -\begin{verbatim} -int -invert( IMAGE *in, IMAGE *out ) -{ - /* Check parameters. - */ - if( in->BandFmt != IM_BANDFMT_UCHAR || - in->Bands != 1 || - in->Coding != IM_CODING_NONE ) { - im_error( "invert", "bad image" ); - return( -1 ); - } - - /* Set fields in output image. - */ - if( im_cp_desc( out, in ) ) - return( -1 ); - - /* Process! We don't use either of the - * user parameters in this function, - * so leave them as NULL. - */ - if( im_wrapone( in, out, - (im_wrapone_fn) invert_buffer, - NULL, NULL ) ) - return( -1 ); - - return( 0 ); -} -\end{verbatim} - -And that's all there is to it. This function will have all of the desirable -properties of PIO functions, while being as easy to program as the WIO -\verb+invert()+ earlier in this chapter. - -This version of \verb+invert()+ is not very general: it will only accept -one-band unsigned char images. It is easy to modify for n-band images: - -\begin{verbatim} -/* As before, but use one of the user - * parameters to pass in the number of - * bands in the image. - */ -static void -invert_buffer( unsigned char *p, - unsigned char *q, int n, - IMAGE *in ) -{ - int i; - int sz = n * in->Bands; - - for( i = 0; i < sz; i++ ) - q[i] = 255 - p[i]; -} -\end{verbatim} - -We must also modify \verb+invert()+: - -\begin{verbatim} -int -invert( IMAGE *in, IMAGE *out ) -{ - /* Check parameters. - */ - if( in->BandFmt != IM_BANDFMT_UCHAR || - in->Coding != IM_CODING_NONE ) { - im_error( "invert", "bad image" ); - return( -1 ); - } - - /* Set fields in output image. - */ - if( im_cp_desc( out, in ) ) - return( -1 ); - - /* Process! The first user-parameter - * is the number of bands involved. - */ - if( im_wrapone( in, out, - (im_wrapone_fn)invert_buffer, - in, NULL ) ) - return( -1 ); - - return( 0 ); -} -\end{verbatim} - -There are two significant hidden traps here. First, inside the buffer -processing functions, you may only read the contents of the user parameters -\verb+a+ and \verb+b+, you may not write to them. This is because on a -multi-CPU machine, several copies of your buffer-processing functions will -be run in parallel --- if they all write to the same place, there will be -complete confusion. If you need writeable parameters (for example, to count -and report overflows), you can't use \verb+im_wrapone()+, you'll have to -use the PIO system in all its gory detail, see below. - -Secondly, your buffer processing function may not be called immediately. VIPS -may decide to delay evaluation of your operation until long after the call -to \verb+invert()+ has returned. As a result, care is needed to ensure -that you never read anything in your buffer-processing function that may -have been freed. The best way to ensure this is to use the local resource -allocators, such as \verb+im_open_local()+ and \verb+im_malloc()+. This issue -is discussed at length in the sections below, and in \pref{sec:appl}. - -\verb+im_wrapone()+ is for operations which take exactly one input image. VIPS -provides a second function, \verb+im_wrapmany()+, which works for any number -of input images. The type of \verb+im_wrapmany()+ is slightly different: - -\begin{verbatim} -int -im_wrapmany( IMAGE **in, IMAGE *out, - im_wrapmany_fn fn, void *a, void *b ) -\end{verbatim} - -\noindent - -\begin{verbatim} -void -(*im_wrapmany_fn)( void **in, void *out, - int n, void *a, void *b ) -\end{verbatim} - -\noindent -\verb+im_wrapmany()+ takes a \verb+NULL+-terminated array of input images, -and creates a \verb+NULL+-terminated array of buffers for the use of your -buffer processing function. A function to add two \verb+IM_BANDFMT_UCHAR+ -images to make a \verb+IM_BANDFMT_UCHAR+ image might be written as: - -\begin{verbatim} -static void -add_buffer( unsigned char **in, - unsigned short *out, int n, - IMAGE *in ) -{ - int i; - int sz = n * in->Bands; - unsigned char *p1 = in[0]; - unsigned char *p2 = in[1]; - - for( i = 0; i < sz; i++ ) - out[i] = p1[i] + p2[i]; -} -\end{verbatim} - -This can be made into a PIO function with: - -\begin{verbatim} -int -add_uchar( IMAGE *i1, IMAGE *i2, - IMAGE *out ) -{ - IMAGE *invec[3]; - - /* Check parameters. We don't need to - * check that i1 and i2 are the same - * size, im_wrapmany() does that for - * us. - */ - if( i1->BandFmt != IM_BANDFMT_UCHAR || - i1->Coding != IM_CODING_NONE || - i2->BandFmt != IM_BANDFMT_UCHAR || - i2->Coding != IM_CODING_NONE || - i1->Bands != i2->Bands ) { - im_error( "add_uchar", "bad in" ); - return( -1 ); - } - - /* Set fields in output image. As - * input image, but we want a USHORT. - */ - if( im_cp_desc( out, i1 ) ) - return( -1 ); - out->BandFmt = IM_BANDFMT_USHORT; - out->Bbits = IM_BBITS_SHORT; - - /* Process! The first user-parameter - * is the number of bands involved. - * invec is a NULL-terminated array of - * input images. - */ - invec[0] = i1; invec[1] = i2; - invec[2] = NULL; - if( im_wrapmany( invec, out, - (im_wrapone_fn)add_buffer, - i1, NULL ) ) - return( -1 ); - - return( 0 ); -} -\end{verbatim} - -\subsection{Region descriptors} - -Regions are the next layer of abstraction above image descriptors. A region -is a small part of an image, held in memory ready for processing. A region -is defined as: - -\begin{verbatim} -typedef struct { - Rect valid; - IMAGE *im; - - ... and some other private fields, - ... used by VIPS for housekeeping -} REGION; -\end{verbatim} - -\noindent -where \verb+valid+ holds the sub-area of image \verb+im+ that this region -represents, and \verb+Rect+ is defined as: - -\begin{verbatim} -typedef struct { - int left, top; - int width, height; -} Rect; -\end{verbatim} - -\noindent -two macros are available for \verb+Rect+ calculations: - -\begin{verbatim} -int IM_RECT_RIGHT( Rect *r ) -int IM_RECT_BOTTOM( Rect *r ) -\end{verbatim} - -\noindent -where \verb+IM_RECT_RIGHT()+ returns \verb+left+ + \verb+width+, and -\verb+IM_RECT_BOTTOM()+ returns \verb+top+ + \verb+height+. A small library -of C functions are also available for \verb+Rect+ algebra, see the manual -pages for \verb+im_rect_intersectrect()+. - -Regions are created with \verb+im_region_create()+. This has type: - -\begin{verbatim} -REGION *im_region_create( IMAGE *im ) -\end{verbatim} - -\noindent -\verb+im_region_create()+ returns a pointer to a new region structure, -or \verb+NULL+ on error. Regions returned by \verb+im_region_create()+ -are blank --- they contain no image data and cannot be read from or written -to. See the next couple of sections for calls to fill regions with data. - -Regions are destroyed with \verb+im_region_free()+. It has type: - -\begin{verbatim} -int im_region_free( REGION *reg ) -\end{verbatim} - -\noindent -And, as usual, returns 0 on success and non-zero on error, setting -\verb+im_error()+. You must free all regions you create. If you close -an image without freeing all the regions defined on that image, the image is -just marked for future closure --- it is not actually closed until the final -region is freed. This behaviour helps to prevent dangling pointers, and it -is not difficult to make sure you free all regions --- see the examples below. - -\subsection{Image input with regions} - -Before you can read from a region, you need to call \verb+im_prepare()+ -to fill the region with image data. It has type: - -\begin{verbatim} -int im_prepare( REGION *reg, Rect *r ) -\end{verbatim} - -Area \verb+r+ of the image on which \verb+reg+ has been created is prepared -and attached to the region. - -Exactly what this preparation involves depends upon the image --- it can -vary from simply adjusting some pointers, to triggering the evaluation of a -series of other functions. If it returns successfully, \verb+im_prepare()+ -guarantees that all pixels within \verb+reg->valid+ may be accessed. Note -that this may be smaller or larger than \verb+r+, since \verb+im_prepare()+ -clips \verb+r+ against the size of the image. - -Programs can access image data in the region by calling the macro -\verb+IM_REGION_ADDR()+. It has type - -\begin{verbatim} -char *IM_REGION_ADDR( REGION *reg, - int x, int y ) -\end{verbatim} - -Provided that point (x,y) lies inside \verb+reg->valid+, -\verb+IM_REGION_ADDR()+ returns a pointer to pel $(x,y)$. Adding to the result -of \verb+IM_REGION_ADDR()+ moves to the right along the line of pels, provided -you stay strictly within \verb+reg->valid+. Add \verb+IM_REGION_LSKIP()+ -to move down a line, see below. \verb+IM_REGION_ADDR()+ has some other -useful features --- see the manual page. - -Other macros are available to ease address calculation: - -\begin{verbatim} -int IM_REGION_LSKIP( REGION *reg ) -int IM_REGION_N_ELEMENTS( REGION *reg ) -int IM_REGION_SIZEOF_LINE( REGION *reg ) -\end{verbatim} - -\noindent -These find the number of bytes to add to the result of \verb+IM_REGION_ADDR()+ -to move down a line, the number of band elements across the region and the -number of bytes across the region. - -\fref{fg:paverage} is a version of \verb+average()+ which uses -regions rather than WIO input. Two things: first, we should really be -using \verb+vips_sink()+, see \pref{sec:sequence}, to do the rectangle -algebra for us. Secondly, note that we call \verb+im_pincheck()+ rather -than \verb+im_incheck()+. \verb+im_pincheck()+ signals to the IO system -that you are a PIO-aware function, giving \verb+im_prepare()+ much more -flexibility in the sorts of preparation it can do. Also see the manual -pages for \verb+im_poutcheck()+ and \verb+im_piocheck()+. - -\begin{fig2} -\begin{verbatim} -#include -#include -#include -#include - -int -average( IMAGE *im, double *out ) -{ - int total, i, y; - REGION *reg; - Rect area, *r; - - /* Check im. - */ - if( im_pincheck( im ) ) - return( -1 ); - if( im->BandFmt != IM_BANDFMT_UCHAR || im->Coding != IM_CODING_NONE ) { - im_error( "average", "uncoded uchar images only" ); - return( -1 ); - } - - /* Make a region on im which we can use for reading. - */ - if( !(reg = im_region_create( im )) ) - return( -1 ); -\end{verbatim} -\caption{First PIO average of image} -\label{fg:paverage} -\end{fig2} - -\begin{fig2} -\begin{verbatim} - /* Move area over the image in 100x100 pel chunks. - * im_prepare() will clip against the edges of the image - * for us. - */ - total = 0; - r = ®->valid; - area.width = 100; area.height = 100; - for( area.top = 0; area.top < im->Ysize; area.top += 100 ) - for( area.left = 0; area.left < im->Xsize; - area.left += 100 ) { - /* Fill reg with pels. - */ - if( im_prepare( reg, &area ) ) { - /* We must free the region! - */ - im_region_free( reg ); - return( -1 ); - } - - /* Loop over reg, adding to our total. - */ - for( y = r->top; y < IM_RECT_BOTTOM( r ); y++ ) { - unsigned char *p = IM_REGION_ADDR( reg, r->left, y ); - - for( i = 0; i < IM_REGION_N_ELEMENTS( reg ); i++ ) - total += p[i]; - } - } - - /* Make sure we free the region. - */ - im_region_free( reg ); - - /* Find average. - */ - *out = (double) total / (IM_IMAGE_N_ELEMENTS( im ) * im->Ysize); - - return( 0 ); -} -\end{verbatim} -\caption{First PIO average of image (cont.)} -\end{fig2} - -This version of \verb+average()+ can be called in exactly the same way as -the previous one, but this version has the great advantage of not needing -to have the whole of the input image available at once. - -We can do one better than this --- if the image is being split into small -pieces, we can assign each piece to a separate thread of execution and get -parallelism. To support this splitting of tasks, VIPS has the notion of -a sequence. - -\subsection{Splitting into sequences} -\label{sec:sequence} - -A sequence comes in three parts: a start function, a processing function, -and a stop function. When VIPS starts up a new sequence, it runs the -start function. Start functions return sequence values: a void pointer -representing data local to this sequence. VIPS then repeatedly calls the -processing function, passing in the sequence value and a new piece of image -data for processing. Finally, when processing is complete, VIPS cleans up by -calling the stop function, passing in the sequence value as an argument. The -types look like this: - -\begin{verbatim} -void * -(*start_fn)( IMAGE *out, - void *a, void *b ) -int -(*process_fn)( REGION *reg, - void *seq, void *a, void *b ) -int -(*stop_fn)( void *seq, void *a, void *b ) -\end{verbatim} - -\noindent -The values \verb+a+ and \verb+b+ are carried around by VIPS for your use. - -For functions like \verb+average()+ which consume images but produce no image -output, VIPS provides \verb+vips_sink()+. This has type: - -\begin{verbatim} -int vips_sink( VipsImage *in, - VipsStart start, - VipsGenerate generate, - VipsStop stop, - void *a, void *b ) -\end{verbatim} - -VIPS starts one or more sequences, runs one or more processing functions -over image \verb+in+ until all of \verb+in+ has been consumed, and then closes -all of the sequences down and returns. VIPS guarantees that the regions -the \verb+process_fn()+ is given will be complete and disjoint, that is, -every pixel in the image will be passed through exactly one sequence. To -make it possible for the sequences to each contribute to the result of the -function in an orderly manner, VIPS also guarantees that all start and stop -functions are mutually exclusive. - -An example should make this clearer. This version of \verb+average()+ -is very similar to the average function in the VIPS library --- it is only -missing polymorphism. - -\begin{fig2} -\begin{verbatim} -#include -#include -#include -#include - -/* Start function for average(). We allocate a small piece of - * storage which this sequence will accumulate its total in. Our - * sequence value is just a pointer to this storage area. - * - * The first of the two pointers VIPS carries around for us is a - * pointer to the space where we store the grand total. - */ -static int * -average_start( IMAGE *out ) -{ - int *seq = IM_NEW( out, int ); - - if( !seq ) - return( NULL ); - *seq = 0; - - return( seq ); -} - -/* Stop function for average(). Add the total which has - * accumulated in our sequence value to the grand total for - * the program. - */ -static int -average_stop( int *seq, int *gtotal ) -{ - /* Stop functions are mutually exclusive, so we can write - * to gtotal without clashing with any other stop functions. - */ - *gtotal += *seq; - - return( 0 ); -} -\end{verbatim} -\caption{Final PIO average of image} -\label{fg:p2average} -\end{fig2} - -\begin{fig2} -\begin{verbatim} -/* Process function for average(). Total this region, and - * add that total to the sequence value. - */ -static int -average_process( REGION *reg, int *seq ) -{ - int total, i, y; - Rect *r = ®->valid; - - /* Get the appropriate part of the input image ready. - */ - if( im_prepare( reg, r ) ) - return( -1 ); - - /* Loop over the region. - */ - total = 0; - for( y = r->top; y < IM_RECT_BOTTOM( r ); y++ ) { - unsigned char *p = IM_REGION_ADDR( reg, r->left, y ); - - for( i = 0; i < IM_REGION_N_ELEMENTS( reg ); i++ ) - total += p[i]; - } - - /* Add to the total for this sequence. - */ - *seq += total; - - return( 0 ); -} -\end{verbatim} -\caption{Final PIO average of image (cont.)} -\end{fig2} - -\begin{fig2} -\begin{verbatim} -/* Find average of image. - */ -int -average( IMAGE *im, double *out ) -{ - /* Accumulate grand total here. - */ - int gtotal = 0; - - /* Prepare im for PIO reading. - */ - if( im_pincheck( im ) ) - return( -1 ); - - /* Check it is the sort of thing we can process. - */ - if( im->BandFmt != IM_BANDFMT_UCHAR || - im->Coding != IM_CODING_NONE ) { - im_error( "average", "uncoded uchar images only" ); - return( -1 ); - } - - /* Loop over the image in pieces, and possibly in parallel. - */ - if( vips_sink( im, - average_start, average_process, average_stop, - >otal, NULL ) ) - return( -1 ); - - /* Calculate average. - */ - *out = (double) gtotal / (IM_IMAGE_N_ELEMENTS( im ) * im->Ysize); - - return( 0 ); -} -\end{verbatim} -\caption{Final PIO average of image (cont.)} -\end{fig2} - -There are a couple of variations on \verb+im_prepare()+: you can use -\verb+im_prepare_to()+ to force writing to a particular place, and -\verb+im_prepare_thread()+ to use threaded evaluation. See the man pages. - -\subsection{Output to regions} -\label{sec:generate} - -Regions are written to in just the same way they are read from --- by -writing to a pointer found with the \verb+IM_REGION_ADDR()+ macro. - -\verb+vips_sink()+ does input --- \verb+im_generate()+ does output. It -has the same type as \verb+vips_sink()+: - -\begin{verbatim} -int -im_generate( IMAGE *out, - void *(*start_fn)(), - int (*process_fn)(), - int (*stop_fn)(), - void *a, void *b ) -\end{verbatim} - -The region given to the process function is ready for output. Each time -the process function is called, it should fill in the pels in the region -it was given. Note that, unlike \verb+vips_sink()+, the areas the process -function is asked to produce are not guaranteed to be either disjoint or -complete. Again, VIPS may start up many process functions if it sees fit. - -Here is \verb+invert()+, rewritten to use PIO. This piece of code makes use -of a pair of standard start and stop functions provided by the VIPS library: -\verb+im_start_one()+ and \verb+im_stop_one()+. They assume that the first -of the two user arguments to \verb+im_generate()+ is the input image. They are -defined as: - -\begin{verbatim} -REGION * -im_start_one( IMAGE *out, IMAGE *in ) -{ - return( im_region_create( in ) ); -} -\end{verbatim} - -\noindent -and: - -\begin{verbatim} -int -im_stop_one( REGION *seq ) -{ - return( im_region_free( seq ) ); -} -\end{verbatim} - -They are useful for simple functions which expect only one input -image. See the manual page for \verb+im_start_many()+ for many-input -functions. - -\begin{fig2} -\begin{verbatim} -#include -#include -#include -#include - -/* Process function for invert(). Build the pixels in or - * from the appropriate pixels in ir. - */ -static int -invert_process( REGION *or, REGION *ir ) -{ - Rect *r = &or->valid; - int i, y; - - /* Ask for the part of ir we need to make or. In this - * case, the two areas will be the same. - */ - if( im_prepare( ir, r ) ) - return( -1 ); - - /* Loop over or writing pels calculated from ir. - */ - for( y = r->top; y < IM_RECT_BOTTOM( r ); y++ ) { - unsigned char *p = IM_REGION_ADDR( ir, r->left, y ); - unsigned char *q = IM_REGION_ADDR( or, r->left, y ); - - for( i = 0; i < IM_REGION_N_ELEMENTS( or ); i++ ) - q[i] = 255 - p[i]; - } - - /* Success! - */ - return( 0 ); -} -\end{verbatim} -\caption{PIO invert} -\label{fg:p2invert} -\end{fig2} - -\begin{fig2} -\begin{verbatim} -/* Invert an image. - */ -int -invert( IMAGE *in, IMAGE *out ) -{ - /* Check descriptors for PIO compatibility. - */ - if( im_piocheck( in, out ) ) - return( -1 ); - - /* Check input image for compatibility with us. - */ - if( in->BandFmt != IM_BANDFMT_UCHAR || in->Coding != IM_CODING_NONE ) { - im_error( "invert", "uncoded uchar images only" ); - return( -1 ); - } - - /* out inherits from in, as before. - */ - if( im_cp_desc( out, in ) ) - return( -1 ); - - /* Set demand hints for out. - */ - if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) ) - return( -1 ); - - /* Build out in pieces, and possibly in parallel! - */ - if( im_generate( out, - im_start_one, invert_process, im_stop_one, - in, NULL ) ) - return( -1 ); - - return( 0 ); -} -\end{verbatim} -\caption{PIO invert (cont.)} -\end{fig2} - -Functions have some choice about the way they write their output. Usually, they -should just write to the region they were given by \verb+im_generate()+. They -can, if they wish, set up the region for output to some other place. See -the manual page for \verb+im_region_region()+. See also the source for -\verb+im_copy()+ and \verb+im_extract()+ for examples of these tricks. - -Note also the call to \verb+im_demand_hint()+. This function hints to the IO -system, suggesting the sorts of shapes of region this function is happiest -with. VIPS supports four basic shapes --- choosing the correct shape can -have a dramatic effect on the speed of your function. See the man page for -full details. - -\subsection{Callbacks} -\label{sec:callback} - -VIPS lets you attach callbacks to image descriptors. These are functions -you provide that VIPS will call when certain events occur. There are more -callbacks than are listed here: see the man page for full details. - -\subsubsection{Close callbacks} - -These callbacks are invoked just before an image is closed. They are useful -for freeing objects which are associated with the image. All callbacks are -triggered in the reverse order to the order in which they were attached. This -is sometimes important when freeing objects which contain pointers to -other objects. Close callbacks are guaranteed to be called, and to be called -exactly once. - -Use \verb+im_add_close_callback()+ to add a close callback: - -\begin{verbatim} -typedef int (*im_callback)( void *, void * ) -int im_add_close_callback( IMAGE *, - im_callback_fn, - void *, void * ) -\end{verbatim} - -As with \verb+im_generate()+, the two \verb+void *+ pointers -are carried around for you by VIPS and may be used as your -function sees fit. - -\subsubsection{Preclose callbacks} - -Preclose callbacks are called before any shutdown has occured. Everything is -still alive and your callback can do anything to the image. Preclose callbacks -are guaranteed to be called, and to be called exactly once. See the manual -page for \verb+im_add_preclose_callback()+ for full details. - -\subsubsection{Eval callbacks} - -These are callbacks which are invoked periodically by VIPS during evaluation. -The callback has access to a struct containing information about the progress -of evaluation, useful for user-interfaces built on top of VIPS. See the -manual page for \verb+im_add_eval_callback()+ for full details. - -\subsection{Memory allocation revisited} - -When you are using PIO, memory allocation becomes rather more complicated than -it was before. There are essentially two types of memory which your function -might want to use for working space: memory which is associated with each -instance of your function (remember that two copies of you function may be -joined together in a pipeline and be running at the same time --- you can't -just use global variables), and memory which is local to each sequence -which VIPS starts on your argument image. - -The first type, memory local to this function instance, typically holds -copies of any parameters passed to your image processing function, and links -to any read-only tables used by sequences which you run over the image. This -should be allocated in your main function. - -The second type of memory, memory local to a sequence, should be allocated -in a start function. Because this space is private to a sequence, it may be -written to. Start and stop functions are guaranteed -to be single-threaded, so you may write to the function-local memory within -them. - diff --git a/doc/src/refintro.tex b/doc/src/refintro.tex deleted file mode 100644 index 0c2b5efa..00000000 --- a/doc/src/refintro.tex +++ /dev/null @@ -1,114 +0,0 @@ -\section{Introduction} -\mylabel{sec:ref} - -{/bf -VIPS reference documentation is in the process of switching to gtkdoc. -Half-done manuals are distributed with VIPS, and they should be all done by -the next version. - -In the meantime, this old and slightly outdated chapter has been left -unchanged from the previous version. -} - -This chapter introduces the functions available in the VIPS image -processing library. For detailed information on particular functions, -refer to the UNIX on-line manual pages. Enter (for example): - -\begin{verbatim} -example% man im_abs -\end{verbatim} - -for information on the function \verb+im_abs()+. - -All the comand-line vips operations will print help text too. For example: - -\begin{verbatim} -example% vips im_extract -usage: vips im_extract input output - left top width height band -where: - input is of type "image" - output is of type "image" - left is of type "integer" - top is of type "integer" - width is of type "integer" - height is of type "integer" - band is of type "integer" -extract area/band, from package - "conversion" -flags: (PIO function) - (coordinate transformer) - (area operation) - (result can be cached) -vips: error calling function -im_run_command: too few arguments -\end{verbatim} - -Once you have found a function you need to use, you can call it from a C -program (see \pref{sec:appl}), you can call -it from C++ or Python (see \pref{sec:cpp}), you can call -it from the \nip{} ((see the \emph{nip Manual}), or SIAM graphical -user-interfaces, or you can run it from the UNIX command line with the -\vips{} program. For example: - -\begin{verbatim} -$ vips im_vips2tiff cam.v t1.tif none -$ vips im_tiff2vips t1.tif t2.v.v 0 -$ vips im_equal cam.v t2.v t3.v -$ vips im_min t3.v -255 -\end{verbatim} - -VIPS may have been set up at your site with a set of links which call the -vips program for you. You may also be able to type: - -\begin{verbatim} -$ im_vips2tiff cam.v t1.tif none -$ im_tiff2vips t1.tif t2.v.v 0 -$ im_equal cam.v t2.v t3.v -$ im_min t3.v -\end{verbatim} - -There are a few VIPS programs which you cannot run with \vips{}, either -because their arguments are a very strange, or because they are complete -mini-applications (like \verb+vips2dj+). These programs are listed in -table~\ref{tb:nondb}, see the man pages for full details. - -\begin{tab2} -\centerline{ -\begin{tabular}{|l|l|} -\hline -Name & Description \\ -\hline -\texttt{binfile} & Read RAW image \\ -\texttt{debugim} & Print an image pixel by pixel \\ -\texttt{edvips} & Change fields in a VIPS header \\ -\texttt{header} & Print fields from a VIPS header \\ -\texttt{printlines} & Print an image a line at a time \\ -\texttt{vips} & VIPS universal main program \\ -\texttt{vips-7.14} & VIPS wrapper script \\ -\texttt{find\_mosaic} & Analyse a set of images for overlaps \\ -\texttt{mergeup} & Join a set of images together \\ -\texttt{cooc\_features} & Calculate features of a co-occurence matrix \\ -\texttt{cooc} & Calculate a co-occurence matrix \\ -\texttt{glds\_features} & Calculate features of a grey-level - distribution matrix \\ -\texttt{glds} & Calculate a grey-level distribution matrix \\ -\texttt{simcontr} & Demonstrate simultaneous contrast \\ -\texttt{sines} & Generate a sinusoidal test pattern \\ -\texttt{spatres} & Generate a spatial resolution test pattern \\ -\texttt{squares} & Generate some squares \\ -\texttt{batch\_crop} & Crop a lot of images \\ -\texttt{batch\_image\_convert} & File format convert a lot of images \\ -\texttt{batch\_rubber\_sheet} & Warp a lot of images \\ -\texttt{light\_correct} & Correct a set of images for shading errors \\ -\texttt{mitsub} & Format a VIPS image for output to a Mitsubishi 3600 \\ -\texttt{shrink\_width} & Shrink to a specific width \\ -\texttt{vdump} & VIPS to mono Postscript \\ -\texttt{vips2dj} & VIPS to high-quality colour Postscript \\ -\hline -\end{tabular} -} -\caption{Miscellaneous programs} -\label{tb:nondb} -\end{tab2} diff --git a/doc/src/vdisplay.tex b/doc/src/vdisplay.tex deleted file mode 100644 index f244be71..00000000 --- a/doc/src/vdisplay.tex +++ /dev/null @@ -1,75 +0,0 @@ -\section{The \texttt{VDisplay} class} - -The \verb+VDisplay+ class is an abstraction over the VIPS \verb+im_col_display+ -type which gives convenient and safe representation of VIPS display profiles. - -VIPS display profiles are now mostly obsolete. You're better off using the -ICC colour management \verb+VImage+ member functions \verb+ICC_export()+ and -\verb+ICC_import()+. - -\subsection{Constructors} - -There are two constructors for \verb+VDisplay+: - -\begin{verbatim} -VDisplay( const char *name ); -VDisplay(); -\end{verbatim} - -The first form initialises the display from one of the standard VIPS display -types. For example: - -\begin{verbatim} -VDisplay fred( "sRGB" ); -VDisplay jim( "ultra2-20/2/98" ); -\end{verbatim} - -Makes \verb+fred+ a profile for making images in sRGB format, and \verb+jim+ a -profile representing my workstation display, as of 20/2/98. The second form -of constructor makes an uninitialised display. - -\subsection{Projection functions} - -A set of member functions of \verb+VDisplay+ provide read and write access to -the fields in the display. - -\begin{verbatim} -char *name(); -VDisplayType &type(); -matrix &mat(); -float &YCW(); -float &xCW(); -float &yCW(); -float &YCR(); -float &YCG(); -float &YCB(); -int &Vrwr(); -int &Vrwg(); -int &Vrwb(); -float &Y0R(); -float &Y0G(); -float &Y0B(); -float &gammaR(); -float &gammaG(); -float &gammaB(); -float &B(); -float &P(); -\end{verbatim} - -Where \verb+VDisplayType+ is defined as: - -\begin{verbatim} -enum VDisplayType { - BARCO, - DUMB -}; -\end{verbatim} - -And \verb+matrix+ is defined as: - -\begin{verbatim} -typedef float matrix[3][3]; -\end{verbatim} - -For a description of all the fields in a VIPS display profile, see the manual -page for \verb+im_XYZ2RGB()+. diff --git a/doc/src/verror.tex b/doc/src/verror.tex deleted file mode 100644 index 5680e43e..00000000 --- a/doc/src/verror.tex +++ /dev/null @@ -1,76 +0,0 @@ -\section{The \texttt{VError} class} - -The \verb+VError+ class is the class thrown by the VIPS C++ API when an -error is detected. It is derived from \verb+std::exception+ in the usual way. - -\subsection{Constructors} - -There are two constructors for \verb+VError+: - -\begin{verbatim} -VError( std::string str ); -VError(); -\end{verbatim} - -The first form creates an error object initialised with the specified -string, the last form creates an empty error object. - -\subsection{Projection functions} - -A function gives access to the string held by \verb+VError+: - -\begin{verbatim} -const char *what(); -\end{verbatim} - -You can also send to an \verb+ostream+. - -\begin{verbatim} -std::ostream& operator<<( - std::ostream&, const error& ); -\end{verbatim} - -\subsection{Computing with \texttt{VError}} - -Two member functions let you append elements to an error: - -\begin{verbatim} -VError &app( std::string txt ); -VError &app( const int i ); -\end{verbatim} - -For example: - -\begin{verbatim} -VError wombat; -int n = 12; - -wombat.app( "possum: no more than " ). - app( n ).app( " elements\n" ); -throw( wombat ); -\end{verbatim} - -\noindent -will throw a \verb+VError+ with a diagnostic of: - -\begin{verbatim} -possum: no more than 12 elements -\end{verbatim} - -The member function \verb+perror()+ prints the error message to \verb+stdout+ -and exits with a code of 1. - -\begin{verbatim} -void perror( const char * ); -void perror(); -\end{verbatim} - -\subsection{Convenience function} - -The convenience function \verb+verror+ creates an \verb+VError+ with the -specified error string, and throws it. If you pass \verb+""+ for the string, -verror uses the contents of the VIPS error buffer instead. - -\begin{verbatim} -extern void verror( std::string str = "" ); -\end{verbatim} diff --git a/doc/src/vimage.tex b/doc/src/vimage.tex deleted file mode 100644 index 10be1d96..00000000 --- a/doc/src/vimage.tex +++ /dev/null @@ -1,372 +0,0 @@ -\section{The \texttt{VImage} class} - -The \verb+VImage+ class is a layer over the VIPS \verb+IMAGE+ type. It -automates almost all of the image creation and destruction issues that -complicate the C API, it automates error handling, and it provides a -convenient system for composing operations. - -\subsection{Constructors} - -There are two principal constructors for \verb+VImage+: - -\begin{verbatim} -VImage::VImage( const char *name, - const char *mode = "r" ); -VImage::VImage(); -\end{verbatim} - -The first form creates a new \verb+VImage+, linking it to the named file. -\verb+mode+ sets the mode for the file: it can take the following values: - -\begin{description} - -\item[\texttt{"r"}] -The named image file is opened read-only. This is the default mode. - -\item[\texttt{"w"}] -A \verb+VImage+ is created which, when written to, will write pixels to disc -in the specified file. Any existing file of this name is deleted. - -\item[\texttt{"t"}] -As the \verb'"w"' mode, but pixels written to the \verb+VImage+ will be saved -in a temporary memory buffer. - -\item[\texttt{"p"}] -This creates a special `partial' image. Partial images represent -intermediate results, and are used to join VIPS operations together, -see~\pref{sec:compute}. - -\item[\texttt{"rw"}] -As the \verb'"r"' mode, but the image is mapped into your address space -read-write. This mode is useful for paintbox-style -applications which need to directly modify an image. See \pref{sec:inplace}. - -\end{description} - -The second form of constructor is shorthand for: - -\begin{verbatim} -VImage( "VImage:1", "p" ) -\end{verbatim} - -\noindent -It is used for representing intermediate results of computations. - -Two further constructors are handy for wrapping \verb+VImage+ around existing -images. - -\begin{verbatim} -VImage( void *buffer, - int width, int height, int bands, - TBandFmt format ); -VImage( void *image ); -\end{verbatim} - -\noindent -The first constructor makes a \verb+VImage+ from an area of memory (perhaps -from another image processing system), and the second makes a \verb+VImage+ -from an \verb+IMAGE+. - -In both these two cases, the VIPS C++ API does not assume responsibility -for the resources: it's up to you to make sure the buffer is freed. - -The Python interface adds the usual \verb+frombuffer+ and -\verb+fromstring+ methods. - -\begin{verbatim} -VImage.fromstring (string, - width, height, bands, format) -> - VImage -\end{verbatim} - -\begin{verbatim} -VImage.frombuffer (buffer, - width, height, bands, format) -> - VImage -\end{verbatim} - -\noindent -Use \verb+fromstring+ to avoid worries about object lifetime, but you'll see a -lot of copies and high memory use. Use \verb+frombuffer+ for speed, but you -have to manage object lifetime yourself. - -They are useful for moving images into VIPS from other image processing -libraries. There's also a utility function, \verb+vips_from_PIL_mode+, which -turns a PIL mode into a VIPS band, format, type triple. - -\begin{verbatim} -VImage.vips_from_PIL_mode (mode) -> - (bands, format, type) -\end{verbatim} - -See also \verb+tobuffer+ and \verb+tostring+ below. - -\subsection{File conversion} - -VIPS can read and write a number of different file formats. Information about -file format conversion is taken from the filename. For example: - -\begin{verbatim} -VImage jim( "fred.jpg" ); -\end{verbatim} - -\noindent -This will decompress the file \verb+fred.jpg+ to a memory buffer, wrap a VIPS -image around the buffer and build a reference to it called \verb+jim+. - -Options are passed to the file format converters embedded in the filename. For -example: - -\begin{verbatim} -VImage out( "jen.tif:deflate", "w" ); -\end{verbatim} - -\noindent -Writing to the descriptor \verb+out+ will cause a TIFF image to be written to -disc with deflate compression. - -See the manual page for \verb+im_open(3)+ for details of all the file formats -and conversions available. See the man page for \verb+VipsFormat(3)+ for a -lower-level API which lets you control more of the detail of reading and -writing data and is more suitable for large files. - -\subsection{Projection functions} - -A set of member functions of \verb+VImage+ provide access to the fields in -the header: - -\begin{verbatim} -int Xsize(); -int Ysize(); -int Bands(); -TBandFmt BandFmt(); -TCoding Coding(); -TType Type(); -float Xres(); -float Yres(); -int Length(); -TCompression Compression(); -short Level(); -int Xoffset(); -int Yoffset(); -\end{verbatim} - -\noindent -Where \verb+TBandFmt+, \verb+TCoding+, \verb+TType+ and \verb+TCompression+ -are \verb+enum+s for the types in the VIPS file header. See -section~\pref{sec:header} for an explanation of all of these fields. - -Two functions give access to the filename and history -fields maintained by the VIPS IO system. - -\begin{verbatim} -char *filename(); -char *Hist(); -\end{verbatim} - -You can get and set extra metadata fields with \verb+meta_get()+ and -\verb+meta_set()+. They read and write \verb+GValue+ objects, see -\pref{sec:meta}. - -\begin{verbatim} -void meta_set( const char *field, GValue *value ); -void meta_get( const char *field, GValue *value_copy ); -GType meta_get_type( const char *field ); -\end{verbatim} - -A set of convenience functions build on these two to provide accessors for -common types. - -\begin{verbatim} -int meta_get_int( const char *field ) -double meta_get_double( const char *field ) -const char *meta_get_string( const char *field ) -void *meta_get_area( const char *field ) -void *meta_get_blob( const char *field, size_t *length ) - -void meta_set( const char *field, int value ) -void meta_set( const char *field, double value ) -void meta_set( const char *field, const char *value ) -void meta_set( const char *field, - VCallback free_fn, void *value ) -void meta_set( const char *field, - VCallback free_fn, void *value, size_t length ) -\end{verbatim} - -The \verb+image()+ member function provides access to the \verb+IMAGE+ -descriptor underlying the C++ API. See the \pref{sec:appl} for details. - -\begin{verbatim} -void *image(); -\end{verbatim} - -The \verb+data()+ member function returns a pointer to an array of pixel data -for the image. - -\begin{verbatim} -void *data() const; -\end{verbatim} - -\noindent -This can be very slow and use huge amounts of RAM. - -The Python interface adds \verb+tobuffer+ and \verb+tostring+. These -operations call \verb+data()+ to generate the image pixels and then either -copy it and return the copy as a string, or wrap the pixels up as a Python -buffer object. - -Use \verb+tostring+ to avoid worries about object lifetime, but you'll see a -lot of copies and high memory use. Use \verb+tobuffer+ for speed, but you -have to manage object lifetime yourself. - -They are useful for moving images from VIPS into other image processing -libraries. There's also a utility function, \verb+PIL_mode_from_vips+, which -makes a PIL mode from a VIPS image. - -\begin{verbatim} -VImage.PIL_mode_from_vips (vips-image) -> - mode -\end{verbatim} - -See also \verb+frombuffer+ and \verb+fromstring+ above. - -\subsection{Assignment} - -\verb+VImage+ defines copy and assignment, with reference-counted, -pointer-style semantics. For example, if you write: - -\begin{verbatim} -VImage fred( "fred.v" ); -VImage jim( "jim.v" ); - -fred = jim; -\end{verbatim} - -This will automatically close the file \verb+fred.v+, and make the variable -\verb+fred+ point to the image \verb+jim.v+ instead. Both \verb+jim+ and -\verb+fred+ now point to the same underlying image object. - -Internally, a \verb+VImage+ object is just a pointer to a reference-counting -block, which in turn holds a pointer to the underlying VIPS \verb+IMAGE+ type. -You can therefore efficiently pass \verb+VImage+ objects to functions by -value, and return \verb+VImage+ objects as function results. - -\subsection{Computing with \texttt{VImage}s} -\label{sec:compute} - -All VIPS image processing operations are member functions of the \verb+VImage+ -class. For example: - -\begin{verbatim} -VImage fred( "fred.v" ); -VImage jim( "jim.v" ); - -VImage result = fred.cos() + jim; -\end{verbatim} - -Will apply \verb+im_costra()+ to \verb+fred.v+, making an image where each -pixel is the cosine of the corresponding pixel in \verb+fred.v+; then add that -image to \verb+jim.v+. Finally, the result will be held in \verb+result+. - -VIPS is a demand-driven image processing system: when it computes expressions -like this, no actual pixels are calculated (although you can use the -projection functions on images --- \verb+result.BandFmt()+ for example). When -you finally write the result to a file (or use some operation that needs pixel -values, such as \verb+min()+, find minimum value), VIPS evaluates all of the -operations you have called to that point in parallel. If you have more than one -CPU in your machine, the load is spread over the available processors. This -means that there is no limit to the size of the images you can process. - -\pref{sec:packages} lists all of the VIPS packages. These general -rules apply: - -\begin{itemize} - -\item -VIPS operation names become C++ member function names by dropping the -\verb+im_+ prefix, and if present, the \verb+tra+ postfix, the \verb+const+ -postfix and the \verb+_vec+ postfix. For example, the -VIPS operation \verb+im_extract()+ becomes \verb+extract()+, and -\verb+im_costra()+ becomes \verb+cos()+. - -\item -The \verb+VImage+ object to which you apply the member function is the first -input image, the member function returns the first output. If there is no -image input, the member is declared \verb+static+. - -For example, \verb+im_project(3)+ returns two images. You can call it from -Python like this: - -\begin{verbatim} -hout = VImage.VImage () -vout = im.project (hout) -\end{verbatim} - -\noindent -In other words, \verb+.project()+ writes the second result to the -\verb+VImage+ you pass as an argument. - -\item -\verb+INTMASK+ and \verb+DOUBLEMASK+ types become \verb+VMask+ objects, -\verb+im_col_display+ types become \verb+VDisplay+ objects. - -\item -Several C API functions can map to the same C++ API member. For example, -\verb+im_andimage+, \verb+im_andimage_vec+ and \verb+im_andimageconst+ all map -to the member \verb+andimage+. The API relies on overloading to -discriminate between these functions. - -\end{itemize} - -This part of the C++ API is generated automatically from the VIPS function -database, so it should all be up-to-date. - -There are a set of arithmetic operators defined for your convenience. You can -generally write any arithmetic expression and include \verb+VImage+ in there. - -\begin{verbatim} -VImage fred( "fred.v" ); -VImage jim( "jim.v" ); - -Vimage v = int((fred + jim) / 2); -\end{verbatim} - -\subsection{Writing results} - -Once you have computed some result, you can write it to a file with the member -\verb+write()+. It takes the following forms: - -\begin{verbatim} -VImage write( const char *name ); -VImage write( VImage out ); -VImage write(); -\end{verbatim} - -The first form simply writes the image to the named file. The second form -writes the image to the specified \verb+VImage+ object, for example: - -\begin{verbatim} -VImage fred( "fred.v" ); -VImage jim( "jim buffer", "t" ); - -Vimage v = (fred + 42).write( jim ); -\end{verbatim} - -\noindent -This creates a temporary memory buffer called \verb+jim+, and fills it with -the result of adding 42 to every pixel in \verb+fred.v+. - -The final form of \verb+write()+ writes the image to a memory buffer, and -returns that. - -\subsection{Type conversions} - -Two type conversions are defined: you can cast \verb+VImage+ to a -\verb+VDMask+ and to a \verb+VIMask+. - -\begin{verbatim} -operator VDMask(); -operator VIMask(); -\end{verbatim} - -These operations are slow and need a lot of memory! Emergencies only. diff --git a/doc/src/vipsmanual.tex b/doc/src/vipsmanual.tex deleted file mode 100644 index 703f5896..00000000 --- a/doc/src/vipsmanual.tex +++ /dev/null @@ -1,95 +0,0 @@ -\documentclass[a4paper,twocolumn,dvips]{book} -\usepackage[dvips=false,pdftex=false,vtex=false]{geometry} -\usepackage{ifpdf} -\ifpdf - \usepackage[pdftex]{graphicx,color} -\else - \usepackage{graphicx,color} -\fi -\usepackage{times} -\usepackage{fancyhdr} -\usepackage{ifthen} - -\input{mydefs} - -\fancyhead{} % clear all fields -\fancyhead[LE,RO]{\leftmark} % left-even, right-odd -\fancyhead[RE,LO]{VIPS Manual} % right-even, left-odd -\fancyfoot[LE,RO]{\thepage} % left-even, right-odd -\fancyfoot[RE,LO]{November 2014} - -\begin{document} - -\pagenumbering{roman} - -\begin{titlepage} -\thispagestyle{empty} -\begin{center} -\huge -VIPS Manual\\ -\large Version 7.42\\ -\vspace{0.5in} -\large -John Cupitt, -Kirk Martinez\\ -\end{center} - -VIPS is currently (v. 7.42, November 2014) in an API transition. The API as -documented in 7.24 is still complete and supported and is the one you should -use. The 8.0 API is not yet done and may still change before completion. - -% hmm ... must be a better way to get the quote at the bottom of the page -\vspace{5in} - -This manual formatted \today -\setcounter{page}{1} -\end{titlepage} - -% \blankpage -\tableofcontents -\thispagestyle{plain} - -% \blankpage -\listoffigures -\thispagestyle{plain} - -% \blankpage -\listoftables -\thispagestyle{plain} - -% \blankpage -\pagenumbering{arabic} -\thispagestyle{plain} -\cfoot{} - -\chapter{VIPS from C++ and Python} - -\input{cppintro} -\input{fileformat} -\input{vimage} -\input{vmask} -\input{vdisplay} -\input{verror} - -\chapter{VIPS for C programmers} - -\input{applintro} -\input{iosys} -\input{func} -\input{object} -\input{format} -\input{interpolate} - -\chapter{Writing VIPS operations} - -\input{operintro} -\input{wio} -\input{pio} -\input{ipio} - -\chapter{VIPS reference} - -\input{refintro} -\input{packages} - -\end{document} diff --git a/doc/src/vmask.tex b/doc/src/vmask.tex deleted file mode 100644 index 57b5ce0c..00000000 --- a/doc/src/vmask.tex +++ /dev/null @@ -1,175 +0,0 @@ -\section{The \texttt{VMask} class} - -The \verb+VMask+ class is an abstraction over the VIPS \verb+DOUBLEMASK+ and -\verb+INTMASK+ types which gives convenient and safe representation of -matrices. - -\verb+VMask+ has two sub-classes, \verb+VIMask+ and \verb+VDMask+. These -represent matrices of integers and doubles respectively. - -\subsection{Constructors} - -There are four constructors for \verb+VIMask+ and \verb+VDMask+: - -\begin{verbatim} -VIMask( int xsize, int ysize ); -VIMask( int xsize, int ysize, - int scale, int offset, ... ); -VIMask( int xsize, int ysize, - int scale, int offset, - std::vector coeff ); -VIMask( const char *name ); -VIMask(); -VDMask( int xsize, int ysize ); -VDMask( int xsize, int ysize, - double scale, double offset, ... ); -VDMask( int xsize, int ysize, - double scale, double offset, - std::vector coeff ); -VDMask( const char *name ); -VDMask(); -\end{verbatim} - -The first form creates an empty matrix, with the specified dimensions; -the second form initialises a matrix from a varargs list; the third form -sets the matrix from a vector of coefficients; the fourth from the named file. -The final form makes a mask object with no contents yet. - -The varargs constructors are not wrapped in Python --- use the vector -constructor instead. For example: - -\begin{verbatim} -m = VMask.VIMask (3, 3, 1, 0, - [-1, -1, -1, - -1, 8, -1, - -1, -1, -1]) -\end{verbatim} - -\subsection{Projection functions} - -A set of member functions of \verb+VIMask+ provide access to the fields in -the matrix: - -\begin{verbatim} -int xsize() const; -int ysize() const; -int scale() const; -int offset() const; -const char *filename() const; -\end{verbatim} - -\verb+VDMask+ is the same, except that the \verb+scale()+ and \verb+offset()+ -members return \verb+double+. \verb+VMask+ allows all operations that are -common to \verb+VIMask+ and \verb+VDMask+. - -\subsection{Assignment} - -\verb+VMask+ defines copy and assignment with pointer-style -semantics. You can write stuff like: - -\begin{verbatim} -VIMask fred( "mask" ); -VMask jim; - -jim = fred; -\end{verbatim} - -This reads the file \verb+mask+, noting a pointer to the mask in \verb+fred+. -It then makes \verb+jim+ also point to it, so \verb+jim+ and \verb+fred+ are -sharing the same underlying matrix values. - -Internally, a \verb+VMask+ object is just a pointer to a reference-counting -block, which in turn holds a pointer to the underlying VIPS \verb+MASK+ type. -You can therefore efficiently pass \verb+VMask+ objects to functions by -value, and return \verb+VMask+ objects as function results. - -\subsection{Computing with \texttt{VMask}} - -You can use \verb+[]+ to get at matrix elements, numbered left-to-right, -top-to-bottom. Alternatively, use \verb+()+ to address elements by $x,y$ -position. For example: - -\begin{verbatim} -VIMask fred( "mask" ); - -for( int i = 0; i < fred.xsize(); i++ ) - fred[i] = 12; -\end{verbatim} - -\noindent -will set the first line of the matrix to 12, and: - -\begin{verbatim} -VDMask fred( "mask" ); - -for( int x = 0; x < fred.xsize(); x++ ) - fred(x, x) = 12.0; -\end{verbatim} - -\noindent -will set the leading diagonal to 12. - -These don't work well in Python, so there's an extra member, \verb+get()+, -which will get an element by $x,y$ position. - -\begin{verbatim} -x = mat.get (2, 4) -\end{verbatim} - -See the member functions below for other operations on \verb+VMask+. - -\subsection{\texttt{VIMask} operations} - -The following operations are defined for \verb+VIMask+: - -\begin{verbatim} -// Cast to VDMask and VImage -operator VDMask(); -operator VImage(); - -// Build gaussian and log masks -static VIMask gauss( double, double ); -static VIMask gauss_sep( double, double ); -static VIMask log( double, double ); - -// Rotate -VIMask rotate45(); -VIMask rotate90(); - -// Transpose, invert, join and multiply -VDMask trn() ; -VDMask inv(); -VDMask cat( VDMask ); -VDMask mul( VDMask ); -\end{verbatim} - -\subsection{\texttt{VDMask} operations} - -The following operations are defined for \verb+VDMask+: - -\begin{verbatim} -// Cast to VIMask and VImage -operator VIMask(); -operator VImage(); - -// Build gauss and log masks -static VDMask gauss( double, double ); -static VDMask log( double, double ); - -// Rotate -VDMask rotate45(); -VDMask rotate90(); - -// Scale to intmask -VIMask scalei(); - -// Transpose, invert, join and multiply -VDMask trn(); -VDMask inv(); -VDMask cat( VDMask ); -VDMask mul( VDMask ); -\end{verbatim} - -\subsection{Output of masks} - -You can output masks with the usual \verb+<<+ operator. diff --git a/doc/src/wio.tex b/doc/src/wio.tex deleted file mode 100644 index 6f8eb278..00000000 --- a/doc/src/wio.tex +++ /dev/null @@ -1,363 +0,0 @@ -\section{Programming WIO operations} - -WIO is the style for you if you want ease of programming, or if your -algorithm must have the whole of the input image available at the same -time. For example, a Fourier transform operation is unable to produce any -output until it has seen the whole of the input image. - -\subsection{Input from an image} - -In WIO input, the whole of the image data is made available to the program -via the \verb+data+ field of the descriptor. To make an image ready for reading -in this style, programs should call \verb+im_incheck()+: - -\begin{verbatim} -int im_incheck( IMAGE *im ) -\end{verbatim} - -\noindent -If it succeeds, it returns 0, if it fails, it returns non-zero and -sets \verb+im_error()+. On success, VIPS guarantees that all of the -user-accessible fields in the descriptor contain valid data, and that all -of the image data may be read by simply reading from the \verb+data+ field -(see below for an example). This will only work for images less than about -2GB in size. - -VIPS has some simple macros to help address calculations on images: - -\begin{verbatim} -int IM_IMAGE_SIZEOF_ELEMENT( IMAGE * ) -int IM_IMAGE_SIZEOF_PEL( IMAGE * ) -int IM_IMAGE_SIZEOF_LINE( IMAGE * ) -int IM_IMAGE_N_ELEMENTS( IMAGE * ) -char *IM_IMAGE_ADDR( IMAGE *, - int x, int y ) -\end{verbatim} - -\noindent -These macros calculate \verb+sizeof()+ a band element, a pel and a horizontal -line of pels. \verb+IM_IMAGE_N_ELEMENTS+ returns the number of band elements -across an image. \verb+IM_IMAGE_ADDR+ calculates the address of a pixel in an -image. If \verb+DEBUG+ is defined, it does bounds checking too. - -\begin{fig2} -\begin{verbatim} -#include -#include - -#include - -int -average( IMAGE *im, double *out ) -{ - int x, y; - long total; - - /* Prepare for reading. - */ - if( im_incheck( im ) ) - return( -1 ); - - /* Check that this is the kind of image we can process. - */ - if( im->BandFmt != IM_BANDFMT_UCHAR || - im->Coding != IM_CODING_NONE ) { - im_error( "average", "uncoded uchar images only" ); - return( -1 ); - } - - /* Loop over the image, summing pixels. - */ - total = 0; - for( y = 0; y < im->Ysize; y++ ) { - unsigned char *p = (unsigned char *) IM_IMAGE_ADDR( im, 0, y ); - - for( x = 0; x < IM_IMAGE_N_ELEMENTS( im ); x++ ) - total += p[x]; - } - - /* Calculate average. - */ - *out = (double) total / - (IM_IMAGE_N_ELEMENTS( im ) * im->Ysize)); - - /* Success! - */ - return( 0 ); -} -\end{verbatim} -\caption{Find average of image} -\label{fg:average} -\end{fig2} - -\fref{fg:average} is a simple WIO operation which calculates the -average of an unsigned char image. It will work for any size image, with any -number of bands. See~\pref{sec:poly} for techniques for making operations -which will work for any image type. This operation might be called from an -application with: - -\begin{verbatim} -#include -#include - -#include - -void -find_average( char *name ) -{ - IMAGE *im; - double avg; - - if( !(im = im_open( name, "r" )) || - average( im, &avg ) || - im_close( im ) ) - error_exit( "failure!" ); - - printf( "Average of \"%s\" is %G\n", - name, avg ); -} -\end{verbatim} - -\noindent -When you write an image processing operation, you can test it by writing -a VIPS function descriptor and calling it from the \vips{} universal -main program, or from the \nip{} interface. See \pref{sec:appl}. - -\subsection{Output to an image} - -Before attempting WIO output, programs should call \verb+im_outcheck()+. It -has type: - -\begin{verbatim} -int im_outcheck( IMAGE *im ) -\end{verbatim} - -\noindent -If \verb+im_outcheck()+ succeeds, VIPS guarantees that WIO output is sensible. - -Programs should then set fields in the output descriptor to describe -the sort of image they wish to write (size, type, and so on) and call -\verb+im_setupout()+. It has type: - -\begin{verbatim} -int im_setupout( IMAGE *im ) -\end{verbatim} - -\noindent -\verb+im_setupout()+ creates the output file or memory buffer, using the -size and type fields that were filled in by the program between the calls to -\verb+im_outcheck()+ and \verb+im_setupout()+, and gets it ready for writing. - -Pels are written with \verb+im_writeline()+. This takes a y position (pel -(0,0) is in the top-left-hand corner of the image), a descriptor and a -pointer to a line of pels. It has type: - -\begin{verbatim} -int im_writeline( int y, - IMAGE *im, unsigned char *pels ) -\end{verbatim} - -Two convenience functions are available to make this process slightly -easier. \verb+im_iocheck()+ is useful for programs which take one input -image and produce one image output. It simply calls \verb+im_incheck()+ -and \verb+im_outcheck()+. It has type: - -\begin{verbatim} -int im_iocheck( IMAGE *in, IMAGE *out ) -\end{verbatim} - -The second convenience function copies the fields describing size, type, -metadata and history from one image descriptor to another. It is useful when -the output -image will be similar in size and type to the input image. It has type: - -\begin{verbatim} -int im_cp_desc( IMAGE *out, IMAGE *in ) -\end{verbatim} - -\noindent -There's also \verb+im_cp_descv()+, see the man page. - -\begin{fig2} -\begin{verbatim} -#include -#include - -#include -#include - -int -invert( IMAGE *in, IMAGE *out ) -{ - int x, y; - unsigned char *buffer; - - /* Check images. - */ - if( im_iocheck( in, out ) ) - return( -1 ); - if( in->BandFmt != IM_BANDFMT_UCHAR || in->Coding != IM_CODING_NONE ) { - im_error( "invert", "uncoded uchar images only" ); - return( -1 ); - } - - /* Make output image. - */ - if( im_cp_desc( out, in ) ) - return( -1 ); - if( im_setupout( out ) ) - return( -1 ); - - /* Allocate a line buffer and make sure it will be freed correctly. - */ - if( !(buffer = IM_ARRAY( out, - IM_IMAGE_SIZEOF_LINE( in ), unsigned char )) ) - return( -1 ); - - /* Loop over the image! - */ - for( y = 0; y < in->Ysize; y++ ) { - unsigned char *p = (unsigned char *) IM_IMAGE_ADDR( in, 0, y ); - - for( x = 0; x < IM_IMAGE_N_ELEMENTS( in ); x++ ) - buffer[x] = 255 - p[x]; - if( im_writeline( y, out, buffer ) ) - return( -1 ); - } - - return( 0 ); -} -\end{verbatim} -\caption{Invert an image} -\label{fg:invert} -\end{fig2} - -\fref{fg:invert} is a WIO VIPS operation which finds the photographic -negative of an unsigned char image. See \pref{sec:malloc} for an explanation -of \verb+IM_ARRAY+. This operation might be called from an -application with: - -\begin{verbatim} -#include -#include - -#include - -void -find_negative( char *inn, char *outn ) -{ - IMAGE *in, *out; - - if( !(in = im_open( inn, "r" )) || - !(out = im_open( outn, "w" )) || - invert( in, out ) || - im_updatehist( out, "invert" ) || - im_close( in ) || - im_close( out ) ) - error_exit( "failure!" ); -} -\end{verbatim} - -See \pref{sec:history} for an explanation of the call to \verb+im_updatehist()+. - -\subsection{Polymorphism} -\label{sec:poly} - -Most image processing operations in the VIPS library can operate on -images of any type (\verb+IM_BANDFMT_UCHAR+, as in our examples above, -also \verb+IM_BANDFMT_UINT+ etc.). This is usually implemented with code -replication: the operation contains loops for processing every kind of image, -and when called, invokes the appropriate loop for the image it is given. - -As an example, figure~\ref{fg:exp} calculates \verb+exp()+ for every pel -in an image. If the input image is \verb+double+, we write \verb+double+ -output. If it is any other non-complex type, we write \verb+float+. If it -is complex, we flag an error (\verb+exp()+ of a complex number is fiddly). -The example uses an image type predicate, \verb+im_iscomplex()+. There are -a number of these predicate functions, see the manual page. - -\begin{fig2} -\begin{verbatim} -#include -#include -#include - -#include -#include - -/* Exponential transform. - */ -int -exptra( IMAGE *in, IMAGE *out ) -{ - int x, y; - unsigned char *buffer; - - /* Check descriptors. - */ - if( im_iocheck( in, out ) ) - return( -1 ); - if( in->Coding != IM_CODING_NONE || im_iscomplex( in ) ) { - im_error( "exptra", "uncoded non-complex only" ); - return( -1 ); - } - - /* Make output image. - */ - if( im_cp_desc( out, in ) ) - return( -1 ); - if( in->BandFmt != IM_BANDFMT_DOUBLE ) - out->BandFmt = IM_BANDFMT_FLOAT; - if( im_setupout( out ) ) - return( -1 ); -\end{verbatim} -\caption{Calculate \texttt{exp()} for an image} -\label{fg:exp} -\end{fig2} - -\begin{fig2} -\begin{verbatim} - /* Allocate a line buffer. - */ - if( !(buffer = IM_ARRAY( out, IM_IMAGE_SIZEOF_LINE( in ), unsigned char )) ) - return( -1 ); - -/* Our inner loop, parameterised for both the input and output - * types. Note the use of `\', since macros have to be all on - * one line. - */ -#define loop(IN, OUT) { \ - for( y = 0; y < in->Ysize; y++ ) { \ - IN *p = (IN *) IM_IMAGE_ADDR( in, 0, y ); \ - OUT *q = (OUT *) buffer; \ - \ - for( x = 0; x < IM_IMAGE_N_ELEMENTS( in ); x++ ) \ - q[x] = exp( p[x] ); \ - if( im_writeline( y, out, buffer ) ) \ - return( -1 ); \ - } \ -} - - /* Switch for all the types we can handle. - */ - switch( in->BandFmt ) { - case IM_BANDFMT_UCHAR: loop( unsigned char, float ); break; - case IM_BANDFMT_CHAR: loop( char, float ); break; - case IM_BANDFMT_USHORT:loop( unsigned short, float ); break; - case IM_BANDFMT_SHORT: loop( short, float ); break; - case IM_BANDFMT_UINT: loop( unsigned int, float ); break; - case IM_BANDFMT_INT: loop( int, float ); break; - case IM_BANDFMT_FLOAT: loop( float, float ); break; - case IM_BANDFMT_DOUBLE:loop( double, double ); break; - default: - im_error( "exptra", "internal error" ); - return( -1 ); - } - - /* Success. - */ - return( 0 ); -} -\end{verbatim} -\caption{Calculate \texttt{exp()} for an image (cont)} -\end{fig2} diff --git a/doc/reference/using-C.xml b/doc/using-C.xml similarity index 100% rename from doc/reference/using-C.xml rename to doc/using-C.xml diff --git a/doc/reference/using-command-line.xml b/doc/using-command-line.xml similarity index 100% rename from doc/reference/using-command-line.xml rename to doc/using-command-line.xml diff --git a/doc/reference/using-cpp.xml b/doc/using-cpp.xml similarity index 100% rename from doc/reference/using-cpp.xml rename to doc/using-cpp.xml diff --git a/doc/reference/using-python.xml b/doc/using-python.xml similarity index 100% rename from doc/reference/using-python.xml rename to doc/using-python.xml diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index 0e15e44d..014906cf 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -402,6 +402,7 @@ vips_colour_build( VipsObject *object ) */ if( vips_cast( extra_bands[i], &t1, out->BandFmt, + "shift", TRUE, NULL ) ) { g_object_unref( out ); return( -1 ); diff --git a/libvips/colour/colourspace.c b/libvips/colour/colourspace.c index cbefe3e7..21a980c4 100644 --- a/libvips/colour/colourspace.c +++ b/libvips/colour/colourspace.c @@ -73,17 +73,34 @@ vips_scRGB2RGB16( VipsImage *in, VipsImage **out, ... ) return( vips_scRGB2sRGB( in, out, "depth", 16, NULL ) ); } +/* Do these two with a simple cast ... since we're just cast shifting, we can + * short-circuit the extra band processing in vips_colour_build(). + */ + static int vips_RGB162sRGB( VipsImage *in, VipsImage **out, ... ) { - if( vips_msb( in, out, NULL ) ) + if( vips_cast( in, out, VIPS_FORMAT_UCHAR, + "shift", TRUE, + NULL ) ) return( -1 ); - (*out)->Type = VIPS_INTERPRETATION_sRGB; return( 0 ); } +static int +vips_sRGB2RGB16( VipsImage *in, VipsImage **out, ... ) +{ + if( vips_cast( in, out, VIPS_FORMAT_USHORT, + "shift", TRUE, + NULL ) ) + return( -1 ); + (*out)->Type = VIPS_INTERPRETATION_RGB16; + + return( 0 ); +} + /* Process the first @n bands with @fn, detach and reattach remaining bands. */ static int @@ -102,7 +119,9 @@ vips_process_n( const char *domain, VipsImage *in, VipsImage **out, "n", in->Bands - n, NULL ) || fn( t[0], &t[2], NULL ) || - vips_cast( t[1], &t[3], t[2]->BandFmt, NULL ) || + vips_cast( t[1], &t[3], t[2]->BandFmt, + "shift", TRUE, + NULL ) || vips_bandjoin2( t[2], t[3], out, NULL ) ) { g_object_unref( scope ); return( -1 ); diff --git a/libvips/conversion/cast.c b/libvips/conversion/cast.c index 50bcba40..0fae1aae 100644 --- a/libvips/conversion/cast.c +++ b/libvips/conversion/cast.c @@ -47,6 +47,8 @@ * - redone as a class * 10/4/12 * - cast to uint now removes <0 values + * 11/2/15 + * - add @shift option */ /* @@ -101,6 +103,7 @@ typedef struct _VipsCast { VipsImage *in; VipsBandFormat format; + gboolean shift; int underflow; /* Number of underflows */ int overflow; /* Number of overflows */ @@ -179,6 +182,33 @@ vips_cast_start( VipsImage *out, void *a, void *b ) return( seq ); } +/* Rightshift an integer type, ie. sizeof(ITYPE) > sizeof(OTYPE). + */ +#define VIPS_SHIFT_RIGHT( ITYPE, OTYPE ) { \ + ITYPE * restrict p = (ITYPE *) in; \ + OTYPE * restrict q = (OTYPE *) out; \ + int n = ((int) sizeof( ITYPE ) << 3) - ((int) sizeof( OTYPE ) << 3); \ + \ + g_assert( sizeof( ITYPE ) > sizeof( OTYPE ) ); \ + \ + for( x = 0; x < sz; x++ ) \ + q[x] = p[x] >> n; \ +} + +/* Leftshift an integer type, ie. sizeof(ITYPE) < sizeof(OTYPE). We need to + * copy the bottom bit up into the fresh new bits + */ +#define VIPS_SHIFT_LEFT( ITYPE, OTYPE ) { \ + ITYPE * restrict p = (ITYPE *) in; \ + OTYPE * restrict q = (OTYPE *) out; \ + int n = ((int) sizeof( OTYPE ) << 3) - ((int) sizeof( ITYPE ) << 3); \ + \ + g_assert( sizeof( ITYPE ) < sizeof( OTYPE ) ); \ + \ + for( x = 0; x < sz; x++ ) \ + q[x] = (p[x] << n) | (((p[x] & 1) << n) - (p[x] & 1)); \ +} + /* Cast int types to an int type. */ #define VIPS_CLIP_INT_INT( ITYPE, OTYPE, VIPS_CLIP ) { \ @@ -194,6 +224,21 @@ vips_cast_start( VipsImage *out, void *a, void *b ) } \ } +/* Int to int handling. + */ +#define VIPS_INT_INT( ITYPE, OTYPE, VIPS_CLIP ) { \ + if( cast->shift && \ + sizeof( ITYPE ) > sizeof( OTYPE ) ) { \ + VIPS_SHIFT_RIGHT( ITYPE, OTYPE ); \ + } \ + else if( cast->shift ) { \ + VIPS_SHIFT_LEFT( ITYPE, OTYPE ); \ + } \ + else { \ + VIPS_CLIP_INT_INT( ITYPE, OTYPE, VIPS_CLIP ); \ + } \ +} + /* Cast float types to an int type. */ #define VIPS_CLIP_FLOAT_INT( ITYPE, OTYPE, VIPS_CLIP ) { \ @@ -348,42 +393,42 @@ vips_cast_gen( VipsRegion *or, void *vseq, void *a, void *b, switch( cast->in->BandFmt ) { case VIPS_FORMAT_UCHAR: BAND_SWITCH_INNER( unsigned char, - VIPS_CLIP_INT_INT, + VIPS_INT_INT, VIPS_CLIP_REAL_FLOAT, VIPS_CLIP_REAL_COMPLEX ); break; case VIPS_FORMAT_CHAR: BAND_SWITCH_INNER( signed char, - VIPS_CLIP_INT_INT, + VIPS_INT_INT, VIPS_CLIP_REAL_FLOAT, VIPS_CLIP_REAL_COMPLEX ); break; case VIPS_FORMAT_USHORT: BAND_SWITCH_INNER( unsigned short, - VIPS_CLIP_INT_INT, + VIPS_INT_INT, VIPS_CLIP_REAL_FLOAT, VIPS_CLIP_REAL_COMPLEX ); break; case VIPS_FORMAT_SHORT: BAND_SWITCH_INNER( signed short, - VIPS_CLIP_INT_INT, + VIPS_INT_INT, VIPS_CLIP_REAL_FLOAT, VIPS_CLIP_REAL_COMPLEX ); break; case VIPS_FORMAT_UINT: BAND_SWITCH_INNER( unsigned int, - VIPS_CLIP_INT_INT, + VIPS_INT_INT, VIPS_CLIP_REAL_FLOAT, VIPS_CLIP_REAL_COMPLEX ); break; case VIPS_FORMAT_INT: BAND_SWITCH_INNER( signed int, - VIPS_CLIP_INT_INT, + VIPS_INT_INT, VIPS_CLIP_REAL_FLOAT, VIPS_CLIP_REAL_COMPLEX ); break; @@ -499,6 +544,13 @@ vips_cast_class_init( VipsCastClass *class ) VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsCast, format ), VIPS_TYPE_BAND_FORMAT, VIPS_FORMAT_UCHAR ); + + VIPS_ARG_BOOL( class, "shift", 7, + _( "Shift" ), + _( "Shift integer values up and down" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsCast, shift ), + FALSE ); } static void @@ -519,13 +571,22 @@ vips_castv( VipsImage *in, VipsImage **out, VipsBandFormat format, va_list ap ) * @format: format to convert to * @...: %NULL-terminated list of optional named arguments * + * Optional arguments: + * + * @shift: integer values are shifted + * * 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, + * 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_cast_uchar(), vips_msb(). * * Returns: 0 on success, -1 on error */ diff --git a/tools/Makefile.am b/tools/Makefile.am index e9d0f625..f8425dec 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -20,11 +20,11 @@ bin_SCRIPTS = \ batch_rubber_sheet \ batch_crop \ vipsprofile \ - vips-7.42 + vips-8.0 EXTRA_DIST = \ vipsprofile \ - vips-7.42 \ + vips-8.0 \ light_correct.in \ shrink_width.in \ batch_image_convert.in \ diff --git a/tools/vips-8.0 b/tools/vips-8.0 new file mode 100755 index 00000000..bcc1007b --- /dev/null +++ b/tools/vips-8.0 @@ -0,0 +1,129 @@ +#!/bin/bash +# +# Start script for VIPS + +# need extended regexps, hence we insist on bash above +shopt -s extglob +# set -x + +# name we were invoked as +bname=`basename $0` + +# check args +if [[ $# < 1 ]]; then + echo "usage: $bname [command ...]" + echo "examples:" + echo " $bname man im_invert" + echo " $bname vips im_invert /pics/tmp/fred.jpg /pics/tmp/fred2.tif" + exit 1 +fi + +# prepend a path component to an environment variable +# be careful to avoid trailing : characters if the var is not defined, they +# can cause security problems +function prepend_var () { + # we have to use eval to do double indirection, I think + eval value="\$$1" + if [ "x$value" = x ]; then + export $1=$2 + else + export $1=$2:$value + fi +} + +# try to extract the prefix from a path to an executable +# eg. "/home/john/vips/bin/fred" -> "/home/john/vips" +function find_prefix () { + # try to canonicalise the path + ep_canon=$1 + + # relative path? prefix with pwd + if [ ${ep_canon:0:1} != "/" ]; then + ep_canon=`pwd`/$ep_canon + fi + + # replace any "/./" with "/" + ep_canon=${ep_canon//\/.\//\/} + + # any "xxx/../" can go + ep_canon=${ep_canon//+([^\/])\/..\//} + + # trailing "xxx/.." can go + ep_canon=${ep_canon/%+([^\/])\/../} + + # remove trailing "/bin/xxx" to get the prefix + ep_prefix=${ep_canon/%\/bin\/+([^\/])/} + + # was there anything to remove in that final step? if not, the path + # must be wrong + if [ x$ep_prefix == x$ep_canon ]; then + return 1 + fi + + echo $ep_prefix; + + return 0 +} + +# try to guess the install prefix from $0 +function guess_prefix () { + # $0 is a file? must be us + if [ -f $0 ]; then + find_prefix $0 + return + fi + + # nope, extract program name from $0 and try looking along the + # searchpath for it + name=`basename $0` + + fred=$PATH + while [ x$fred != x"" ]; do + path=${fred/:*/}/$name + fred=${fred/*([^:])?(:)/} + + if [ -f $path ]; then + find_prefix $path + return + fi + done + + # not found on path either ... give up! + return 1 +} + +prefix=`guess_prefix`; + +if [ $? != 0 ]; then + echo "unable to find $0 from the file name, or from your PATH" + echo "either run directly, or add the install bin area to " + echo "your PATH" + exit 1 +fi + +export VIPSHOME=$prefix + +# add VIPSHOME to man pages +prepend_var MANPATH $VIPSHOME/man + +# add the VIPS lib area to the library path +case `uname` in +HPUX) + libvar=SHLIB_PATH + ;; + +Darwin) + libvar=DYLD_LIBRARY_PATH + ;; + +*) + libvar=LD_LIBRARY_PATH + ;; +esac +prepend_var $libvar $VIPSHOME/lib + +# add VIPS bin area to path +prepend_var PATH $VIPSHOME/bin + +# run, passing in args we were passed +exec $*