merge gtkdoc branch

This commit is contained in:
John Cupitt 2009-08-16 15:00:08 +00:00
parent 9fcdda8df7
commit 4e76695e19
447 changed files with 142507 additions and 70 deletions

View File

@ -9,6 +9,11 @@
- now (more or less) passes -Wextra
- added "fail" option to im_jpeg2vips: fail with an error on any warning
(thank you Ole)
- started gtk-doc changes
- renamed im_meta_get_type() and im_header_get_type() as
im_meta_get_typeof() and im_header_get_typeof() to prevent confusion with
GObject type definers (was breaking gtkdoc object scan)
- revised more names, limited documented API
- im_buildlut() could segv for non-zero based tables (thanks Jack)
- VIPS_BUF_STATIC() does not take length arg
- check for SetImageOption() so we work with GraphicsMagick too

View File

@ -1,24 +1,24 @@
# only build in the python dir if we can
if HAVE_PYTHON
P_COMPILE_DIR = python
P_COMPILE_DIR = swig
P_DIST_DIR =
else
P_COMPILE_DIR =
P_DIST_DIR = python
P_DIST_DIR = swig
endif
SUBDIRS = \
libsrc \
src \
include \
libsrcCC \
libvips \
tools \
libvipsCC \
contrib \
man \
po \
doc \
$(P_COMPILE_DIR)
EXTRA_DIST = \
doc \
m4 \
benchmark \
bootstrap.sh \
vipsCC-7.${IM_MINOR_VERSION}.pc.in \
@ -45,3 +45,4 @@ uninstall-hook:
-chmod -R u+w ${DESTDIR}$(datadir)/doc/vips
-rm -rf ${DESTDIR}$(datadir)/doc/vips
DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc

54
TODO
View File

@ -36,7 +36,59 @@
- COPYInG file should be lgpl2.1+? seems to be plain 2.1 atm
- look at gtk-doc? installed now
- need a separate sectrion in ref docs for vips, vipsCC (and python?)
- try the new liboil thing:
http://www.schleef.org/orc/
pick something like abs and time it
- im__cast_and_call() no longer does
out->Bbits = im_bits_of_fmt( out->BandFmt );
make sure we do this for each use of im__cast_and_call()
- im__cast_and_call() no longer casts input to output type, it casts inputs
up to the smallest common type
so we need to change all the buffer processors from
T op T -> T
to
T1 op T1 -> T2
- split proto.h into headers for arithmetic etc.
- move headers into libsrc/arithmetic, can we get them installed into the
right prefix?
- move VImage.h into libsrcCC
- rename libsrc as libvips
- rename src as vipstools
- rename libsrcCC as libvipsCC
- rename python as SWIG
- rename vipsCC in SWIG as pyvips
- try the new liboil thing:

View File

@ -8,10 +8,13 @@ rm -rf autom4te.cache
rm -f config.* configure depcomp
rm -f install-sh intltool-* libtool ltmain.sh missing mkinstalldirs
rm -f stamp-* vipsCC-7.19.pc vips-7.19.spec vips-7.19.pc
rm -f python/vipsCC/*.cxx
rm -f python/vipsCC/VImage.h
rm -f python/vipsCC/VImage.py python/vipsCC/VError.py python/vipsCC/VMask.py python/vipsCC/Display.py
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/VIPS-docs.sgml.in poop ; mv reference/Makefile.am poop ; rm -rf reference/* ; mv poop/* reference ; rmdir poop )
gtkdocize --copy --docdir doc/reference --flavour no-tmpl || exit 1
# some systems need libtoolize, some glibtoolize ... how annoying
echo testing for glibtoolize ...
@ -32,4 +35,3 @@ autoconf
autoheader
$LIBTOOLIZE --copy --force --automake
automake --add-missing --copy

View File

@ -1,6 +1,7 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(include/vips/colour.h)
AC_INIT(libvips/include/vips/colour.h)
AM_CONFIG_HEADER(config.h)
AC_CONFIG_MACRO_DIR(m4)
# user-visible library versioning
IM_MAJOR_VERSION=7
@ -204,6 +205,9 @@ if test x"$enable_threads" != "xno"; then
enable_threads=yes
fi
# check for gtk-doc
GTK_DOC_CHECK(1.9)
# optional supporting libraries
# we can wrap fftw3 and fftw2 ... but just look for fftw3, since we can do
@ -494,41 +498,42 @@ AC_OUTPUT([
vipsCC-7.19.pc
vips-7.19.spec
Makefile
include/vips/version.h
include/Makefile
include/vips/Makefile
libsrc/Makefile
libsrc/acquire/Makefile
libsrc/arithmetic/Makefile
libsrc/boolean/Makefile
libsrc/cimg/Makefile
libsrc/colour/Makefile
libsrc/conversion/Makefile
libsrc/convolution/Makefile
libsrc/format/Makefile
libsrc/freq_filt/Makefile
libsrc/histograms_lut/Makefile
libsrc/inplace/Makefile
libsrc/iofuncs/Makefile
libsrc/matrix/Makefile
libsrc/morphology/Makefile
libsrc/mosaicing/Makefile
libsrc/other/Makefile
libsrc/relational/Makefile
libsrc/resample/Makefile
libsrc/video/Makefile
libsrcCC/Makefile
src/Makefile
src/iofuncs/Makefile
src/mosaicing/Makefile
src/other/Makefile
src/scripts/Makefile
src/scripts/batch_crop
src/scripts/batch_image_convert
src/scripts/batch_rubber_sheet
src/scripts/light_correct
src/scripts/shrink_width
man/Makefile
libvips/include/vips/version.h
libvips/include/Makefile
libvips/include/vips/Makefile
libvips/Makefile
libvips/acquire/Makefile
libvips/arithmetic/Makefile
libvips/boolean/Makefile
libvips/cimg/Makefile
libvips/colour/Makefile
libvips/conversion/Makefile
libvips/convolution/Makefile
libvips/format/Makefile
libvips/freq_filt/Makefile
libvips/histograms_lut/Makefile
libvips/inplace/Makefile
libvips/iofuncs/Makefile
libvips/matrix/Makefile
libvips/morphology/Makefile
libvips/mosaicing/Makefile
libvips/other/Makefile
libvips/relational/Makefile
libvips/resample/Makefile
libvips/video/Makefile
libvipsCC/include/Makefile
libvipsCC/include/vipsCC/Makefile
libvipsCC/Makefile
tools/Makefile
tools/iofuncs/Makefile
tools/mosaicing/Makefile
tools/other/Makefile
tools/scripts/Makefile
tools/scripts/batch_crop
tools/scripts/batch_image_convert
tools/scripts/batch_rubber_sheet
tools/scripts/light_correct
tools/scripts/shrink_width
contrib/Makefile
contrib/vips2dj/Makefile
contrib/vips2dj/share/Makefile
@ -538,8 +543,12 @@ AC_OUTPUT([
contrib/vips2dj/share/vips2dj/mono/Makefile
contrib/vdump/Makefile
contrib/mitsub/Makefile
python/Makefile
python/vipsCC/Makefile
swig/Makefile
swig/vipsCC/Makefile
man/Makefile
doc/Makefile
doc/reference/Makefile
doc/reference/VIPS-docs.sgml
po/Makefile.in
])
@ -549,6 +558,7 @@ native win32: $vips_os_win32
open files in binary mode: $vips_binary_open
evaluate with threads: $enable_threads
make symlinks for commands in bin: $enable_links
build docs with gtkdoc $enable_gtk_doc
* optional packages and modules
use fftw3 for FFT: $with_fftw3

View File

@ -2,6 +2,6 @@ bin_PROGRAMS = mitsub
mitsub_SOURCES = mitsub.c
INCLUDES = -I${top_srcdir}/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
AM_LDFLAGS = @LDFLAGS@
LDADD = @VIPS_CFLAGS@ ${top_builddir}/libsrc/libvips.la @VIPS_LIBS@
LDADD = @VIPS_CFLAGS@ ${top_builddir}/libvips/libvips.la @VIPS_LIBS@

View File

@ -8,8 +8,8 @@ man_MANS = \
pkgdata_DATA = \
vdump.pro
INCLUDES = -I${top_srcdir}/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
AM_LDFLAGS = @LDFLAGS@
LDADD = @VIPS_CFLAGS@ ${top_builddir}/libsrc/libvips.la @VIPS_LIBS@
LDADD = @VIPS_CFLAGS@ ${top_builddir}/libvips/libvips.la @VIPS_LIBS@
EXTRA_DIST = $(pkgdata_DATA) $(man_MANS)

View File

@ -9,9 +9,9 @@ vips2dj_SOURCES = \
vips2ah.c \
vips2dj.c
INCLUDES = -I${top_srcdir}/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
AM_LDFLAGS = @LDFLAGS@
LDADD = @VIPS_CFLAGS@ ${top_builddir}/libsrc/libvips.la @VIPS_LIBS@
LDADD = @VIPS_CFLAGS@ ${top_builddir}/libvips/libvips.la @VIPS_LIBS@
EXTRA_DIST = ${vips2dj_DEPENDENCIES}

View File

@ -1,13 +0,0 @@
#
prefix = /home/john/vips
install all:
cd src; $(MAKE) -f Makefile install
echo "Making html man pages"
./Makehtmlman $(prefix)/share/man/man1
./Makehtmlman $(prefix)/share/man/man3
.PHONEY: clean
clean:
cd src; $(MAKE) -f Makefile clean

10
doc/Makefile.am Normal file
View File

@ -0,0 +1,10 @@
SUBDIRS = reference
EXTRA_DIST = \
html \
pdf \
src \
makefile.tex \
Makehtmlman \
README

View File

@ -1,6 +1,6 @@
VIPS documentation
edit Makefile and change "prefix" to be your install prefix (eg.
edit makefile.tex and change "prefix" to be your install prefix (eg.
"/usr/local/vips-7.8") ... the HTML man page maker will pull manual pages from
this area

101
doc/reference/Makefile.am Normal file
View File

@ -0,0 +1,101 @@
## 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=VIPS
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
DOC_MODULE_VERSION=7
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# The directory containing the source code. Relative to $(srcdir).
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting the functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk
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=--sgml-mode --output-format=xml
MKDB_OPTIONS=--sgml-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 to ignore when scanning. Use base file name, no paths
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
IGNORE_HFILES=merge.h debug.h internal.h intl.h CImg.h im_video_v4l1.h global_balance.h dbh.h base64.h templates.h mosaic.h deprecated.h thread.h private.h internal.h almostdeprecated.h fmask.h inlines.h r_access.h struct.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# 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=
# 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=
# 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)
# (use VIPS_CFLAGS/VIPS_LIBS/VIPS_LIBS so we pick up the glib-object.h that
# the scanner uses)
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 $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
#EXTRA_DIST +=
# 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 = VIPS.types
# Comment this out if you want your docs-status tested during 'make check'
if ENABLE_GTK_DOC
#TESTS_ENVIRONMENT = cd $(srcsrc)
#TESTS = $(GTKDOC_CHECK)
endif

View File

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>VIPS Reference Manual</title>
<releaseinfo>
for VIPS 7.19.0
The latest version of this documentation can be found on-line at
<ulink role="online-location"
url="http://http://www.vips.ecs.soton.ac.uk/index.php?title=Documentation">http://www.vips.ecs.soton.ac.uk/index.php?title=Documentation</ulink>.
</releaseinfo>
</bookinfo>
<chapter>
<title>API by section</title>
<xi:include href="xml/format.xml"/>
<xi:include href="xml/interpolate.xml"/>
<xi:include href="xml/object.xml"/>
<xi:include href="xml/proto.xml"/>
<xi:include href="xml/colour.xml"/>
<xi:include href="xml/region.xml"/>
<xi:include href="xml/arithmetic.xml"/>
<xi:include href="xml/meta.xml"/>
<xi:include href="xml/image.xml"/>
<xi:include href="xml/transform.xml"/>
<xi:include href="xml/util.xml"/>
<xi:include href="xml/threadgroup.xml"/>
<xi:include href="xml/version.xml"/>
<xi:include href="xml/type.xml"/>
<xi:include href="xml/rect.xml"/>
<xi:include href="xml/buf.xml"/>
<xi:include href="xml/semaphore.xml"/>
<xi:include href="xml/dispatch.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>VIPS Reference Manual</title>
<releaseinfo>
for VIPS @IM_VERSION@
The latest version of this documentation can be found on-line at
<ulink role="online-location"
url="http://http://www.vips.ecs.soton.ac.uk/index.php?title=Documentation">http://www.vips.ecs.soton.ac.uk/index.php?title=Documentation</ulink>.
</releaseinfo>
</bookinfo>
<chapter>
<title>API by section</title>
<xi:include href="xml/format.xml"/>
<xi:include href="xml/interpolate.xml"/>
<xi:include href="xml/object.xml"/>
<xi:include href="xml/proto.xml"/>
<xi:include href="xml/colour.xml"/>
<xi:include href="xml/region.xml"/>
<xi:include href="xml/arithmetic.xml"/>
<xi:include href="xml/meta.xml"/>
<xi:include href="xml/image.xml"/>
<xi:include href="xml/transform.xml"/>
<xi:include href="xml/util.xml"/>
<xi:include href="xml/threadgroup.xml"/>
<xi:include href="xml/version.xml"/>
<xi:include href="xml/type.xml"/>
<xi:include href="xml/rect.xml"/>
<xi:include href="xml/buf.xml"/>
<xi:include href="xml/semaphore.xml"/>
<xi:include href="xml/dispatch.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

177
gtk-doc.make Normal file
View File

@ -0,0 +1,177 @@
# -*- mode: makefile -*-
####################################
# Everything below here is generic #
####################################
if GTK_DOC_USE_LIBTOOL
GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
GTKDOC_RUN = $(LIBTOOL) --mode=execute
else
GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
GTKDOC_RUN = sh -c
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)
EXTRA_DIST = \
$(content_files) \
$(HTML_IMAGES) \
$(DOC_MAIN_SGML_FILE) \
$(DOC_MODULE)-sections.txt \
$(DOC_MODULE)-overrides.txt
DOC_STAMPS=scan-build.stamp sgml-build.stamp html-build.stamp \
$(srcdir)/sgml.stamp $(srcdir)/html.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
CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS)
if ENABLE_GTK_DOC
all-local: html-build.stamp
else
all-local:
endif
docs: html-build.stamp
$(REPORT_FILES): sgml-build.stamp
#### scan ####
scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB)
@echo 'gtk-doc: Scanning header files'
@-chmod -R u+w $(srcdir)
cd $(srcdir) && \
gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(SCAN_OPTIONS) $(EXTRA_HFILES)
if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \
CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \
else \
cd $(srcdir) ; \
for i in $(SCANOBJ_FILES) ; do \
test -f $$i || touch $$i ; \
done \
fi
touch scan-build.stamp
$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp
@true
#### xml ####
sgml-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files)
@echo 'gtk-doc: Building XML'
@-chmod -R u+w $(srcdir)
cd $(srcdir) && \
gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $(MKDB_OPTIONS)
touch sgml-build.stamp
sgml.stamp: sgml-build.stamp
@true
#### html ####
html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files)
@echo 'gtk-doc: Building HTML'
@-chmod -R u+w $(srcdir)
rm -rf $(srcdir)/html
mkdir $(srcdir)/html
mkhtml_options=""; \
gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \
if test "$(?)" = "0"; then \
mkhtml_options=--path="$(srcdir)"; \
fi
cd $(srcdir)/html && gtkdoc-mkhtml $(mkhtml_options) $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html )
@echo 'gtk-doc: Fixing cross-references'
cd $(srcdir) && gtkdoc-fixxref --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
touch html-build.stamp
##############
clean-local:
rm -f *~ *.bak
rm -rf .libs
distclean-local:
cd $(srcdir) && \
rm -rf xml $(REPORT_FILES) \
$(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
maintainer-clean-local: clean
cd $(srcdir) && rm -rf html
install-data-local:
installfiles=`echo $(srcdir)/html/*`; \
if test "$$installfiles" = '$(srcdir)/html/*'; \
then echo '-- 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 '-- Installing '$$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; \
mv -f $${installdir}/$(DOC_MODULE).devhelp \
$${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp; \
fi; \
! which gtkdoc-rebase >/dev/null 2>&1 || \
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 ENABLE_GTK_DOC
dist-check-gtkdoc:
else
dist-check-gtkdoc:
@echo "*** gtk-doc must be installed and enabled in order to make dist"
@false
endif
dist-hook: dist-check-gtkdoc dist-hook-local
mkdir $(distdir)/html
cp $(srcdir)/html/* $(distdir)/html
-cp $(srcdir)/$(DOC_MODULE).types $(distdir)/
-cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/
cd $(distdir) && rm -f $(DISTCLEANFILES)
! which gtkdoc-rebase >/dev/null 2>&1 || \
gtkdoc-rebase --online --relative --html-dir=$(distdir)/html
.PHONY : dist-hook-local docs

67
libvips/Makefile.am Normal file
View File

@ -0,0 +1,67 @@
# only build in the cimg dir if it's enabled
if WITH_CIMG
C_COMPILE_DIR = cimg
C_DIST_DIR =
C_LIB = cimg/libcimg.la
else
C_COMPILE_DIR =
C_DIST_DIR = cimg
C_LIB =
endif
SUBDIRS = \
include \
acquire \
arithmetic \
resample \
boolean \
colour \
conversion \
convolution \
$(C_COMPILE_DIR) \
format \
freq_filt \
histograms_lut \
inplace \
iofuncs \
matrix \
morphology \
mosaicing \
other \
relational \
video \
.
lib_LTLIBRARIES = libvips.la
libvips_la_SOURCES = dummy.c dummy2.cc
# DLLs need dependant libs there too ... put @VIPS_LIBS@ at the end
libvips_la_LIBADD = \
acquire/libacquire.la \
resample/libresample.la \
arithmetic/libarithmetic.la \
boolean/libboolean.la \
colour/libcolour.la \
conversion/libconversion.la \
convolution/libconvolution.la \
$(C_LIB) \
format/libformat.la \
freq_filt/libfreq_filt.la \
histograms_lut/libhistograms_lut.la \
inplace/libinplace.la \
iofuncs/libiofuncs.la \
matrix/libmatrix.la \
morphology/libmorphology.la \
mosaicing/libmosaicing.la \
other/libother.la \
relational/librelational.la \
video/libvideo.la \
@VIPS_LIBS@
libvips_la_LDFLAGS = \
-no-undefined \
-version-info @LIBRARY_CURRENT@:@LIBRARY_REVISION@:@LIBRARY_AGE@
EXTRA_DIST = \
$(C_DIST_DIR)

View File

@ -0,0 +1,7 @@
noinst_LTLIBRARIES = libacquire.la
libacquire_la_SOURCES = \
im_clamp.c
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

127
libvips/acquire/im_clamp.c Normal file
View File

@ -0,0 +1,127 @@
/* @(#) Function to perform black level correction given black image
* @(#) designed for PAD camera single field black to apply in blocks
* @(#) as each is reused for higher resolution pels (eg: 6 8 for Progres)
* @(#) IM_BANDFMT_UCHAR images only. Always writes UCHAR.
* @(#) int im_clamp(in, w, out, hstep, vstep)
* @(#) IMAGE *in, *w, *out; int hstep, vstep;
* @(#) - Compute clip(image - (black)) ie subtract black no negatives
* @(#) scales for low res Progres images to replicate black value
* @(#) Returns 0 on success and -1 on error
* fiddle at your peril - nasty code
* Copyright: 1993 KM
* 20/8/93
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
int
im_clamp( in, out,black, hstep, vstep )
IMAGE *in, *black, *out;
int hstep, vstep;
{ PEL *p, *blk, *bline, *bexp;
PEL *q, *outbuf;
int rep;
int x, y, bnd;
int temp, blacky, newblacky;
if( im_iocheck( in, out ) )
return( -1 );
if( in->Bbits != 8 ||
in->Coding != IM_CODING_NONE || in->BandFmt != IM_BANDFMT_UCHAR ) {
im_error( "im_clamp", "%s", _( "bad input format" ) );
return( -1 );
}
if( black->Bbits != 8 ||
black->Coding != IM_CODING_NONE || black->BandFmt != IM_BANDFMT_UCHAR ) {
im_error( "im_clamp", "%s", _( "bad black format" ) );
return( -1 );
}
/* Set up the output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
if( im_setupout( out ) )
return( -1 );
/* Make buffer for expanded black line
*/
if( !(bline = (PEL *) im_malloc( out, black->Bands * hstep * in->Xsize )) )
return( -1 );
/* Make buffer we write to.
*/
if( !(outbuf = (PEL *) im_malloc( out, out->Bands * out->Xsize )) )
return( -1 );
blacky = -1;
p = (PEL *) in->data;
for( y = 0; y < in->Ysize; y++ ) {
/* calc corresponding black line - get new one if different */
newblacky = (vstep * black->Ysize - in->Ysize + y)/vstep;
if( newblacky != blacky){
blacky = newblacky;
/* time to expand a new black line */
blk = (PEL *) (black->data +
black->Xsize * black->Bands * blacky);
for(bexp = bline, x = 0; x < black->Xsize; x++){
for(rep = 0; rep < hstep; rep++)
for(q=blk, bnd = 0; bnd < in->Bands; bnd++)
*bexp++ = *q++;
blk += black->Bands;
}
}
/* correct a line of image */
bexp = bline;
q = outbuf;
for( x = 0; x < (out->Bands * out->Xsize); x++ ) {
temp = ((int) *p++ - *bexp++);
if( temp < 0 ) temp = 0;
*q++ = (PEL)temp;
}
if( im_writeline( y, out, outbuf ) )
return( -1 );
} /* end of a line */
return( 0 );
}

View File

@ -0,0 +1,45 @@
noinst_LTLIBRARIES = libarithmetic.la
libarithmetic_la_SOURCES = \
arith_dispatch.c \
im_abs.c \
im_add.c \
im_avg.c \
im_point_bilinear.c \
im_bandmean.c \
im_cmulnorm.c \
im_costra.c \
im_cross_phase.c \
im_deviate.c \
im_divide.c \
im_ceil.c \
im_floor.c \
im_expntra.c \
im_fav4.c \
im_gadd.c \
im_gaddim.c \
im_gfadd.c \
im_invert.c \
im_linreg.c \
im_lintra.c \
im_litecor.c \
im_log10tra.c \
im_logtra.c \
im_max.c \
im_maxpos.c \
im_maxpos_avg.c \
im_maxpos_vec.c \
im_measure.c \
im_min.c \
im_minpos.c \
im_multiply.c \
im_powtra.c \
im_remainder.c \
im_rint.c \
im_sign.c \
im_sintra.c \
im_stats.c \
im_subtract.c \
im_tantra.c
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

File diff suppressed because it is too large Load Diff

272
libvips/arithmetic/im_abs.c Normal file
View File

@ -0,0 +1,272 @@
/* im_abs()
*
* Copyright: 1990, N. Dessipris, based on im_powtra()
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 5/5/93 J.Cupitt
* - adapted from im_lintra to work with partial images
* - complex and signed support added
* 30/6/93 JC
* - adapted for partial v2
* - ANSI conversion
* - spe29873r6k3h()**!@lling errors removed
* 9/2/95 JC
* - adapted for im_wrap...
* 20/6/02 JC
* - tiny speed up
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Integer abs operation: just test and negate.
*/
#define intabs(TYPE) \
{ \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
int x; \
\
for( x = 0; x < sz; x++ ) { \
TYPE v = p[x]; \
\
if( v < 0 ) \
q[x] = 0 - v; \
else \
q[x] = v; \
} \
}
/* Float abs operation: call fabs().
*/
#define floatabs(TYPE)\
{\
TYPE *p = (TYPE *) in;\
TYPE *q = (TYPE *) out;\
int x; \
\
for( x = 0; x < sz; x++ )\
q[x] = fabs( p[x] );\
}
/* Complex abs operation: calculate modulus.
*/
#ifdef HAVE_HYPOT
#define complexabs(TYPE) { \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
int i; \
\
for( i = 0; i < sz; i++ ) { \
q[i] = hypot( p[0], p[1] ); \
p += 2; \
} \
}
#else /*HAVE_HYPOT*/
#define complexabs(TYPE) { \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
TYPE *q_stop = q + sz; \
\
while( q < q_stop ){ \
double rp = *p++; \
double ip = *p++; \
double abs_rp= fabs( rp ); \
double abs_ip= fabs( ip ); \
\
if( abs_rp > abs_ip ){ \
double temp= ip / rp; \
*q++= abs_rp * sqrt( 1.0 + temp * temp ); \
} \
else { \
double temp= rp / ip; \
*q++= abs_ip * sqrt( 1.0 + temp * temp ); \
} \
} \
}
#endif /*HAVE_HYPOT*/
/* Abs a buffer of PELs.
*/
static void
abs_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int sz = width * im->Bands;
/* Abs all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR:
#ifdef HAVE_LIBOIL
oil_abs_u8_s8( (uint8_t *) out, sizeof( uint8_t ),
(int8_t *) in, sizeof( int8_t ), sz );
#else /*!HAVE_LIBOIL*/
intabs( signed char );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_SHORT:
#ifdef HAVE_LIBOIL
oil_abs_u16_s16( (uint16_t *) out, sizeof( uint16_t ),
(int16_t *) in, sizeof( int16_t ), sz );
#else /*!HAVE_LIBOIL*/
intabs( signed short );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_INT:
#ifdef HAVE_LIBOIL
oil_abs_u32_s32( (uint32_t *) out, sizeof( uint32_t ),
(int32_t *) in, sizeof( int32_t ), sz );
#else /*!HAVE_LIBOIL*/
intabs( signed int );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_FLOAT:
#ifdef HAVE_LIBOIL
oil_abs_f32_f32( (float *) out, sizeof( float ),
(float *) in, sizeof( float ), sz );
#else /*!HAVE_LIBOIL*/
floatabs( float );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE:
#ifdef HAVE_LIBOIL
oil_abs_f64_f64( (double *) out, sizeof( double ),
(double *) in, sizeof( double ), sz );
#else /*!HAVE_LIBOIL*/
floatabs( float );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_COMPLEX: complexabs( float ); break;
case IM_BANDFMT_DPCOMPLEX: complexabs( double ); break;
default:
assert( 0 );
}
}
/**
* im_abs:
* @in: input #IMAGE
* @out: output #IMAGE
*
* This operation finds the absolute value of an image. It does a copy for
* unsigned integer types, negate for negative values in
* signed integer types, <function>fabs(3)</function> for
* float types, and calculate modulus for complex
* types.
*
* See also: im_exp10tra(), im_sign().
*
* Returns: 0 on success, -1 on error
*/
int
im_abs( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_abs", "%s", _( "not uncoded" ) );
return( -1 );
}
/* Is this one of the unsigned types? Degenerate to im_copy() if it
* is.
*/
if( im_isuint( in ) )
return( im_copy( in, out ) );
/* Prepare output header. Output type == input type, except for
* complex.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_CHAR:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_INT:
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
/* No action.
*/
break;
case IM_BANDFMT_COMPLEX:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_DPCOMPLEX:
out->Bbits = IM_BBITS_DOUBLE;
out->BandFmt = IM_BANDFMT_DOUBLE;
break;
default:
im_error( "im_abs", "%s", _( "unknown input type" ) );
return( -1 );
}
/* Generate!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) abs_gen, in, NULL ) )
return( -1 );
return( 0 );
}

381
libvips/arithmetic/im_add.c Normal file
View File

@ -0,0 +1,381 @@
/* im_add.c
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 29/4/93 J.Cupitt
* - now works for partial images
* 1/7/93 JC
* - adapted for partial v2
* 9/5/95 JC
* - simplified: now just handles 10 cases (instead of 50), using
* im_clip2*() to help
* - now uses im_wrapmany() rather than im_generate()
* 31/5/96 JC
* - SWAP() removed, *p++ removed
* 27/9/04
* - im__cast_and_call() now matches bands as well
* - ... so 1 band + 4 band image -> 4 band image
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Complex add.
*/
#define cloop(TYPE) { \
TYPE *p1 = (TYPE *) in[0]; \
TYPE *p2 = (TYPE *) in[1]; \
TYPE *q = (TYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
double rp1 = p1[0]; \
double ip1 = p1[1]; \
\
double rp2 = p2[0]; \
double ip2 = p2[1]; \
\
p1 += 2; \
p2 += 2; \
\
q[0] = rp1 + rp2; \
q[1] = ip1 + ip2; \
\
q += 2; \
} \
}
/* Real add.
*/
#define rloop(IN, OUT) { \
IN *p1 = (IN *) in[0]; \
IN *p2 = (IN *) in[1]; \
OUT *q = (OUT *) out; \
\
for( x = 0; x < sz; x++ ) \
q[x] = p1[x] + p2[x]; \
}
static void
add_buffer( PEL **in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Add all input types. Kep types here in sync with bandfmt_add[] below.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: rloop( unsigned char, unsigned short ); break;
case IM_BANDFMT_CHAR: rloop( signed char, signed short ); break;
case IM_BANDFMT_USHORT: rloop( unsigned short, unsigned int ); break;
case IM_BANDFMT_SHORT: rloop( signed short, signed int ); break;
case IM_BANDFMT_UINT: rloop( unsigned int, unsigned int ); break;
case IM_BANDFMT_INT: rloop( signed int, signed int ); break;
case IM_BANDFMT_FLOAT:
#ifdef HAVE_LIBOIL
oil_add_f32( (float *) out,
(float *) in[0], (float *) in[1], sz );
#else /*!HAVE_LIBOIL*/
rloop( float, float );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: rloop( double, double ); break;
case IM_BANDFMT_COMPLEX:cloop( float ); break;
case IM_BANDFMT_DPCOMPLEX:cloop( double ); break;
default:
assert( 0 );
}
}
/* Save a bit of typing.
*/
#define UC IM_BANDFMT_UCHAR
#define C IM_BANDFMT_CHAR
#define US IM_BANDFMT_USHORT
#define S IM_BANDFMT_SHORT
#define UI IM_BANDFMT_UINT
#define I IM_BANDFMT_INT
#define F IM_BANDFMT_FLOAT
#define M IM_BANDFMT_COMPLEX
#define D IM_BANDFMT_DOUBLE
#define DM IM_BANDFMT_DPCOMPLEX
/* For two integer types, the "largest", ie. one which can represent the
* full range of both.
*/
static int bandfmt_largest[6][6] = {
/* UC C US S UI I */
/* UC */ { UC, S, US, S, UI, I },
/* C */ { S, C, I, S, I, I },
/* US */ { US, I, US, I, UI, I },
/* S */ { S, S, I, S, I, I },
/* UI */ { UI, I, UI, I, UI, I },
/* I */ { I, I, I, I, I, I }
};
/* For two formats, find one which can represent the full range of both.
*/
static VipsBandFmt
im__format_common( IMAGE *in1, IMAGE *in2 )
{
if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) {
/* What kind of complex?
*/
if( in1->BandFmt == IM_BANDFMT_DPCOMPLEX ||
in2->BandFmt == IM_BANDFMT_DPCOMPLEX )
/* Output will be DPCOMPLEX.
*/
return( IM_BANDFMT_DPCOMPLEX );
else
return( IM_BANDFMT_COMPLEX );
}
else if( im_isfloat( in1 ) || im_isfloat( in2 ) ) {
/* What kind of float?
*/
if( in1->BandFmt == IM_BANDFMT_DOUBLE ||
in2->BandFmt == IM_BANDFMT_DOUBLE )
return( IM_BANDFMT_DOUBLE );
else
return( IM_BANDFMT_FLOAT );
}
else
/* Must be int+int -> int.
*/
return( bandfmt_largest[in1->BandFmt][in2->BandFmt] );
}
/* Make an n-band image. Input 1 or n bands.
*/
static int
im__bandup( IMAGE *in, IMAGE *out, int n )
{
IMAGE *bands[256];
int i;
if( in->Bands == n )
return( im_copy( in, out ) );
if( in->Bands != 1 ) {
im_error( "im__bandup", _( "not one band or %d bands" ), n );
return( -1 );
}
if( n > 256 || n < 1 ) {
im_error( "im__bandup", "%s", _( "bad bands" ) );
return( -1 );
}
for( i = 0; i < n; i++ )
bands[i] = in;
return( im_gbandjoin( bands, out, n ) );
}
/* Cast in1 and in2 up to a common type and number of bands, then call the
* function. Also used by subtract, multiply, divide, etc.
*/
int
im__cast_and_call( IMAGE *in1, IMAGE *in2, IMAGE *out,
im_wrapmany_fn fn, void *a )
{
VipsBandFmt fmt;
IMAGE *t[5];
if( im_open_local_array( out, t, 4, "type cast:1", "p" ) )
return( -1 );
/* Cast our input images up to a common type.
*/
fmt = im__format_common( in1, in2 );
if( im_clip2fmt( in1, t[0], fmt ) ||
im_clip2fmt( in2, t[1], fmt ) )
return( -1 );
/* Force bands up to the same as out.
*/
if( im__bandup( t[0], t[2], out->Bands ) ||
im__bandup( t[1], t[3], out->Bands ) )
return( -1 );
/* And process!
*/
t[4] = NULL;
if( im_wrapmany( t + 2, out, fn, out, a ) )
return( -1 );
return( 0 );
}
/* Type promotion for addition. Sign and value preserving. Make sure these
* match the case statement in add_buffer() above.
*/
static int bandfmt_add[10] = {
/* UC C US S UI I F M D DM */
US, S, UI, I, UI, I, F, M, D, DM
};
/**
* im_add:
* @in1: input image 1
* @in2: input image 2
* @out: output image
*
* This operation adds corresponding pixels in images @in1 and
* @in2 and writes the result to the image descriptor @out. The images must be
* the same size, but may have any type. If one of the images has a single
* band, it is added to every band of the other image.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>), then the
* following table is used to determine the output type:
*
* <table>
* <title>im_add() type promotion</title>
* <tgroup cols='2' align='left' colsep='1' rowsep='1'>
* <thead>
* <row>
* <entry>input type</entry>
* <entry>output type</entry>
* </row>
* </thead>
* <tbody>
* <row>
* <entry>uchar</entry>
* <entry>ushort</entry>
* </row>
* <row>
* <entry>char</entry>
* <entry>short</entry>
* </row>
* <row>
* <entry>ushort</entry>
* <entry>uint</entry>
* </row>
* <row>
* <entry>short</entry>
* <entry>int</entry>
* </row>
* <row>
* <entry>uint</entry>
* <entry>uint</entry>
* </row>
* <row>
* <entry>int</entry>
* <entry>int</entry>
* </row>
* <row>
* <entry>float</entry>
* <entry>float</entry>
* </row>
* <row>
* <entry>double</entry>
* <entry>double</entry>
* </row>
* <row>
* <entry>complex</entry>
* <entry>complex</entry>
* </row>
* <row>
* <entry>double complex</entry>
* <entry>double complex</entry>
* </row>
* </tbody>
* </tgroup>
* </table>
*
* In other words, the output type is just large enough to hold the whole
* range of possible values.
*
* See also: im_subtract(), im_lintra().
*
* Returns: 0 on success, -1 on error
*/
int
im_add( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
/* Basic checks.
*/
if( im_piocheck( in1, out ) || im_pincheck( in2 ) )
return( -1 );
if( in1->Bands != in2->Bands &&
(in1->Bands != 1 && in2->Bands != 1) ) {
im_error( "im_add", "%s", _( "not same number of bands" ) );
return( -1 );
}
if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) {
im_error( "im_add", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_cp_descv( out, in1, in2, NULL ) )
return( -1 );
/* What number of bands will we write?
*/
out->Bands = IM_MAX( in1->Bands, in2->Bands );
/* What output type will we write? int, float or complex.
*/
out->BandFmt = bandfmt_add[im__format_common( in1, in2 )];
out->Bbits = im_bits_of_fmt( out->BandFmt );
/* And process!
*/
if( im__cast_and_call( in1, in2, out,
(im_wrapmany_fn) add_buffer, NULL ) )
return( -1 );
/* Success!
*/
return( 0 );
}

207
libvips/arithmetic/im_avg.c Normal file
View File

@ -0,0 +1,207 @@
/* @(#) Find the average of an image. Takes any non-complex image format,
* @(#) returns a double. Finds the average of all bands.
* @(#)
* @(#) int
* @(#) im_avg( im, out )
* @(#) IMAGE *im;
* @(#) double *out;
* @(#)
* @(#) Returns 0 on success and -1 on error.
*
* Copyright: 1990, J. Cupitt
*
* Author: J. Cupitt
* Written on: 02/08/1990
* Modified on:
* 5/5/93 JC
* - now does partial images
* - less likely to overflow
* 1/7/93 JC
* - adapted for partial v2
* - ANSI C
* 21/2/95 JC
* - modernised again
* 11/5/95 JC
* - oops! return( NULL ) in im_avg(), instead of return( -1 )
* 20/6/95 JC
* - now returns double
* 13/1/05
* - use 64 bit arithmetic
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Start function: allocate space for a double in which we can accululate the
* sum.
*/
static void *
start_fn( IMAGE *out, void *a, void *b )
{
double *tmp;
if( !(tmp = IM_ARRAY( out, 1, double )) )
return( NULL );
*tmp = 0.0;
return( (void *) tmp );
}
/* Stop function. Add this little sum to the main sum.
*/
static int
stop_fn( void *seq, void *a, void *b )
{
double *tmp = (double *) seq;
double *sum = (double *) a;
*sum += *tmp;
return( 0 );
}
/* Loop over region, accumulating a sum in *tmp.
*/
static int
scan_fn( REGION *reg, void *seq, void *a, void *b )
{
double *tmp = (double *) seq;
Rect *r = &reg->valid;
IMAGE *im = reg->im;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int sz = IM_REGION_N_ELEMENTS( reg );
double sum = 0.0;
int x, y;
/* Sum pels in this section.
*/
#define loop(TYPE) \
{ TYPE *p;\
\
for( y = to; y < bo; y++ ) { \
p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < sz; x++ ) \
sum += *p++;\
}\
}
/* Now generate code for all types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop(unsigned char); break;
case IM_BANDFMT_CHAR: loop(signed char); break;
case IM_BANDFMT_USHORT: loop(unsigned short); break;
case IM_BANDFMT_SHORT: loop(signed short); break;
case IM_BANDFMT_UINT: loop(unsigned int); break;
case IM_BANDFMT_INT: loop(signed int); break;
case IM_BANDFMT_FLOAT: loop(float); break;
case IM_BANDFMT_DOUBLE:
#ifdef HAVE_LIBOIL
for( y = to; y < bo; y++ ) {
double *p = (double *) IM_REGION_ADDR( reg, le, y );
double t;
oil_sum_f64( &t, p, sizeof( double ), sz );
sum += t;
}
#else /*!HAVE_LIBOIL*/
loop(double);
#endif /*HAVE_LIBOIL*/
break;
default:
assert( 0 );
}
/* Add to sum for this sequence.
*/
*tmp += sum;
return( 0 );
}
/* Find the average of an image.
*/
int
im_avg( IMAGE *in, double *out )
{
double sum = 0.0;
gint64 vals, pels;
/* Check our args.
*/
if( im_pincheck( in ) )
return( -1 );
if( im_iscomplex( in ) ) {
im_error( "im_avg", "%s", _( "bad input type" ) );
return( -1 );
}
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_avg", "%s", _( "not uncoded" ) );
return( -1 );
}
/* Loop over input, summing pixels.
*/
if( im_iterate( in, start_fn, scan_fn, stop_fn, &sum, NULL ) )
return( -1 );
/* Calculate and return average.
*/
pels = (gint64) in->Xsize * in->Ysize;
vals = pels * in->Bands;
*out = sum / vals;
return( 0 );
}

View File

@ -0,0 +1,161 @@
/* @(#) Average the bands in an image.
* @(#)
* @(#) int
* @(#) im_bandmean(in, out)
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
*
* Author: Simon Goodall
* Written on: 17/7/07
* 17/7/07 JC
* - hacked about a bit
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Int types. Round, keep sum in a larger variable.
*/
#define ILOOP( TYPE, STYPE ) { \
TYPE *p1 = (TYPE *) p; \
TYPE *q1 = (TYPE *) q; \
\
for( i = 0; i < n; i++ ) { \
STYPE sum; \
\
sum = 0; \
for( j = 0; j < b; j++ ) \
sum += p1[j]; \
*q1++ = sum > 0 ? (sum + b / 2) / b : (sum - b / 2) / b; \
p1 += b; \
} \
}
/* Float loop. No rounding, sum in same container.
*/
#define FLOOP( TYPE ) { \
TYPE *p1 = (TYPE *) p; \
TYPE *q1 = (TYPE *) q; \
\
for( i = 0; i < n; i++ ) { \
TYPE sum; \
\
sum = 0; \
for( j = 0; j < b; j++ ) \
sum += p1[j]; \
*q1++ = sum / b; \
p1 += b; \
} \
}
/* Complex loop. Mean reals and imaginaries separately.
*/
#define CLOOP( TYPE ) { \
TYPE *p1 = (TYPE *) p; \
TYPE *q1 = (TYPE *) q; \
\
for( i = 0; i < n * 2; i += 2 ) { \
TYPE sum; \
\
sum = 0; \
for( j = 0; j < b; j++ ) \
sum += p1[j * 2]; \
q1[0] = sum / b; \
sum = 0; \
for( j = 0; j < b; j++ ) \
sum += p1[j * 2 + 1]; \
q1[1] = sum / b; \
p1 += b; \
q1 += 2; \
} \
}
static void
bandmean_buffer( PEL *p, PEL *q, int n, IMAGE *in )
{
int i, j;
const int b = in->Bands;
switch( in->BandFmt ) {
case IM_BANDFMT_CHAR: ILOOP( signed char, int ); break;
case IM_BANDFMT_UCHAR: ILOOP( unsigned char, unsigned int ); break;
case IM_BANDFMT_SHORT: ILOOP( signed short, int ); break;
case IM_BANDFMT_USHORT: ILOOP( unsigned short, unsigned int ); break;
case IM_BANDFMT_INT: ILOOP( signed int, int ); break;
case IM_BANDFMT_UINT: ILOOP( unsigned int, unsigned int ); break;
case IM_BANDFMT_FLOAT: FLOOP( float ); break;
case IM_BANDFMT_DOUBLE: FLOOP( double ); break;
case IM_BANDFMT_COMPLEX: CLOOP( float ); break;
case IM_BANDFMT_DPCOMPLEX: CLOOP( double ); break;
default:
assert( 0 );
}
}
int
im_bandmean( IMAGE *in, IMAGE *out )
{
/* Check input params
*/
if( in->Bands == 1 )
return( im_copy( in, out ) );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_bandmean", "%s", _( "uncoded multiband only" ) );
return( -1 );
}
/* Prepare output image.
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Bands = 1;
out->Type = IM_TYPE_B_W;
/* And process!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) bandmean_buffer, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,114 @@
/* @(#) ceil() an image ... no promotion, so output type == input type
* @(#)
* @(#) int
* @(#) im_ceil( in, out )
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* 20/6/02 JC
* - adapted from im_abs()
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
#define ceil_loop(TYPE)\
{\
TYPE *p = (TYPE *) in;\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = ceil( p[x] );\
}
/* Ceil a buffer of PELs.
*/
static void
ceil_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
switch( im->BandFmt ) {
case IM_BANDFMT_FLOAT: ceil_loop(float); break;
case IM_BANDFMT_DOUBLE: ceil_loop(double); break;
case IM_BANDFMT_COMPLEX: sz *= 2; ceil_loop(float); break;
case IM_BANDFMT_DPCOMPLEX: sz *= 2; ceil_loop(double); break;
default:
assert( 0 );
}
}
/* Ceil of image.
*/
int
im_ceil( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_ceil", "%s", _( "not uncoded" ) );
return( -1 );
}
/* Is this one of the int types? Degenerate to im_copy() if it
* is.
*/
if( im_isint( in ) )
return( im_copy( in, out ) );
/* Output type == input type.
*/
if( im_cp_desc( out, in ) )
return( -1 );
/* Generate!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) ceil_gen, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,75 @@
/* @(#) Multiplies two complex images. complex output is normalised to 1
* @(#) Inputs can be complex double or complex float
* @(#) Result (double complex or float complex) depends on inputs
* @(#) Function im_cmulnorm() assumes that the both input files
* @(#) are either memory mapped or in a buffer.
* @(#) Images must have the same no of bands and must be complex
* @(#) No check for overflow is carried out.
* @(#)
* @(#) int im_cmulnorm(in1, in2, out)
* @(#) IMAGE *in1, *in2, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 15/4/97 JC
* - thrown away and redone in terms of im_multiply()
* 9/7/02 JC
* - im_sign() broken out, done in terms of that
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <vips/vips.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
int
im_cmulnorm( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
IMAGE *t1 = im_open_local( out, "im_cmulnorm:1", "p" );
if( !t1 || im_multiply( in1, in2, t1 ) || im_sign( t1, out ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,239 @@
/* @(#) Find cos of any non-complex image. Output is always float for integer
* @(#) input and double for double input. All angles in degrees.
* @(#)
* @(#) int
* @(#) im_costra( in, out )
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris, based on im_powtra()
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 5/5/93 JC
* - adapted from im_lintra to work with partial images
* - incorrect implementation of complex logs removed
* 1/7/93 JC
* - adapted for partial v2
* - ANSIfied
* 24/2/95 JC
* - im_logtra() adapted to make im_costra()
* - adapted for im_wrapone()
* 26/1/96 JC
* - im_acostra() added
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Define what we do for each band element type. Non-complex input, any
* output.
*/
#define loop( IN, OUT )\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = cos( IM_RAD( (double) p[x] ) );\
}
/* cos a buffer of PELs.
*/
static void
costra_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Switch for all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop( unsigned char, float ); break;
case IM_BANDFMT_CHAR: loop( signed char, float ); break;
case IM_BANDFMT_USHORT: loop( unsigned short, float ); break;
case IM_BANDFMT_SHORT: loop( signed short, float ); break;
case IM_BANDFMT_UINT: loop( unsigned int, float ); break;
case IM_BANDFMT_INT: loop( signed int, float ); break;
case IM_BANDFMT_FLOAT: loop( float, float ); break;
case IM_BANDFMT_DOUBLE: loop( double, double ); break;
default:
assert( 0 );
}
}
/* Cos transform.
*/
int
im_costra( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_costra", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_costra", "%s", _( "bad input type" ) );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
break;
default:
assert( 0 );
}
/* Generate!
*/
if( im_wrapone( in, out, (im_wrapone_fn) costra_gen, in, NULL ) )
return( -1 );
return( 0 );
}
/* And acos().
*/
#define aloop( IN, OUT )\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = IM_DEG( acos( (double) p[x] ) );\
}
/* acos a buffer of PELs.
*/
static void
acostra_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Switch for all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: aloop( unsigned char, float ); break;
case IM_BANDFMT_CHAR: aloop( signed char, float ); break;
case IM_BANDFMT_USHORT: aloop( unsigned short, float ); break;
case IM_BANDFMT_SHORT: aloop( signed short, float ); break;
case IM_BANDFMT_UINT: aloop( unsigned int, float ); break;
case IM_BANDFMT_INT: aloop( signed int, float ); break;
case IM_BANDFMT_FLOAT: aloop( float, float ); break;
case IM_BANDFMT_DOUBLE: aloop( double, double ); break;
default:
assert( 0 );
}
}
/* Acos transform.
*/
int
im_acostra( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_acostra", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_acostra", "%s", _( "bad input type" ) );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
break;
default:
assert( 0 );
}
/* Generate!
*/
if( im_wrapone( in, out, (im_wrapone_fn) acostra_gen, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,158 @@
/* @(#) Find the phase of the cross power spectrum of two complex images,
* @(#) expressed as a complex image where the modulus of each pixel is
* @(#) one.
* @(#)
* @(#) I.E. find (a.b*)/|a.b*| where
* @(#) . represents complex multiplication
* @(#) * represents the complex conjugate
* @(#) || represents the complex modulus
* @(#)
* @(#) int im_cross_phase( IMAGE *a, IMAGE *b, IMAGE *out );
* @(#)
* @(#) All functions return 0 on success and -1 on error
* @(#)
*
* Copyright: 2008, Nottingham Trent University
*
* Author: Tom Vajzovic
* Written on: 2008-01-09
*
* 2008-02-04 tcv:
* - exp( i.th ) == cos(th)+i.sin(th) NOT sin(th)+i.cos(th)
* - add quadratic version (ifdef'd out ATM - still using trigonometric one)
*
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* There doesn't seem to be much difference in speed between these two methods (on an Athlon64),
* so I use the modulus argument version, since atan2() is in c89 but hypot() is c99.
*
* If you think that it might be faster on your platform, uncomment the following:
*/
#define USE_MODARG_DIV
#ifdef USE_MODARG_DIV
#define COMPLEX_PHASE_FN( TYPE, ABS ) \
static void \
complex_phase_ ## TYPE ( void *in1, void *in2, void *out, int n, void *im, void *unrequired ){ \
\
TYPE *X= (TYPE*) in1; \
TYPE *Y= (TYPE*) in2; \
TYPE *Z= (TYPE*) out; \
TYPE *Z_stop= Z + 2 * n * ((IMAGE*)im)-> Bands; \
\
for( ; Z < Z_stop; X+= 2, Y+= 2 ){ \
double arg= atan2( X[1], X[0] ) - atan2( Y[1], Y[0] ); \
*Z++= cos( arg ); \
*Z++= sin( arg ); \
} \
}
#else /* USE_MODARG_DIV */
#define COMPLEX_PHASE_FN( TYPE, ABS ) \
static void \
complex_phase_ ## TYPE ( void *in1, void *in2, void *out, int n, void *im, void *unrequired ){ \
\
TYPE *X= (TYPE*) in1; \
TYPE *Y= (TYPE*) in2; \
TYPE *Z= (TYPE*) out; \
TYPE *Z_stop= Z + 2 * n * ((IMAGE*)im)-> Bands; \
\
for( ; Z < Z_stop; X+= 2, Y+= 2 ) \
\
if( ABS( Y[0] ) > ABS( Y[1] )){ \
double a= Y[1] / Y[0]; \
double b= Y[0] + Y[1] * a; \
double re= ( X[0] + X[1] * a ) / b; \
double im= ( X[1] - X[0] * a ) / b; \
double mod= im__hypot( re, im ); \
*Z++= re / mod; \
*Z++= im / mod; \
} \
else { \
double a= Y[0] / Y[1]; \
double b= Y[1] + Y[0] * a; \
double re= ( X[0] * a + X[1] ) / b; \
double im= ( X[1] * a - X[0] ) / b; \
double mod= im__hypot( re, im ); \
*Z++= re / mod; \
*Z++= im / mod; \
} \
}
#endif /* USE_MODARG_DIV */
COMPLEX_PHASE_FN( float, fabsf )
COMPLEX_PHASE_FN( double, fabs )
int im_cross_phase( IMAGE *a, IMAGE *b, IMAGE *out ){
#define FUNCTION_NAME "im_phase"
if( im_pincheck( a ) || im_pincheck( b ) || im_poutcheck( out ))
return -1;
if( a-> Xsize != b-> Xsize || a-> Ysize != b-> Ysize ){
im_error( FUNCTION_NAME, "not same size" );
return -1;
}
if( a-> Bands != b-> Bands ){
im_error( FUNCTION_NAME, "numbers of bands differ" );
return -1;
}
if( a-> Coding || b-> Coding ){
im_error( FUNCTION_NAME, "not uncoded" );
return -1;
}
if( a-> BandFmt != b-> BandFmt ){
im_error( FUNCTION_NAME, "formats differ" );
return -1;
}
if( IM_BANDFMT_COMPLEX != a-> BandFmt && IM_BANDFMT_DPCOMPLEX != a-> BandFmt ){
im_error( FUNCTION_NAME, "not complex format" );
return -1;
}
return im_cp_descv( out, a, b, NULL ) || im_wraptwo( a, b, out,
IM_BANDFMT_COMPLEX == a-> BandFmt ? complex_phase_float : complex_phase_double, a, NULL );
}

View File

@ -0,0 +1,226 @@
/* @(#) Find the standard deviation of an image. Takes any non-complex image
* @(#) format, returns a double. Finds the deviation of all bands.
* @(#)
* @(#) int
* @(#) im_deviate( im, out )
* @(#) IMAGE *im;
* @(#) double *out;
* @(#)
* @(#) Returns 0 on success and -1 on error.
*
* Copyright: 1990, J. Cupitt
*
* Author: J. Cupitt
* Written on: 02/08/1990
* Modified on:
* 5/5/93 JC
* - now does partial images
* - less likely to overflow
* - adapted from im_avg
* 1/7/93 JC
* - adapted for partial v2
* - ANSIfied
* 21/2/95 JC
* - modernised again
* 11/5/95 JC
* - oops! return( NULL ) in im_avg(), instead of return( -1 )
* 20/6/95 JC
* - now returns double, not float
* 13/1/05
* - use 64 bit arithmetic
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Start function: allocate space for a pair of doubles in which we can
* accumulate the sum and the sum of squares.
*/
static void *
start_fn( IMAGE *out, void *a, void *b )
{
double *tmp;
if( !(tmp = IM_ARRAY( out, 2, double )) )
return( NULL );
tmp[0] = 0.0;
tmp[1] = 0.0;
return( (void *) tmp );
}
/* Stop function. Add this little sum to the main sum.
*/
static int
stop_fn( void *seq, void *a, void *b )
{
double *tmp = (double *) seq;
double *sum = (double *) a;
sum[0] += tmp[0];
sum[1] += tmp[1];
return( 0 );
}
/* Loop over region, adding information to the appropriate fields of tmp.
*/
static int
scan_fn( REGION *reg, void *seq, void *a, void *b )
{
double *tmp = (double *) seq;
Rect *r = &reg->valid;
IMAGE *im = reg->im;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int sz = IM_REGION_N_ELEMENTS( reg );
double s = 0.0;
double s2 = 0.0;
int x, y;
/* Sum pels in this section.
*/
#define loop(TYPE) \
{ TYPE *p; \
\
for( y = to; y < bo; y++ ) { \
p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < sz; x++ ) { \
TYPE v = p[x]; \
\
s += v; \
s2 += (double) v * (double) v; \
}\
}\
}
/* Now generate code for all types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop(unsigned char); break;
case IM_BANDFMT_CHAR: loop(signed char); break;
case IM_BANDFMT_USHORT: loop(unsigned short); break;
case IM_BANDFMT_SHORT: loop(signed short); break;
case IM_BANDFMT_UINT: loop(unsigned int); break;
case IM_BANDFMT_INT: loop(signed int); break;
case IM_BANDFMT_FLOAT: loop(float); break;
case IM_BANDFMT_DOUBLE:
#ifdef HAVE_LIBOIL
for( y = to; y < bo; y++ ) {
double *p = (double *) IM_REGION_ADDR( reg, le, y );
double t;
double t2;
oil_sum_f64( &t, p, sizeof( double ), sz );
oil_squaresum_f64( &t2, p, sz );
s += t;
s2 += t2;
}
#else /*!HAVE_LIBOIL*/
loop(double);
#endif /*HAVE_LIBOIL*/
break;
default:
assert( 0 );
}
/* Add to sum for this sequence.
*/
tmp[0] += s;
tmp[1] += s2;
return( 0 );
}
/* Find the average of an image.
*/
int
im_deviate( IMAGE *in, double *out )
{
double sum[2] = { 0.0, 0.0 };
gint64 N;
/* Check our args.
*/
if( im_pincheck( in ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_deviate", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_deviate", "%s", _( "bad input type" ) );
return( -1 );
}
/* Loop over input, summing pixels.
*/
if( im_iterate( in, start_fn, scan_fn, stop_fn, &sum, NULL ) )
return( -1 );
/*
NOTE: NR suggests a two-pass algorithm to minimise roundoff.
But that's too expensive for us :-( so do it the old one-pass
way.
*/
/* Calculate and return deviation. Add a fabs to stop sqrt(<=0).
*/
N = (gint64) in->Xsize * in->Ysize * in->Bands;
*out = sqrt( fabs( sum[1] - (sum[0] * sum[0] / N) ) / (N - 1) );
return( 0 );
}

View File

@ -0,0 +1,234 @@
/* @(#) Divide two images
* @(#) Images must have the same no of bands and can be of any type
* @(#) No check for overflow is carried out.
* @(#)
* @(#) int
* @(#) im_divide(in1, in2, out)
* @(#) IMAGE *in1, *in2, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 29/4/93 JC
* - now works for partial images
* 1/7/93 JC
* - adapted for partial v2
* - ANSIfied
* 19/10/93 JC
* - coredump-inducing bug in complex*complex fixed
* 13/12/93
* - char*short bug fixed
* 12/6/95 JC
* - new im_multiply adapted to make new im_divide
* 27/9/04
* - updated for 1 band $op n band image -> n band image case
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Complex divide.
*/
#ifdef USE_MODARG_DIV
/* This is going to be much slower */
#define cloop(TYPE) \
{ \
TYPE *X= (TYPE*) in[0]; \
TYPE *Y= (TYPE*) in[1]; \
TYPE *Z= (TYPE*) out; \
TYPE *Z_stop= Z + sz * 2; \
\
for( ; Z < Z_stop; X+= 2, Y+=2 ){ \
double arg= atan2( X[1], X[0] ) - atan2( Y[1], Y[0] ); \
double mod= hypot( X[1], X[0] ) / hypot( Y[1], Y[0] ); \
*Z++= mod * cos( arg ); \
*Z++= mod * sin( arg ); \
} \
}
#else /* USE_MODARG_DIV */
#define cloop(TYPE) \
{ \
TYPE *X= (TYPE*) in[0]; \
TYPE *Y= (TYPE*) in[1]; \
TYPE *Z= (TYPE*) out; \
TYPE *Z_stop= Z + sz * 2; \
\
for( ; Z < Z_stop; X+= 2, Y+=2 ) \
if( fabs( Y[0] ) > fabs( Y[1] )){ \
double a= Y[1] / Y[0]; \
double b= Y[0] + Y[1] * a; \
*Z++= ( X[0] + X[1] * a ) / b; \
*Z++= ( X[1] - X[0] * a ) / b; \
} \
else { \
double a= Y[0] / Y[1]; \
double b= Y[1] + Y[0] * a; \
*Z++= ( X[0] * a + X[1] ) / b; \
*Z++= ( X[1] * a - X[0] ) / b; \
} \
}
#endif /* USE_MODARG_DIV */
/* Real divide.
*/
#define rloop(TYPE) \
{\
TYPE *p1 = (TYPE *) in[0];\
TYPE *p2 = (TYPE *) in[1];\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = p1[x] / p2[x];\
}
static void
divide_buffer( PEL **in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Divide all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR: rloop( signed char ); break;
case IM_BANDFMT_UCHAR: rloop( unsigned char ); break;
case IM_BANDFMT_SHORT: rloop( signed short ); break;
case IM_BANDFMT_USHORT: rloop( unsigned short ); break;
case IM_BANDFMT_INT: rloop( signed int ); break;
case IM_BANDFMT_UINT: rloop( unsigned int ); break;
case IM_BANDFMT_FLOAT:
#ifdef HAVE_LIBOIL
oil_divide_f32( (float *) out,
(float *) in[0], (float *) in[1], sz );
#else /*!HAVE_LIBOIL*/
rloop( float );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: rloop( double ); break;
case IM_BANDFMT_COMPLEX: cloop( float ); break;
case IM_BANDFMT_DPCOMPLEX: cloop( double ); break;
default:
assert( 0 );
}
}
int
im_divide( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
/* Basic checks.
*/
if( im_piocheck( in1, out ) || im_pincheck( in2 ) )
return( -1 );
if( in1->Bands != in2->Bands &&
(in1->Bands != 1 && in2->Bands != 1) ) {
im_error( "im_divide", "%s", _( "not same number of bands" ) );
return( -1 );
}
if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) {
im_error( "im_divide", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_cp_descv( out, in1, in2, NULL ) )
return( -1 );
/* What number of bands will we write?
*/
out->Bands = IM_MAX( in1->Bands, in2->Bands );
/* What output type will we write? float, double or complex.
*/
if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) {
/* What kind of complex?
*/
if( in1->BandFmt == IM_BANDFMT_DPCOMPLEX ||
in2->BandFmt == IM_BANDFMT_DPCOMPLEX )
/* Output will be DPCOMPLEX.
*/
out->BandFmt = IM_BANDFMT_DPCOMPLEX;
else
out->BandFmt = IM_BANDFMT_COMPLEX;
}
else if( im_isfloat( in1 ) || im_isfloat( in2 ) ) {
/* What kind of float?
*/
if( in1->BandFmt == IM_BANDFMT_DOUBLE ||
in2->BandFmt == IM_BANDFMT_DOUBLE )
out->BandFmt = IM_BANDFMT_DOUBLE;
else
out->BandFmt = IM_BANDFMT_FLOAT;
}
else {
/* An int type -- output must be just float.
*/
out->BandFmt = IM_BANDFMT_FLOAT;
}
/* And process!
*/
if( im__cast_and_call( in1, in2, out,
(im_wrapmany_fn) divide_buffer, NULL ) )
return( -1 );
/* Success!
*/
return( 0 );
}

View File

@ -0,0 +1,249 @@
/* @(#) Calculates n^pel, with n as a parameter.
* @(#) If input is up to float, output is float, else input is the same as
* @(#) output. Does not work for complex input.
* @(#)
* @(#) int
* @(#) im_expntra( in, out, e )
* @(#) IMAGE *in, *out;
* @(#) double e;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 10/12/93 JC
* - now reports total number of x/0, rather than each one.
* 1/2/95 JC
* - rewritten for PIO with im_wrapone()
* - incorrect complex code removed
* - /0 reporting removed for ease of programming
* 8/5/95 JC
* - im_expntra() adapted to make this
* 15/4/97 JC
* - oops, return(0) missing
* - M_E removed, as not everywhere
* 6/7/98 JC
* - _vec version added
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Parameters saved here.
*/
typedef struct {
int n; /* Number of bands of constants */
double *e; /* Exponent values, one per band */
} ExpntraInfo;
/* Define what we do for each band element type. Single constant.
*/
#define loop1(IN, OUT)\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < sz; x++ ) {\
double f = (double) p[x];\
\
if( e == 0.0 && f < 0.0 ) {\
/* Division by zero! Difficult to report tho'\
*/\
q[x] = 0.0;\
}\
else\
q[x] = pow( e, f );\
}\
}
/* Expntra a buffer.
*/
static int
expntra1_gen( PEL *in, PEL *out, int width, IMAGE *im, ExpntraInfo *inf )
{
int sz = width * im->Bands;
double e = inf->e[0];
int x;
/* Expntra all non-complex input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop1(unsigned char, float); break;
case IM_BANDFMT_CHAR: loop1(signed char, float); break;
case IM_BANDFMT_USHORT: loop1(unsigned short, float); break;
case IM_BANDFMT_SHORT: loop1(signed short, float); break;
case IM_BANDFMT_UINT: loop1(unsigned int, float); break;
case IM_BANDFMT_INT: loop1(signed int, float); break;
case IM_BANDFMT_FLOAT: loop1(float, float); break;
case IM_BANDFMT_DOUBLE: loop1(double, double); break;
default:
assert( 0 );
}
return( 0 );
}
/* Define what we do for each band element type. One constant per band.
*/
#define loopn(IN, OUT)\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( i = 0, x = 0; x < width; x++ )\
for( k = 0; k < im->Bands; k++, i++ ) {\
double e = inf->e[k];\
double f = (double) p[i];\
\
if( e == 0.0 && f < 0.0 ) {\
q[i] = 0.0;\
}\
else\
q[i] = pow( e, f );\
}\
}
/* Expntra a buffer.
*/
static int
expntran_gen( PEL *in, PEL *out, int width, IMAGE *im, ExpntraInfo *inf )
{
int x, k, i;
/* Expntra all non-complex input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loopn(unsigned char, float); break;
case IM_BANDFMT_CHAR: loopn(signed char, float); break;
case IM_BANDFMT_USHORT: loopn(unsigned short, float); break;
case IM_BANDFMT_SHORT: loopn(signed short, float); break;
case IM_BANDFMT_UINT: loopn(unsigned int, float); break;
case IM_BANDFMT_INT: loopn(signed int, float); break;
case IM_BANDFMT_FLOAT: loopn(float, float); break;
case IM_BANDFMT_DOUBLE: loopn(double, double); break;
default:
assert( 0 );
}
return( 0 );
}
int
im_expntra_vec( IMAGE *in, IMAGE *out, int n, double *e )
{
ExpntraInfo *inf;
int i;
/* Check args.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_expntra_vec", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_expntra_vec", "%s", _( "not non-complex" ) );
return( -1 );
}
if( n != 1 && n != in->Bands ) {
im_error( "im_expntra_vec",
_( "not 1 or %d elements in vector" ), in->Bands );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
if( im_isint( in ) ) {
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
}
/* Make space for a little buffer.
*/
if( !(inf = IM_NEW( out, ExpntraInfo )) ||
!(inf->e = IM_ARRAY( out, n, double )) )
return( -1 );
for( i = 0; i < n; i++ )
inf->e[i] = e[i];
inf->n = n;
/* Generate!
*/
if( n == 1 ) {
if( im_wrapone( in, out,
(im_wrapone_fn) expntra1_gen, in, inf ) )
return( -1 );
}
else {
if( im_wrapone( in, out,
(im_wrapone_fn) expntran_gen, in, inf ) )
return( -1 );
}
return( 0 );
}
int
im_expntra( IMAGE *in, IMAGE *out, double e )
{
return( im_expntra_vec( in, out, 1, &e ) );
}
/* Define im_exptra() and im_exp10tra() in terms of im_expntra().
*/
int
im_exptra( IMAGE *in, IMAGE *out )
{
return( im_expntra( in, out, 2.7182818284590452354 ) );
}
int
im_exp10tra( IMAGE *in, IMAGE *out )
{
return( im_expntra( in, out, 10.0 ) );
}

View File

@ -0,0 +1,95 @@
/* @(#) Optimised 4 frame average
Copyright (C) 1992, Kirk Martinez, History of Art Dept, Birkbeck College
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
#define ARGS "fav4: frame average 4 frames\nARGS: im1 im2 im3 im4 outfile"
#define NFRAMES 4
/* @(#) Optimised 4 frame average
Copyright (C) 1992, Kirk Martinez, History of Art Dept, Birkbeck College
CHAR images only!
ARGS: array of 4 source images and output image
*/
int
im_fav4( IMAGE **in, IMAGE *out)
{
PEL *result, *buffer, *p1, *p2, *p3, *p4;
int x,y;
int linebytes, PICY;
/* check IMAGEs parameters
*/
if(im_iocheck(in[1], out)) return(-1);
/* BYTE images only!
*/
if( (in[0]->BandFmt != IM_BANDFMT_CHAR) && (in[0]->BandFmt != IM_BANDFMT_UCHAR)) return(-1);
if ( im_cp_desc(out, in[1]) == -1) /* copy image descriptors */
return(-1);
if ( im_setupout(out) == -1)
return(-1);
linebytes = in[0]->Xsize * in[0]->Bands;
PICY = in[0]->Ysize;
buffer = (PEL*)im_malloc(NULL,linebytes);
memset(buffer, 0, linebytes);
p1 = (PEL*)in[0]->data;
p2 = (PEL*)in[1]->data;
p3 = (PEL*)in[2]->data;
p4 = (PEL*)in[3]->data;
for (y = 0; y < PICY; y++)
{
result = buffer;
/* average 4 pels with rounding, for whole line*/
for (x = 0; x < linebytes; x++) {
*result++ = (PEL)((int)((int)*p1++ + (int)*p2++ + (int)*p3++ + (int)*p4++ +2) >> 2);
}
im_writeline(y,out, buffer);
}
im_free(buffer);
return(0);
}

View File

@ -0,0 +1,128 @@
/* @(#) floor() an image ... no promotion, so output type == input type
* @(#)
* @(#) int
* @(#) im_floor( in, out )
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* 20/6/02 JC
* - adapted from im_abs()
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
#define floor_loop(TYPE)\
{\
TYPE *p = (TYPE *) in;\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = floor( p[x] );\
}
/* Ceil a buffer of PELs.
*/
static void
floor_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
switch( im->BandFmt ) {
case IM_BANDFMT_FLOAT:
#ifdef HAVE_LIBOIL
oil_floor_f32( (float *) out, (float *) in, sz );
#else /*!HAVE_LIBOIL*/
floor_loop(float);
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: floor_loop(double); break;
case IM_BANDFMT_COMPLEX: sz *= 2; floor_loop(float); break;
case IM_BANDFMT_DPCOMPLEX: sz *= 2; floor_loop(double); break;
default:
assert( 0 );
}
}
/* Ceil of image.
*/
int
im_floor( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_floor", "%s", _( "not uncoded" ) );
return( -1 );
}
/* Is this one of the int types? Degenerate to im_copy() if it
* is.
*/
if( im_isint( in ) )
return( im_copy( in, out ) );
/* Output type == input type.
*/
if( im_cp_desc( out, in ) )
return( -1 );
/* Generate!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) floor_gen, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,127 @@
/* @(#) Generalised addition of two vasari images using the routines
* @(#) im_gaddim or im_gfadd
* @(#) Convention to ease the complilation time.
* @(#) Function im_gadd() assumes that the both input files
* @(#) are either memory mapped or in a buffer.
* @(#) Images must have the same no of bands and must not be complex
* @(#) No check for overflow is carried out.
* @(#)
* @(#) int im_gadd(a, in1, b, in2, c, out)
* @(#) IMAGE *in1, *in2, *out;
* @(#) double a, b, c;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
extern int im_gfadd();
extern int im_gaddim();
/* This function works on either mmaped files or on images in buffer
*/
int im_gadd(a, in1, b, in2, c, out)
IMAGE *in1, *in2, *out;
double a, b, c;
{
int flagint = 0;
int flagfloat = 0;
int value = 0;
switch(in1->BandFmt) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
flagint = 1;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
flagfloat = 1;
break;
default: im_error("im_gadd","%s", _("Unable to accept image1"));
return(-1);
}
switch(in2->BandFmt) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
flagint = 1;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
flagfloat = 1;
break;
default: im_error("im_gadd","%s", _("Unable to accept image1"));
return(-1);
}
/* Select output routines */
if (flagfloat == 1)
{
value = im_gfadd(a, in1, b, in2, c, out);
if (value == -1)
return(-1);
}
else if (flagint == 1)
{
value = im_gaddim(a, in1, b, in2, c, out);
if (value == -1)
return(-1);
}
else
assert( 0 );
return(0);
}

View File

@ -0,0 +1,241 @@
/* @(#) Generalised addition of two vasari images.
* @(#)Inputs, outputs are neither float nor double
* @(#) Result at each point is a*in1 + b*in2 + c
* @(#) Result depends on inputs, rounding is carried out;
* @(#) Function im_gaddim() assumes that the both input files
* @(#) are either memory mapped or in a buffer.
* @(#) Images must have the same no of bands and must not be complex
* @(#) No check for overflow is done;
* @(#)
* @(#) int im_gaddim(a, in1, b, in2, c, out)
* @(#) double a, b, c;
* @(#) IMAGE *in1, *in2, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* This function works on either mmaped files or on images in buffer
*/
/* uchar char ushort short uint int */
static int array[6][6] = {
/* uchar */ { 2, 3, 2, 3, 4, 5 },
/* char */ { 3, 3, 3, 3, 5, 5 },
/* ushort */ { 2, 3, 2, 3, 4, 5 },
/* short */ { 3, 3, 3, 3, 5, 5 },
/* uint */ { 4, 5, 4, 5, 4, 5 },
/* int */ { 5, 5, 5, 5, 5, 5 }
};
#define select_tmp2_for_out_int(OUT) \
case IM_BANDFMT_UCHAR: select_tmp1_for_out_int(unsigned char, OUT); break; \
case IM_BANDFMT_CHAR: select_tmp1_for_out_int(signed char, OUT); break; \
case IM_BANDFMT_USHORT: select_tmp1_for_out_int(unsigned short, OUT); break; \
case IM_BANDFMT_SHORT: select_tmp1_for_out_int(signed short, OUT); break; \
case IM_BANDFMT_UINT: select_tmp1_for_out_int(unsigned int, OUT); break; \
case IM_BANDFMT_INT: select_tmp1_for_out_int(signed int, OUT); break; \
\
default: \
im_error("im_gaddim","Wrong tmp2 format(1)"); \
free( line); \
return(-1);
#define select_tmp1_for_out_int(IN2, OUT) \
switch(tmp1->BandFmt) { \
case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break; \
case IM_BANDFMT_INT: loop(int, IN2, OUT); break; \
default: im_error("im_gaddim","Wrong tmp2 format(2)");\
free( line);\
return(-1); \
}
#define select_tmp2_for_out_short(OUT) \
case IM_BANDFMT_UCHAR: select_tmp1_for_out_short(unsigned char, OUT); break; \
case IM_BANDFMT_CHAR: select_tmp1_for_out_short(signed char, OUT); break; \
case IM_BANDFMT_USHORT: select_tmp1_for_out_short(unsigned short, OUT); break; \
case IM_BANDFMT_SHORT: select_tmp1_for_out_short(signed short, OUT); break;
#define select_tmp1_for_out_short(IN2, OUT) \
switch(tmp1->BandFmt) { \
case IM_BANDFMT_UCHAR: loop(unsigned char, IN2, OUT); break; \
case IM_BANDFMT_CHAR: loop(signed char, IN2, OUT); break; \
case IM_BANDFMT_USHORT: loop(unsigned short, IN2, OUT); break; \
case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break; \
default: im_error("im_gaddim","Wrong image1 format(4)");\
free( line);\
return(-1); \
}
int im_gaddim(a, in1, b, in2, c, out)
IMAGE *in1, *in2, *out;
double a, b, c;
{
static int bb[] = { IM_BBITS_BYTE, IM_BBITS_BYTE, IM_BBITS_SHORT,
IM_BBITS_SHORT, IM_BBITS_INT, IM_BBITS_INT };
static int fmt[] = { IM_BANDFMT_UCHAR, IM_BANDFMT_CHAR,
IM_BANDFMT_USHORT, IM_BANDFMT_SHORT,
IM_BANDFMT_UINT, IM_BANDFMT_INT };
int y, x;
int first, second, result;
IMAGE *tmp1, *tmp2;
PEL *line;
int os; /* size of a line of output image */
/* fd, data filename must have been set before the function is called
* Check whether they are set properly */
if ((im_iocheck(in1, out) == -1) || (im_iocheck(in2, out) == -1))
{
return(-1);
}
/* Checks the arguments entered in in and prepares out */
if ( (in1->Xsize != in2->Xsize) || (in1->Ysize != in2->Ysize) ||
(in1->Bands != in2->Bands) || (in1->Coding != in2->Coding) )
{ im_error("im_gaddim"," Input images differ"); return(-1); }
if (in1->Coding != IM_CODING_NONE)
{ im_error("im_gaddim"," images must be uncoded"); return(-1);}
switch(in1->BandFmt) {
case IM_BANDFMT_UCHAR: first = 0; break;
case IM_BANDFMT_CHAR: first = 1; break;
case IM_BANDFMT_USHORT: first = 2; break;
case IM_BANDFMT_SHORT: first = 3; break;
case IM_BANDFMT_UINT: first = 4; break;
case IM_BANDFMT_INT: first = 5; break;
default: im_error("im_gaddim"," Unable to accept image1");
return(-1);
}
switch(in2->BandFmt) {
case IM_BANDFMT_UCHAR: second = 0; break;
case IM_BANDFMT_CHAR: second = 1; break;
case IM_BANDFMT_USHORT: second = 2; break;
case IM_BANDFMT_SHORT: second = 3; break;
case IM_BANDFMT_UINT: second = 4; break;
case IM_BANDFMT_INT: second = 5; break;
default: im_error("im_gaddim"," Unable to accept image2");
return(-1);
}
/* Define the output */
result = array[first][second];
/* Prepare the output header */
if ( im_cp_desc(out, in1) == -1)
{ im_error("im_gaddim"," im_cp_desc failed"); return(-1); }
out->Bbits = bb[result];
out->BandFmt = fmt[result];
if( im_setupout(out) == -1)
{ im_error("im_gaddim"," im_setupout failed"); return(-1); }
/* Order in1 and in2 */
if ( first >= second )
{ tmp1 = in1; tmp2 = in2; }
else
{ tmp1 = in2; tmp2 = in1; }
/* Define what we do for each band element type. */
#define loop(IN1, IN2, OUT) \
{ IN1 *input1 = (IN1 *) tmp1->data; \
IN2 *input2 = (IN2 *) tmp2->data; \
\
for (y=0; y <out->Ysize; y++) {\
OUT *cpline = (OUT*)line; \
for (x=0; x<os; x++)\
*cpline++ = (OUT) \
(a*(*input1++)+b*(*input2++)+c +0.5);\
if (im_writeline(y, out, line) == -1) {\
free( line);\
return ( -1 );\
}\
}\
}
os = out->Xsize * out->Bands;
line = (PEL *) calloc ( (unsigned)os, sizeof(double) );
if (line == NULL)
{
im_error("im_gaddim"," Unable to calloc");
return(-1);
}
switch (out->BandFmt) {
case IM_BANDFMT_INT:
switch (tmp2->BandFmt) {
select_tmp2_for_out_int(int);
}
break;
case IM_BANDFMT_UINT:
switch (tmp2->BandFmt) {
select_tmp2_for_out_int(unsigned int);
}
break;
case IM_BANDFMT_SHORT:
switch (tmp2->BandFmt) {
select_tmp2_for_out_short(short);
}
break;
case IM_BANDFMT_USHORT:
switch (tmp2->BandFmt) {
select_tmp2_for_out_short(unsigned short);
}
break;
default:
im_error("im_gaddim"," Impossible output state");
free( line);
return(-1);
}
free( line);
return(0);
}

View File

@ -0,0 +1,351 @@
/* @(#) Generalised addition of two vasari images. Result (double or float)
* @(#)depends on inputs
* @(#) Function im_gfadd() assumes that the both input files
* @(#) are either memory mapped or in a buffer.
* @(#) Images must have the same no of bands and can be of any type
* @(#) No check for overflow is carried out. If in doubt use im_clip2...
* @(#) Result at eachpoint is a*in1 + b*in2 + c
* @(#)
* @(#) int im_gfadd(a, in1, b, in2, c, out)
* @(#) double a, b, c;
* @(#) IMAGE *in1, *in2, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 15/6/93 J.Cupitt
* - externs removed
* - casts added to please ANSI C
* - includes rationalised
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* uchar char ushort short uint int float double */
static int array[8][8] = {
/* uchar */ { 0, 0, 0, 0, 0, 0, 0, 1 },
/* char */ { 0, 0, 0, 0, 0, 0, 0, 1 },
/* ushort */ { 0, 0, 0, 0, 0, 0, 0, 1 },
/* short */ { 0, 0, 0, 0, 0, 0, 0, 1 },
/* uint */ { 0, 0, 0, 0, 0, 0, 0, 1 },
/* int */ { 0, 0, 0, 0, 0, 0, 0, 1 },
/* float */ { 0, 0, 0, 0, 0, 0, 0, 1 },
/* double */ { 1, 1, 1, 1, 1, 1, 1, 1 }
};
#define select_outdouble(IN2, OUT)\
switch(tmp1->BandFmt) {\
case IM_BANDFMT_DOUBLE: loop(double, IN2, OUT); break;\
default: im_error("im_gfadd","Wrong tmp1 format(d)");\
free( line); return( -1 );\
}
#define outfloat_2uchar(IN2, OUT)\
case IM_BANDFMT_UCHAR: loop(unsigned char, IN2, OUT); break;\
case IM_BANDFMT_CHAR: loop(signed char, IN2, OUT); break;\
case IM_BANDFMT_USHORT: loop(unsigned short, IN2, OUT); break;\
case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break;\
case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
#define outfloat_2char(IN2, OUT)\
case IM_BANDFMT_CHAR: loop(signed char, IN2, OUT); break;\
case IM_BANDFMT_USHORT: loop(unsigned short, IN2, OUT); break;\
case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break;\
case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
#define outfloat_2ushort(IN2, OUT)\
case IM_BANDFMT_USHORT: loop(unsigned short, IN2, OUT); break;\
case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break;\
case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
#define outfloat_2short(IN2, OUT)\
case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break;\
case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
#define outfloat_2uint(IN2, OUT)\
case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
#define outfloat_2int(IN2, OUT)\
case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
#define outfloat_2float(IN2, OUT)\
case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
int im_gfadd(a, in1, b, in2, c, out)
double a, b, c;
IMAGE *in1, *in2, *out;
{
static int bb[] = { IM_BBITS_FLOAT, IM_BBITS_DOUBLE };
static int fmt[] = { IM_BANDFMT_FLOAT, IM_BANDFMT_DOUBLE };
int y, x;
int first, second, result;
IMAGE *tmp1, *tmp2;
PEL *line;
int os; /* size of a line of output image */
/* fd, data filename must have been set before the function is called
* Check whether they are set properly */
if ((im_iocheck(in1, out) == -1) || (im_iocheck(in2, out) == -1))
{ im_error("im_gfadd"," im_iocheck failed"); return( -1 ); }
/* Checks the arguments entered in in and prepares out */
if ( (in1->Xsize != in2->Xsize) || (in1->Ysize != in2->Ysize) ||
(in1->Bands != in2->Bands) || (in1->Coding != in2->Coding) )
{ im_error("im_gfadd"," Input images differ"); return( -1 );}
if (in1->Coding != IM_CODING_NONE)
{ im_error("im_gfadd"," images are coded"); return( -1 ); }
switch(in1->BandFmt) {
case IM_BANDFMT_UCHAR: first = 0; break;
case IM_BANDFMT_CHAR: first = 1; break;
case IM_BANDFMT_USHORT: first = 2; break;
case IM_BANDFMT_SHORT: first = 3; break;
case IM_BANDFMT_UINT: first = 4; break;
case IM_BANDFMT_INT: first = 5; break;
case IM_BANDFMT_FLOAT: first = 6; break;
case IM_BANDFMT_DOUBLE: first = 7; break;
default: im_error("im_gfadd"," unable to accept image1");
return( -1 );
}
switch(in2->BandFmt) {
case IM_BANDFMT_UCHAR: second = 0; break;
case IM_BANDFMT_CHAR: second = 1; break;
case IM_BANDFMT_USHORT: second = 2; break;
case IM_BANDFMT_SHORT: second = 3; break;
case IM_BANDFMT_UINT: second = 4; break;
case IM_BANDFMT_INT: second = 5; break;
case IM_BANDFMT_FLOAT: second = 6; break;
case IM_BANDFMT_DOUBLE: second = 7; break;
default: im_error("im_gfadd"," unable to accept image2");
return( -1 );
}
/* Define the output */
result = array[first][second];
/* Prepare output */
if ( im_cp_desc(out, in1) == -1)
{ im_error("im_gfadd"," im_cp_desc failed"); return( -1 ); }
out->Bbits = bb[result];
out->BandFmt = fmt[result];
if( im_setupout(out) == -1)
{ im_error("im_gfadd"," im_setupout failed"); return( -1 ); }
/* Order in1 and in2 */
if ( first >= second )
{ tmp1 = in1; tmp2 = in2; }
else
{ tmp1 = in2; tmp2 = in1; }
/* Define what we do for each band element type. */
#define loop(IN1, IN2, OUT)\
{ IN1 *input1 = (IN1 *) tmp1->data;\
IN2 *input2 = (IN2 *) tmp2->data;\
\
for (y=0; y <out->Ysize; y++) {\
OUT *cpline = (OUT*)line;\
for (x=0; x<os; x++)\
*cpline++ = (a*((OUT)*input1++) + \
b*((OUT)*input2++) + c);\
if (im_writeline(y, out, line) ) {\
im_error("im_gfadd"," im_writeline failed");\
free( line);\
return( -1 );\
}\
}\
}
os = out->Xsize * out->Bands;
line = (PEL *) calloc ( (unsigned)os, sizeof(double) );
if (line == NULL)
{ im_error("im_gfadd"," unable to calloc"); return( -1 ); }
switch (out->BandFmt) {
case IM_BANDFMT_DOUBLE:
switch (tmp2->BandFmt) {
case IM_BANDFMT_UCHAR:
select_outdouble(unsigned char, double);
break;
case IM_BANDFMT_CHAR:
select_outdouble(signed char, double);
break;
case IM_BANDFMT_USHORT:
select_outdouble(unsigned short, double);
break;
case IM_BANDFMT_SHORT:
select_outdouble(signed short, double);
break;
case IM_BANDFMT_UINT:
select_outdouble(unsigned int, double);
break;
case IM_BANDFMT_INT:
select_outdouble(signed int, double);
break;
case IM_BANDFMT_FLOAT:
select_outdouble(float, double);
break;
case IM_BANDFMT_DOUBLE:
select_outdouble(double, double);
break;
default:
im_error("im_gfadd","Wrong tmp2 format(d)");
free( line );
return( -1 );
}
break;
case IM_BANDFMT_FLOAT :
switch (tmp2->BandFmt) {
case IM_BANDFMT_UCHAR:
switch (tmp1->BandFmt) {
outfloat_2uchar(unsigned char, float);
default:
im_error("im_gfadd"," Error (a)");
free( line );
return( -1 );
}
break;
case IM_BANDFMT_CHAR:
switch (tmp1->BandFmt) {
outfloat_2char(signed char, float);
default:
im_error("im_gfadd"," Error (b)");
free( line); return( -1 );
}
break;
case IM_BANDFMT_USHORT:
switch (tmp1->BandFmt) {
outfloat_2ushort(unsigned short, float);
default:
im_error("im_gfadd"," Error (c)");
free( line); return( -1 );
}
break;
case IM_BANDFMT_SHORT:
switch (tmp1->BandFmt) {
outfloat_2short(signed short, float);
default:
im_error("im_gfadd"," Error (d)");
free( line); return( -1 );
}
break;
case IM_BANDFMT_UINT:
switch (tmp1->BandFmt) {
outfloat_2uint(unsigned int, float);
default:
im_error("im_gfadd"," Error (e)");
free( line); return( -1 );
}
break;
case IM_BANDFMT_INT:
switch (tmp1->BandFmt) {
outfloat_2int(signed int, float);
default:
im_error("im_gfadd"," Error (f)");
free( line );
return( -1 );
}
break;
case IM_BANDFMT_FLOAT:
switch (tmp1->BandFmt) {
outfloat_2float(float, float);
default:
im_error("im_gfadd"," Error (g)");
free( line );
return( -1 );
}
break;
default:
im_error("im_gfadd"," Wrong tmp2 format(f)");
free( line );
return( -1 );
}
break;
default:
im_error("im_gfadd"," Impossible output state");
free( line );
return( -1 );
}
free( line );
return( 0 );
}

View File

@ -0,0 +1,151 @@
/* @(#) Invert a UCHAR image. Very simple new-style VIPS routine. See
* @(#) im_exptra() for the next level of complexity. This function is not
* @(#) as quick as it could be - it is intended to be an example rather than
* @(#) to be useful. This should really be written with im_wrapone().
* @(#)
* @(#) int
* @(#) im_invert( IMAGE *in, IMAGE *out )
* @(#)
* @(#) All functions return 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 12/02/1990
* Modified on :
* 7/7/93 JC
* - memory leaks fixed
* - adapted for partial v2
* - ANSIfied
* 22/2/95 JC
* - tidied up again
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Invert a REGION. We are given the REGION we should write to, the REGION we
* should use for input, and the IMAGE we are processing. On entry to
* invert_gen(), or points to the memory we should write to and ir is blank.
*/
static int
invert_gen( REGION *or, void *seq, void *a, void *b )
{
REGION *ir = (REGION *) seq;
/* Left, right, top and bottom for the output region.
*/
int le = or->valid.left;
int to = or->valid.top;
int bo = IM_RECT_BOTTOM( &or->valid );
int x, y;
/* Ask for the section of the input image we need to produce this
* section of the output image.
*/
if( im_prepare( ir, &or->valid ) )
return( -1 );
/* Loop over output, writing input.
*/
for( y = to; y < bo; y++ ) {
/* Point p and q at the start of the line of pels we must
* process this loop.
*/
PEL *p = (PEL *) IM_REGION_ADDR( ir, le, y );
PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );
/* Loop along the line, processing pels.
* IM_REGION_N_ELEMENTS(region) gives
* the number of band elements across a region. By looping to
* IM_REGION_N_ELEMENTS() rather than ir->valid.width, we work
* for any number of bands.
*/
for( x = 0; x < IM_REGION_N_ELEMENTS( or ); x++ )
q[x] = 255 - p[x];
}
return( 0 );
}
/* Invert IMAGE in to IMAGE out. Any number of bands, unsigned char pels
* only. See im_exptra() for an example of a VIPS function which can process
* any input image type.
*/
int
im_invert( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_invert", "%s", _( "not uncoded" ) );
return( -1 );
}
if( in->BandFmt != IM_BANDFMT_UCHAR ) {
im_error( "im_invert", "%s", _( "not UCHAR" ) );
return( -1 );
}
if( im_piocheck( in, out ) )
return( -1 );
/* Prepare the output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
/* Set demand hints. Like most one-to-one operations, we work best
* with long, thin strips.
*/
if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) )
return( -1 );
/* Generate into out. im_start_one() and im_stop_one() are simple
* convenience functions provided by VIPS which do the necessary
* region creation and destruction for one-image-in
* style functions. See im_add(), im_start_many() and im_stop_many()
* for convenience functions for multiple inputs.
*/
if( im_generate( out,
im_start_one, invert_gen, im_stop_one, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,433 @@
/* @(#) Function to find perform pixelwise linear regression on an array of
* @(#) single band images.
* @(#)
* @(#) int im_linreg(
* @(#) IMAGE **ins,
* @(#) IMAGE *out,
* @(#) double *xs
* @(#) );
* @(#)
*
* Copyright: 2006, The Nottingham Trent University
*
* Author: Tom Vajzovic
*
* Written on: 2006-12-26
*
* 12/5/09
* - make x_anal() static, fix some signed/unsigned warnings
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/** HEADERS **/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <vips/intl.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC */
/** TYPES **/
typedef struct {
unsigned int n;
double *xs;
double *difs;
double mean;
double nsig2;
double err_term;
} x_set;
#define LINREG_SEQ( TYPE ) typedef struct { \
REGION **regs; \
TYPE **ptrs; \
size_t *skips; \
} linreg_seq_ ## TYPE
LINREG_SEQ( gint8 );
LINREG_SEQ( guint8 );
LINREG_SEQ( gint16 );
LINREG_SEQ( guint16 );
LINREG_SEQ( gint32 );
LINREG_SEQ( guint32 );
LINREG_SEQ( float );
LINREG_SEQ( double );
/** LOCAL FUNCTION DECLARATIONS **/
static x_set *x_anal( IMAGE *im, double *xs, unsigned int n );
#define LINREG_START_DECL( TYPE ) static void * linreg_start_ ## TYPE( IMAGE *, void *, void * );
#define LINREG_GEN_DECL( TYPE ) static int linreg_gen_ ## TYPE( REGION *, void *, void *, void * );
#define LINREG_STOP_DECL( TYPE ) static int linreg_stop_ ## TYPE( void *, void *, void * );
#define INCR_ALL_DECL( TYPE ) static void incr_all_ ## TYPE( TYPE **ptrs, unsigned int n )
#define SKIP_ALL_DECL( TYPE ) static void skip_all_ ## TYPE( TYPE **ptrs, size_t *skips, unsigned int n )
LINREG_START_DECL( gint8 );
LINREG_START_DECL( guint8 );
LINREG_START_DECL( gint16 );
LINREG_START_DECL( guint16 );
LINREG_START_DECL( gint32 );
LINREG_START_DECL( guint32 );
LINREG_START_DECL( float );
LINREG_START_DECL( double );
LINREG_GEN_DECL( gint8 );
LINREG_GEN_DECL( guint8 );
LINREG_GEN_DECL( gint16 );
LINREG_GEN_DECL( guint16 );
LINREG_GEN_DECL( gint32 );
LINREG_GEN_DECL( guint32 );
LINREG_GEN_DECL( float );
LINREG_GEN_DECL( double );
LINREG_STOP_DECL( gint8 );
LINREG_STOP_DECL( guint8 );
LINREG_STOP_DECL( gint16 );
LINREG_STOP_DECL( guint16 );
LINREG_STOP_DECL( gint32 );
LINREG_STOP_DECL( guint32 );
LINREG_STOP_DECL( float );
LINREG_STOP_DECL( double );
INCR_ALL_DECL( gint8 );
INCR_ALL_DECL( guint8 );
INCR_ALL_DECL( gint16 );
INCR_ALL_DECL( guint16 );
INCR_ALL_DECL( gint32 );
INCR_ALL_DECL( guint32 );
INCR_ALL_DECL( float );
INCR_ALL_DECL( double );
SKIP_ALL_DECL( gint8 );
SKIP_ALL_DECL( guint8 );
SKIP_ALL_DECL( gint16 );
SKIP_ALL_DECL( guint16 );
SKIP_ALL_DECL( gint32 );
SKIP_ALL_DECL( guint32 );
SKIP_ALL_DECL( float );
SKIP_ALL_DECL( double );
/** EXPORTED FUNCTION DEFINITION **/
int im_linreg( IMAGE **ins, IMAGE *out, double *xs ){
#define FUNCTION_NAME "im_linreg"
int n;
x_set *x_vals;
if( im_poutcheck( out ) )
return( -1 );
for( n= 0; ins[ n ]; ++n ){
/*
if( ! isfinite( xs[ n ] ) ){
im_error( FUNCTION_NAME, "invalid argument" );
return( -1 );
}
*/
if( im_pincheck( ins[ n ] ) )
return( -1 );
if( 1 != ins[ n ]-> Bands ){
im_error( FUNCTION_NAME, "image is not single band" );
return( -1 );
}
if( ins[ n ]-> Coding ){
im_error( FUNCTION_NAME, "image is not uncoded" );
return( -1 );
}
if( n ){
if( ins[ n ]-> BandFmt != ins[ 0 ]-> BandFmt ){
im_error( FUNCTION_NAME, "image band formats differ" );
return( -1 );
}
}
else {
if( ! im_isscalar( ins[ 0 ] ) ){
im_error( FUNCTION_NAME, "image has non-scalar band format" );
return( -1 );
}
}
if( n && ( ins[ n ]-> Xsize != ins[ 0 ]-> Xsize
|| ins[ n ]-> Ysize != ins[ 0 ]-> Ysize ) ){
im_error( FUNCTION_NAME, "image sizes differ" );
return( -1 );
}
}
if( n < 3 ){
im_error( FUNCTION_NAME, "not enough input images" );
return( -1 );
}
if( im_cp_desc_array( out, ins ) )
return( -1 );
out-> Bands= 7;
out-> BandFmt= IM_BANDFMT_DOUBLE;
out-> Bbits= IM_BBITS_DOUBLE;
out-> Type= 0;
if( im_demand_hint_array( out, IM_THINSTRIP, ins ) )
return( -1 );
x_vals= x_anal( out, xs, n );
if( ! x_vals )
return( -1 );
switch( ins[ 0 ]-> BandFmt ){
#define LINREG_RET( TYPE ) return im_generate( out, linreg_start_ ## TYPE, linreg_gen_ ## TYPE, linreg_stop_ ## TYPE, ins, x_vals )
case IM_BANDFMT_CHAR:
LINREG_RET( gint8 );
case IM_BANDFMT_UCHAR:
LINREG_RET( guint8 );
case IM_BANDFMT_SHORT:
LINREG_RET( gint16 );
case IM_BANDFMT_USHORT:
LINREG_RET( guint16 );
case IM_BANDFMT_INT:
LINREG_RET( gint32 );
case IM_BANDFMT_UINT:
LINREG_RET( guint32 );
case IM_BANDFMT_FLOAT:
LINREG_RET( float );
case IM_BANDFMT_DOUBLE:
LINREG_RET( double );
default: /* keep -Wall happy */
return( -1 );
}
#undef FUNCTION_NAME
}
/** LOCAL FUNCTION DECLARATIONS **/
static x_set *x_anal( IMAGE *im, double *xs, unsigned int n ){
unsigned int i;
x_set *x_vals= IM_NEW( im, x_set );
if( ! x_vals )
return( NULL );
x_vals-> xs= IM_ARRAY( im, 2 * n, double );
if( ! x_vals-> xs )
return( NULL );
x_vals-> difs= x_vals-> xs + n;
x_vals-> n= n;
x_vals-> mean= 0.0;
for( i= 0; i < n; ++i ){
x_vals-> xs[ i ]= xs[ i ];
x_vals-> mean+= xs[ i ];
}
x_vals-> mean/= n;
x_vals-> nsig2= 0.0;
for( i= 0; i < n; ++i ){
x_vals-> difs[ i ]= xs[ i ] - x_vals-> mean;
x_vals-> nsig2+= x_vals-> difs[ i ] * x_vals-> difs[ i ];
}
x_vals-> err_term= ( 1.0 / (double) n ) + ( ( x_vals-> mean * x_vals-> mean ) / x_vals-> nsig2 );
return( x_vals );
}
#define LINREG_START_DEFN( TYPE ) static void *linreg_start_ ## TYPE( IMAGE *out, void *a, void *b ){ \
IMAGE **ins= (IMAGE **) a; \
x_set *x_vals= (x_set *) b; \
linreg_seq_ ## TYPE *seq= IM_NEW( out, linreg_seq_ ## TYPE ); \
\
if( ! seq ) \
return NULL; \
\
seq-> regs= im_start_many( NULL, ins, NULL ); \
seq-> ptrs= IM_ARRAY( out, x_vals-> n, TYPE* ); \
seq-> skips= IM_ARRAY( out, x_vals-> n, size_t ); \
\
if( ! seq-> ptrs || ! seq-> regs || ! seq-> skips ){ \
linreg_stop_ ## TYPE( seq, NULL, NULL ); \
return NULL; \
} \
return (void *) seq; \
}
#define N ( (double) n )
#define y(a) ( (double) (* seq-> ptrs[(a)] ) )
#define x(a) ( (double) ( x_vals-> xs[(a)] ) )
#define xd(a) ( (double) ( x_vals-> difs[(a)] ) )
#define Sxd2 ( x_vals-> nsig2 )
#define mean_x ( x_vals-> mean )
#define mean_y ( out[0] )
#define dev_y ( out[1] )
#define y_x0 ( out[2] )
#define d_y_x0 ( out[3] )
#define dy_dx ( out[4] )
#define d_dy_dx ( out[5] )
#define R ( out[6] )
#define LINREG_GEN_DEFN( TYPE ) static int linreg_gen_ ## TYPE( REGION *to_make, void *vseq, void *unrequired, void *b ){ \
linreg_seq_ ## TYPE *seq= (linreg_seq_ ## TYPE *) vseq; \
x_set *x_vals= (x_set *) b; \
unsigned int n= x_vals-> n; \
double *out= (double*) IM_REGION_ADDR_TOPLEFT( to_make ); \
size_t out_skip= IM_REGION_LSKIP( to_make ) / sizeof( double ); \
double *out_end= out + out_skip * to_make-> valid. height; \
double *out_stop; \
size_t out_n= IM_REGION_N_ELEMENTS( to_make ); \
unsigned int i; \
\
out_skip-= out_n; \
\
if( im_prepare_many( seq-> regs, & to_make-> valid ) ) \
return -1; \
\
for( i= 0; i < n; ++i ){ \
seq-> ptrs[ i ]= (TYPE*) IM_REGION_ADDR( seq-> regs[ i ], to_make-> valid. left, to_make-> valid. top ); \
seq-> skips[ i ]= ( IM_REGION_LSKIP( seq-> regs[ i ] ) / sizeof( TYPE ) ) - IM_REGION_N_ELEMENTS( seq-> regs[ i ] ); \
} \
\
for( ; out < out_end; out+= out_skip, skip_all_ ## TYPE( seq-> ptrs, seq-> skips, n ) ) \
for( out_stop= out + out_n; out < out_stop; out+= 7, incr_all_ ## TYPE( seq-> ptrs, n ) ){ \
double Sy= 0.0; \
double Sxd_y= 0.0; \
double Syd2= 0.0; \
double Sxd_yd= 0.0; \
double Se2= 0.0; \
\
for( i= 0; i < n; ++i ){ \
Sy+= y(i); \
Sxd_y+= xd(i) * y(i); \
} \
mean_y= Sy / N; \
dy_dx= Sxd_y / Sxd2; \
y_x0= mean_y - dy_dx * mean_x; \
\
for( i= 0; i < n; ++i ){ \
double yd= y(i) - mean_y; \
double e= y(i) - dy_dx * x(i) - y_x0; \
Syd2+= yd * yd; \
Sxd_yd+= xd(i) * yd; \
Se2+= e * e; \
} \
dev_y= sqrt( Syd2 / N ); \
Se2/= ( N - 2.0 ); \
d_dy_dx= sqrt( Se2 / Sxd2 ); \
d_y_x0= sqrt( Se2 * x_vals-> err_term ); \
R= Sxd_yd / sqrt( Sxd2 * Syd2 ); \
} \
return 0; \
}
#define LINREG_STOP_DEFN( TYPE ) static int linreg_stop_ ## TYPE( void *vseq, void *a, void *b ){ \
linreg_seq_ ## TYPE *seq = (linreg_seq_ ## TYPE *) vseq; \
if( seq-> regs ) \
im_stop_many( seq-> regs, NULL, NULL ); \
return 0; \
}
#define INCR_ALL_DEFN( TYPE ) static void incr_all_ ## TYPE( TYPE **ptrs, unsigned int n ){ \
TYPE **stop= ptrs + n; \
for( ; ptrs < stop; ++ptrs ) \
++*ptrs; \
}
#define SKIP_ALL_DEFN( TYPE ) static void skip_all_ ## TYPE( TYPE **ptrs, size_t *skips, unsigned int n ){ \
TYPE **stop= ptrs + n; \
for( ; ptrs < stop; ++ptrs, ++skips ) \
*ptrs+= *skips; \
}
LINREG_START_DEFN( gint8 );
LINREG_START_DEFN( guint8 );
LINREG_START_DEFN( gint16 );
LINREG_START_DEFN( guint16 );
LINREG_START_DEFN( gint32 );
LINREG_START_DEFN( guint32 );
LINREG_START_DEFN( float );
LINREG_START_DEFN( double );
LINREG_GEN_DEFN( gint8 );
LINREG_GEN_DEFN( guint8 );
LINREG_GEN_DEFN( gint16 );
LINREG_GEN_DEFN( guint16 );
LINREG_GEN_DEFN( gint32 );
LINREG_GEN_DEFN( guint32 );
LINREG_GEN_DEFN( float );
LINREG_GEN_DEFN( double );
LINREG_STOP_DEFN( gint8 );
LINREG_STOP_DEFN( guint8 );
LINREG_STOP_DEFN( gint16 );
LINREG_STOP_DEFN( guint16 );
LINREG_STOP_DEFN( gint32 );
LINREG_STOP_DEFN( guint32 );
LINREG_STOP_DEFN( float );
LINREG_STOP_DEFN( double );
INCR_ALL_DEFN( gint8 );
INCR_ALL_DEFN( guint8 );
INCR_ALL_DEFN( gint16 );
INCR_ALL_DEFN( guint16 );
INCR_ALL_DEFN( gint32 );
INCR_ALL_DEFN( guint32 );
INCR_ALL_DEFN( float );
INCR_ALL_DEFN( double );
SKIP_ALL_DEFN( gint8 );
SKIP_ALL_DEFN( guint8 );
SKIP_ALL_DEFN( gint16 );
SKIP_ALL_DEFN( guint16 );
SKIP_ALL_DEFN( gint32 );
SKIP_ALL_DEFN( guint32 );
SKIP_ALL_DEFN( float );
SKIP_ALL_DEFN( double );

View File

@ -0,0 +1,383 @@
/* @(#) Pass an image through a linear transform - ie. out = in*a + b. Output
* @(#) is always float for integer input, double for double input, complex for
* @(#) complex input and double complex for double complex input.
* @(#)
* @(#) int
* @(#) im_lintra( a, in, b, out )
* @(#) IMAGE *in, *out;
* @(#) double a, b;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris, based on im_powtra()
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 23/4/93 JC
* - adapted to work with partial images
* 1/7/93 JC
* - adapted for partial v2
* 7/10/94 JC
* - new IM_NEW()
* - more typedefs
* 9/2/95 JC
* - adapted for im_wrap...
* - operations on complex images now just transform the real channel
* 29/9/95 JC
* - complex was broken
* 15/4/97 JC
* - return(0) missing from generate, arrgh!
* 1/7/98 JC
* - im_lintra_vec added
* 3/8/02 JC
* - fall back to im_copy() for a == 1, b == 0
* 10/10/02 JC
* - auug, failing to multiply imag for complex! (thanks matt)
* 10/12/02 JC
* - removed im_copy() fallback ... meant that output format could change
* with value :-( very confusing
* 30/6/04
* - added 1 band image * n band vector case
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Struct we need for im_generate().
*/
typedef struct {
int n; /* Number of bands of constants */
double *a, *b;
} LintraInfo;
/* Define what we do for each band element type. Non-complex input, any
* output.
*/
#define LOOP(IN, OUT) { \
IN *p = (IN *) in; \
OUT *q = (OUT *) out; \
\
for( x = 0; x < sz; x++ ) \
q[x] = a * (OUT) p[x] + b; \
}
/* Complex input, complex output.
*/
#define LOOPCMPLX(IN, OUT) {\
IN *p = (IN *) in; \
OUT *q = (OUT *) out; \
\
for( x = 0; x < sz; x++ ) { \
q[0] = a * p[0] + b; \
q[1] = a * p[1]; \
q += 2; \
p += 2; \
} \
}
#ifdef HAVE_LIBOIL
/* Process granularity.
*/
#define CHUNKS (1000)
/* d[] = s[] * b + c, with liboil
*/
static void
lintra_f32( float *d, float *s, int n, float b, float c )
{
float buf[CHUNKS];
int i;
for( i = 0; i < n; i += CHUNKS ) {
oil_scalarmultiply_f32_ns( buf, s,
&b, IM_MIN( CHUNKS, n - i ) );
oil_scalaradd_f32_ns( d, buf,
&c, IM_MIN( CHUNKS, n - i ) );
s += CHUNKS;
d += CHUNKS;
}
}
#endif /*HAVE_LIBOIL*/
/* Lintra a buffer, 1 set of scale/offset.
*/
static int
lintra1_gen( PEL *in, PEL *out, int width, IMAGE *im, LintraInfo *inf )
{
double a = inf->a[0];
double b = inf->b[0];
int sz = width * im->Bands;
int x;
/* Lintra all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: LOOP( unsigned char, float ); break;
case IM_BANDFMT_CHAR: LOOP( signed char, float ); break;
case IM_BANDFMT_USHORT: LOOP( unsigned short, float ); break;
case IM_BANDFMT_SHORT: LOOP( signed short, float ); break;
case IM_BANDFMT_UINT: LOOP( unsigned int, float ); break;
case IM_BANDFMT_INT: LOOP( signed int, float ); break;
case IM_BANDFMT_FLOAT:
#ifdef HAVE_LIBOIL
lintra_f32( (float *) out, (float *) in, sz, a, b );
#else /*!HAVE_LIBOIL*/
LOOP( float, float );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: LOOP( double, double ); break;
case IM_BANDFMT_COMPLEX: LOOPCMPLX( float, float ); break;
case IM_BANDFMT_DPCOMPLEX: LOOPCMPLX( double, double ); break;
default:
assert( 0 );
}
return( 0 );
}
/* Define what we do for each band element type. Non-complex input, any
* output.
*/
#define LOOPN(IN, OUT)\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( i = 0, x = 0; x < width; x++ )\
for( k = 0; k < nb; k++, i++ )\
q[i] = a[k] * (OUT) p[i] + b[k];\
}
/* Complex input, complex output.
*/
#define LOOPCMPLXN(IN, OUT)\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < width; x++ ) \
for( k = 0; k < nb; k++ ) {\
q[0] = a[k] * p[0] + b[k];\
q[1] = a[k] * p[1];\
q += 2;\
p += 2;\
}\
}
/* Lintra a buffer, n set of scale/offset.
*/
static int
lintran_gen( PEL *in, PEL *out, int width, IMAGE *im, LintraInfo *inf )
{
double *a = inf->a;
double *b = inf->b;
int nb = im->Bands;
int i, x, k;
/* Lintra all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: LOOPN( unsigned char, float ); break;
case IM_BANDFMT_CHAR: LOOPN( signed char, float ); break;
case IM_BANDFMT_USHORT: LOOPN( unsigned short, float ); break;
case IM_BANDFMT_SHORT: LOOPN( signed short, float ); break;
case IM_BANDFMT_UINT: LOOPN( unsigned int, float ); break;
case IM_BANDFMT_INT: LOOPN( signed int, float ); break;
case IM_BANDFMT_FLOAT: LOOPN( float, float ); break;
case IM_BANDFMT_DOUBLE: LOOPN( double, double ); break;
case IM_BANDFMT_COMPLEX: LOOPCMPLXN( float, float ); break;
case IM_BANDFMT_DPCOMPLEX: LOOPCMPLXN( double, double ); break;
default:
assert( 0 );
}
return( 0 );
}
/* 1 band image, n band vector.
*/
#define LOOPNV(IN, OUT) { \
IN *p = (IN *) in; \
OUT *q = (OUT *) out; \
\
for( i = 0, x = 0; x < width; x++ ) { \
OUT v = p[x]; \
\
for( k = 0; k < nb; k++, i++ ) \
q[i] = a[k] * v + b[k]; \
} \
}
#define LOOPCMPLXNV(IN, OUT) { \
IN *p = (IN *) in; \
OUT *q = (OUT *) out; \
\
for( x = 0; x < width; x++ ) { \
OUT p0 = p[0]; \
OUT p1 = p[1]; \
\
for( k = 0; k < nb; k++ ) { \
q[0] = a[k] * p0 + b[k]; \
q[1] = a[k] * p1; \
q += 2; \
} \
\
p += 2; \
} \
}
static int
lintranv_gen( PEL *in, PEL *out, int width, IMAGE *im, LintraInfo *inf )
{
double *a = inf->a;
double *b = inf->b;
int nb = inf->n;
int i, x, k;
/* Lintra all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: LOOPNV( unsigned char, float ); break;
case IM_BANDFMT_CHAR: LOOPNV( signed char, float ); break;
case IM_BANDFMT_USHORT: LOOPNV( unsigned short, float ); break;
case IM_BANDFMT_SHORT: LOOPNV( signed short, float ); break;
case IM_BANDFMT_UINT: LOOPNV( unsigned int, float ); break;
case IM_BANDFMT_INT: LOOPNV( signed int, float ); break;
case IM_BANDFMT_FLOAT: LOOPNV( float, float ); break;
case IM_BANDFMT_DOUBLE: LOOPNV( double, double ); break;
case IM_BANDFMT_COMPLEX: LOOPCMPLXNV( float, float ); break;
case IM_BANDFMT_DPCOMPLEX: LOOPCMPLXNV( double, double ); break;
default:
assert( 0 );
}
return( 0 );
}
/* Linear transform n bands.
*/
int
im_lintra_vec( int n, double *a, IMAGE *in, double *b, IMAGE *out )
{
LintraInfo *inf;
int i;
/* Check args.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_lintra_vec", "%s", _( "not uncoded" ) );
return( -1 );
}
/* If n and bands differ, one of them must be one (and we multiplex
* the other).
*/
if( n != in->Bands && (n != 1 && in->Bands != 1) ) {
im_error( "im_lintra_vec",
_( "not 1 or %d elements in vector" ), in->Bands );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
if( im_isint( in ) ) {
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
}
if( in->Bands == 1 )
out->Bands = n;
/* Make space for a little buffer.
*/
if( !(inf = IM_NEW( out, LintraInfo )) ||
!(inf->a = IM_ARRAY( out, n, double )) ||
!(inf->b = IM_ARRAY( out, n, double )) )
return( -1 );
inf->n = n;
for( i = 0; i < n; i++ ) {
inf->a[i] = a[i];
inf->b[i] = b[i];
}
/* Generate!
*/
if( n == 1 ) {
if( im_wrapone( in, out,
(im_wrapone_fn) lintra1_gen, in, inf ) )
return( -1 );
}
else if( in->Bands == 1 ) {
if( im_wrapone( in, out,
(im_wrapone_fn) lintranv_gen, in, inf ) )
return( -1 );
}
else {
if( im_wrapone( in, out,
(im_wrapone_fn) lintran_gen, in, inf ) )
return( -1 );
}
return( 0 );
}
/* Linear transform.
*/
int
im_lintra( double a, IMAGE *in, double b, IMAGE *out )
{
return( im_lintra_vec( 1, &a, in, &b, out ) );
}

View File

@ -0,0 +1,321 @@
/* @(#) Function to perform lighting correction.
* @(#) One band IM_BANDFMT_UCHAR images only. Always writes UCHAR.
* @(#)
* @(#) Function im_litecor() assumes that imin
* @(#) is either memory mapped or in a buffer.
* @(#)
* @(#) int im_litecor(in, w, out, clip, factor)
* @(#) IMAGE *in, *w, *out;
* @(#) int clip;
* @(#) double factor;
* @(#)
* @(#) clip==1
* @(#) - Compute max(white)*factor*(image/white), Clip to 255.
* @(#) clip==0
* @(#) - Compute factor for you.
* @(#)
* @(#)
* @(#)
* @(#)
* @(#) Returns 0 on success and -1 on error
*
* Copyright: 1990, J. Cupitt, 1991 N. Dessipris
*
* Author: J. Cupitt, N. Dessipris
* Written on: 02/08/1990
* Modified on : 6/11/1991, by ND to produce a UCHAR output
* 1/4/93 J.Cupitt
* - bugs if white is smaller than image fixed
* - im_warning() now called
* - clip==0 case not tested or changed! do not use!
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* If maximum output is > 255 scale output between minout and maxout,
* by normalising maxout to 255.
* If maximum output is < 255 do the light correction without scaling
*/
static int
im_litecor0( in, white, out )
IMAGE *in, *white, *out;
{ PEL *p, *w;
PEL *q, *bu;
int c;
int x, y;
float xrat = (float) in->Xsize / white->Xsize;
float yrat = (float) in->Ysize / white->Ysize;
int xstep = (int) xrat;
int ystep = (int) yrat;
double max;
int wtmp, maxw, maxout, temp;
/* Check white is some simple multiple of image.
*/
if( xrat < 1.0 || xrat != xstep || yrat < 1.0 || yrat != ystep ) {
im_error( "im_litecor", "white not simple scale of image" );
return( -1 );
}
/* Find the maximum of the white.
*/
if( im_max( white, &max ) )
return( -1 );
maxw = (int)max;
/* Set up the output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
if( im_setupout( out ) )
return( -1 );
/* Make buffer for outputting to.
*/
if( !(bu = (PEL *) im_malloc( out, out->Xsize )) )
return( -1 );
/* Find largest value we might generate if factor == 1.0
*/
maxout = -1;
p = (PEL *) in->data;
for( y = 0; y < in->Ysize; y++ ) {
/* Point w to the start of the line in the white
* corresponding to the line we are about to correct. c counts
* up to xstep; each time it wraps, we should move w on one.
*/
w = (PEL *) (white->data + white->Xsize * (int)(y/ystep));
c = 0;
/* Scan along line.
*/
for( x = 0; x < out->Xsize; x++ ) {
wtmp = (int)*w;
temp = ( maxw * (int) *p++ + (wtmp>>1) ) / wtmp;
if (temp > maxout )
maxout = temp;
/* Move white pointer on if necessary. */
c++;
if( c == xstep ) {
w++;
c = 0;
}
}
}
/* Do exactly the same as above by scaling the result with respect to
* maxout
*/
p = (PEL *) in->data;
if (maxout <= 255 ) /* no need for rescaling output */
{
for( y = 0; y < in->Ysize; y++ )
{
q = bu;
w = (PEL *) (white->data +
white->Xsize * (int)(y/ystep));
c = 0;
/* Scan along line. */
for( x = 0; x < in->Xsize; x++ )
{
wtmp = (int)*w;
*q++ = (PEL)
( ( maxw * (int) *p++ + (wtmp>>1) ) / wtmp );
/* Move white pointer on if necessary.
*/
c++;
if( c == xstep ) { w++; c = 0; }
}
if( im_writeline( y, out, bu ) )
{
im_error("im_litecor", "im_writeline failed");
return( -1 );
}
}
}
else /* rescale output wrt maxout */
{
for( y = 0; y < in->Ysize; y++ )
{
q = bu;
w = (PEL *) (white->data +
white->Xsize * (int)(y/ystep));
c = 0;
/* Scan along line. */
for( x = 0; x < in->Xsize; x++ )
{
wtmp = maxout * ((int)*w);
*q++ = (PEL)
( ( maxw * (int) *p++ * 255 + (wtmp>>1)) / wtmp );
/* Move white pointer on if necessary.
*/
c++;
if( c == xstep ) { w++; c = 0; }
}
if( im_writeline( y, out, bu ) )
{
im_error("im_litecor", "im_writeline failed");
return( -1 );
}
}
}
return( 0 );
}
/* Clip all corrected values above 255, if any.
*/
static int
im_litecor1( in, white, out, factor )
IMAGE *in, *white, *out;
double factor;
{ PEL *p, *w;
PEL *q, *bu;
int c;
int x, y;
float xrat = (float) in->Xsize / white->Xsize;
float yrat = (float) in->Ysize / white->Ysize;
int xstep = (int) xrat;
int ystep = (int) yrat;
double max;
double maxw, temp;
int nclipped = 0;
/* Check white is some simple multiple of image.
*/
if( xrat < 1.0 || xrat != xstep || yrat < 1.0 || yrat != ystep ) {
im_error( "im_litecor", "white not simple scale of image" );
return( -1 );
}
/* Find the maximum of the white.
*/
if( im_max( white, &max ) )
return( -1 );
maxw = max;
/* Set up the output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
if( im_setupout( out ) )
return( -1 );
/* Make buffer we write to.
*/
if( !(bu = (PEL *) im_malloc( out, out->Xsize )) )
return( -1 );
/* Loop through sorting max output
*/
p = (PEL *) in->data;
for( y = 0; y < in->Ysize; y++ ) {
q = bu;
w = (PEL *) (white->data + white->Xsize * (int)(y / ystep));
c = 0;
for( x = 0; x < out->Xsize; x++ ) {
temp = ((factor * maxw * (int) *p++)/((int) *w)) + 0.5;
if( temp > 255.0 ) {
temp = 255;
nclipped++;
}
*q++ = temp;
/* Move white pointer on if necessary.
*/
c++;
if( c == xstep ) {
w++;
c = 0;
}
}
if( im_writeline( y, out, bu ) )
return( -1 );
}
if( nclipped )
im_warn( "im_litecor", "%d pels over 255 clipped", nclipped );
return( 0 );
}
/* Lighting correction. One band uchar images only.
* Assumes the white is some simple multiple of the image in size; ie. the
* white has been taken with some smaller or equal set of resolution
* parameters.
*/
int
im_litecor( in, white, out, clip, factor )
IMAGE *in, *white, *out;
int clip;
double factor;
{ /* Check our args.
*/
if( im_iocheck( in, out ) )
return( -1 );
if( in->Bands != 1 || in->Bbits != 8 ||
in->Coding != IM_CODING_NONE || in->BandFmt != IM_BANDFMT_UCHAR ) {
im_error( "im_litecor", "bad input format" );
return( -1 );
}
if( white->Bands != 1 || white->Bbits != 8 ||
white->Coding != IM_CODING_NONE || white->BandFmt != IM_BANDFMT_UCHAR ) {
im_error( "im_litecor", "bad white format" );
return( -1 );
}
switch( clip ) {
case 1:
return( im_litecor1( in, white, out, factor ) );
case 0:
return( im_litecor0( in, white, out ) );
default:
im_error( "im_litecor", "unknown flag %d", clip );
return( -1 );
}
}

View File

@ -0,0 +1,167 @@
/* @(#) Find base 10 log of any non-complex image. Output
* @(#) is always float for integer input and double for double input.
* @(#)
* @(#) int
* @(#) im_log10tra( in, out )
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris, based on im_powtra()
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 5/5/93 JC
* - adapted from im_lintra to work with partial images
* - incorrect implementation of complex logs removed
* 1/7/93 JC
* - adapted for partial v2
* - ANSIfied
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Define what we do for each band element type. Non-complex input, any
* output.
*/
#define loop(IN, OUT)\
for( y = to; y < bo; y++ ) {\
IN *p = (IN *) IM_REGION_ADDR( ir, le, y );\
OUT *q = (OUT *) IM_REGION_ADDR( or, le, y );\
\
for( x = 0; x < sz; x++ )\
*q++ = log10( *p++ );\
}
/* log10tra a small area.
*/
static int
log10tra_gen( REGION *or, void *seq, void *a, void *b )
{
REGION *ir = (REGION *) seq;
Rect *r = &or->valid;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int sz = IM_REGION_N_ELEMENTS( or );
int x, y;
/* Ask for input we need.
*/
if( im_prepare( ir, r ) )
return( -1 );
/* log10tra all input types.
*/
switch( ir->im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop(unsigned char, float); break;
case IM_BANDFMT_CHAR: loop(signed char, float); break;
case IM_BANDFMT_USHORT: loop(unsigned short, float); break;
case IM_BANDFMT_SHORT: loop(signed short, float); break;
case IM_BANDFMT_UINT: loop(unsigned int, float); break;
case IM_BANDFMT_INT: loop(signed int, float); break;
case IM_BANDFMT_FLOAT: loop(float, float); break;
case IM_BANDFMT_DOUBLE: loop(double, double); break;
default:
assert( 0 );
}
return( 0 );
}
/* Log 10 transform.
*/
int
im_log10tra( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_log10tra", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_log10tra", "%s", _( "not non-complex" ) );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
break;
default:
assert( 0 );
}
/* Set demand hints.
*/
if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) )
return( -1 );
/* Generate!
*/
if( im_generate( out,
im_start_one, log10tra_gen, im_stop_one, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,167 @@
/* @(#) Find natural log of any non-complex image. Output
* @(#) is always float for integer input and double for double input.
* @(#)
* @(#) int
* @(#) im_logtra( in, out )
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris, based on im_powtra()
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 5/5/93 JC
* - adapted from im_lintra to work with partial images
* - incorrect implementation of complex logs removed
* 1/7/93 JC
* - adapted for partial v2
* - ANSIfied
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Define what we do for each band element type. Non-complex input, any
* output.
*/
#define loop(IN, OUT)\
for( y = to; y < bo; y++ ) {\
IN *p = (IN *) IM_REGION_ADDR( ir, le, y );\
OUT *q = (OUT *) IM_REGION_ADDR( or, le, y );\
\
for( x = 0; x < sz; x++ )\
*q++ = log( *p++ );\
}
/* logtra a small area.
*/
static int
logtra_gen( REGION *or, void *seq, void *a, void *b )
{
REGION *ir = (REGION *) seq;
Rect *r = &or->valid;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int sz = IM_REGION_N_ELEMENTS( or );
int x, y;
/* Ask for input we need.
*/
if( im_prepare( ir, r ) )
return( -1 );
/* logtra all input types.
*/
switch( ir->im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop(unsigned char, float); break;
case IM_BANDFMT_CHAR: loop(signed char, float); break;
case IM_BANDFMT_USHORT: loop(unsigned short, float); break;
case IM_BANDFMT_SHORT: loop(signed short, float); break;
case IM_BANDFMT_UINT: loop(unsigned int, float); break;
case IM_BANDFMT_INT: loop(signed int, float); break;
case IM_BANDFMT_FLOAT: loop(float, float); break;
case IM_BANDFMT_DOUBLE: loop(double, double); break;
default:
assert( 0 );
}
return( 0 );
}
/* Log transform.
*/
int
im_logtra( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_logtra", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_logtra", "%s", _( "not non-complex" ) );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
break;
default:
assert( 0 );
}
/* Set demand hints.
*/
if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) )
return( -1 );
/* Generate!
*/
if( im_generate( out,
im_start_one, logtra_gen, im_stop_one, in, NULL ) )
return( -1 );
return( 0 );
}

249
libvips/arithmetic/im_max.c Normal file
View File

@ -0,0 +1,249 @@
/* @(#) Function to find the maximim of an image. Works for any
* @(#) image type. Returns a double.
* @(#)
* @(#) int im_max(in, max)
* @(#) IMAGE *in;
* @(#) double *max;
* @(#)
* @(#) Returns 0 on success and -1 on error
*
* Copyright: 1990, J. Cupitt
*
* Author: J. Cupitt
* Written on: 02/05/1990
* Modified on : 18/03/1991, N. Dessipris
* 7/7/93 JC
* - complex case fixed
* - im_incheck() call added
* 20/6/95 JC
* - now returns double
* - modernised a little
* - now returns max square amplitude rather than amplitude for complex
* 9/5/02 JC
* - partialed
* 3/4/02 JC
* - random wrong result for >1 thread :-( (thanks Joe)
* 15/10/07
* - oh, heh, seq->inf was not being set correctly, not that it mattered
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Per-call state.
*/
typedef struct _MaxInfo {
/* Parameters.
*/
IMAGE *in;
double *out;
/* Global max so far.
*/
double value;
int valid; /* zero means value is unset */
} MaxInfo;
/* Per thread state.
*/
typedef struct _Seq {
MaxInfo *inf;
double value;
int valid; /* zero means value is unset */
} Seq;
/* New sequence value.
*/
static void *
max_start( IMAGE *in, void *a, void *b )
{
MaxInfo *inf = (MaxInfo *) a;
Seq *seq = IM_NEW( NULL, Seq );
seq->inf = inf;
seq->valid = 0;
return( (void *) seq );
}
/* Merge the sequence value back into the per-call state.
*/
static int
max_stop( void *vseq, void *a, void *b )
{
Seq *seq = (Seq *) vseq;
MaxInfo *inf = (MaxInfo *) a;
if( seq->valid ) {
if( !inf->valid )
/* Just copy.
*/
inf->value = seq->value;
else
/* Merge.
*/
inf->value = IM_MAX( inf->value, seq->value );
inf->valid = 1;
}
im_free( seq );
return( 0 );
}
/* Loop over region, adding to seq.
*/
static int
max_scan( REGION *reg, void *vseq, void *a, void *b )
{
Seq *seq = (Seq *) vseq;
Rect *r = &reg->valid;
IMAGE *im = reg->im;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int nel = IM_REGION_N_ELEMENTS( reg );
int x, y;
double m;
#define loop(TYPE) { \
m = *((TYPE *) IM_REGION_ADDR( reg, le, to )); \
\
for( y = to; y < bo; y++ ) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < nel; x++ ) { \
double v = p[x]; \
\
if( v > m ) \
m = v; \
} \
} \
}
#define complex_loop(TYPE) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, to ); \
double real = p[0]; \
double imag = p[1]; \
\
m = real * real + imag * imag; \
\
for( y = to; y < bo; y++ ) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < nel * 2; x += 2 ) { \
double mod; \
\
real = p[x]; \
imag = p[x + 1]; \
mod = real * real + imag * imag; \
\
if( mod > m ) \
m = mod; \
} \
} \
}
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop( unsigned char ); break;
case IM_BANDFMT_CHAR: loop( signed char ); break;
case IM_BANDFMT_USHORT: loop( unsigned short ); break;
case IM_BANDFMT_SHORT: loop( signed short ); break;
case IM_BANDFMT_UINT: loop( unsigned int ); break;
case IM_BANDFMT_INT: loop( signed int ); break;
case IM_BANDFMT_FLOAT: loop( float ); break;
case IM_BANDFMT_DOUBLE: loop( double ); break;
case IM_BANDFMT_COMPLEX: complex_loop( float ); break;
case IM_BANDFMT_DPCOMPLEX: complex_loop( double ); break;
default:
assert( 0 );
}
if( seq->valid ) {
seq->value = IM_MAX( seq->value, m );
}
else {
seq->value = m;
seq->valid = 1;
}
#ifdef DEBUG
printf( "im_max: left = %d, top = %d, width = %d, height = %d\n",
r->left, r->top, r->width, r->height );
printf( " (max = %g)\n", seq->value );
#endif /*DEBUG*/
return( 0 );
}
int
im_max( IMAGE *in, double *out )
{
MaxInfo inf;
inf.in = in;
inf.out = out;
inf.valid = 0;
if( im_pincheck( in ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_max", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iterate( in, max_start, max_scan, max_stop, &inf, NULL ) )
return( -1 );
*out = inf.value;
return( 0 );
}

View File

@ -0,0 +1,151 @@
/* @(#) Function to find the maximum of an image. Works for any
* @(#) image type. Returns a double and the location of max.
* @(#)
* @(#) Function im_maxpos() assumes that input
* @(#) is either memory mapped or in a buffer.
* @(#)
* @(#) int im_maxpos(in, xpos, ypos, max)
* @(#) IMAGE *in;
* @(#) int *xpos, *ypos;
* @(#) double *max;
* @(#)
* @(#) Returns 0 on success and -1 on error
*
* Copyright: 1990, J. Cupitt
*
* Author: J. Cupitt
* Written on: 02/05/1990
* Modified on : 18/03/1991, N. Dessipris
* 23/11/92: J.Cupitt - correct result for more than 1 band now.
* 23/7/93 JC
* - im_incheck() call added
* 20/6/95 JC
* - now returns double for value, like im_max()
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Useful: Call a macro with the name, type pairs for all VIPS functions.
*/
#define im_for_all_types() \
case IM_BANDFMT_UCHAR: loop(unsigned char); break; \
case IM_BANDFMT_CHAR: loop(signed char); break; \
case IM_BANDFMT_USHORT: loop(unsigned short); break; \
case IM_BANDFMT_SHORT: loop(signed short); break; \
case IM_BANDFMT_UINT: loop(unsigned int); break; \
case IM_BANDFMT_INT: loop(signed int); break; \
case IM_BANDFMT_FLOAT: loop(float); break; \
case IM_BANDFMT_DOUBLE: loop(double); break; \
case IM_BANDFMT_COMPLEX: loopcmplx(float); break; \
case IM_BANDFMT_DPCOMPLEX: loopcmplx(double); break;
/* Find the position of the maximum of an image. Take any format, returns a
* float and its position.
*/
int
im_maxpos( IMAGE *in, int *xpos, int *ypos, double *out )
{
double m;
int xp=0, yp=0;
int os;
/* Check our args. */
if( im_incheck( in ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_maxpos", "%s", _( "not uncoded" ) );
return( -1 );
}
/* What type? First define the loop we want to perform for all types. */
#define loop(TYPE) \
{ TYPE *p = (TYPE *) in->data; \
int x, y; \
m = (double) *p; \
\
for ( y=0; y<in->Ysize; y++ ) \
for ( x=0; x<os; x++ ) {\
if( (double) *p > m ) {\
m = (double) *p; \
xp = x; yp = y; \
}\
p++ ;\
}\
}
#define loopcmplx(TYPE) \
{ TYPE *p = (TYPE *) in->data; \
double re=(double)*p;\
double im=(double)*(p+1);\
double mod = re * re + im * im;\
int x, y; \
m = mod; \
\
for ( y=0; y<in->Ysize; y++ ) \
for ( x=0; x<os; x++ ) {\
re = (double)*p++; im = (double)*p++; \
mod = re * re + im * im; \
if( mod > m ) {\
m = mod; \
xp = x; yp = y; \
}\
}\
}
/* Now generate code for all types. */
os = in->Xsize * in->Bands;
switch( in->BandFmt ) {
im_for_all_types();
default: {
assert( 0 );
return( -1 );
}
}
/* Return maxima and position of maxima. Nasty: we divide the xpos by
* the number of bands to get the position in pixels.
*/
*out = m;
*xpos = xp / in->Bands;
*ypos = yp;
return( 0 );
}

View File

@ -0,0 +1,201 @@
/* @(#) Function to find the maximum of an image. Returns coords and value at
* @(#) double precision. In the event of a draw, returns average of all
* @(#) drawing coords, and interpolated value at that position.
* @(#)
* @(#) int im_maxpos_avg(
* @(#) IMAGE *im,
* @(#) double *xpos,
* @(#) double *ypos,
* @(#) double *out
* @(#) );
* @(#)
*
* Copyright: 2006, The Nottingham Trent University
* Copyright: 2006, Tom Vajzovic
*
* Author: Tom Vajzovic
*
* Written on: 2006-09-25
* 15/10/07 JC
* - changed spelling of occurrences
* - check for !occurrences before using val
* - renamed avg as sum, a bit clearer
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/** HEADERS **/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <vips/intl.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC */
/** LOCAL TYPES **/
typedef struct {
double x_sum;
double y_sum;
double val;
unsigned int occurrences;
} pos_avg_t;
/** LOCAL FUNCTIONS DECLARATIONS **/
static void *maxpos_avg_start( IMAGE *im , void *, void * );
static int maxpos_avg_scan( REGION *reg, void *seq, void *, void * );
static int maxpos_avg_stop( void *seq, void *, void * );
/** EXPORTED FUNCTION **/
int im_maxpos_avg( IMAGE *im, double *xpos, double *ypos, double *out ){
#define FUNCTION_NAME "im_maxpos_avg"
pos_avg_t master= { 0.0, 0.0, 0.0, 0 };
if( im_pincheck( im ) )
return -1;
if( im-> Coding ){
im_error( FUNCTION_NAME, "%s", _("uncoded images only") );
return -1;
}
if( !( im_isint( im ) || im_isfloat( im ) ) ){
im_error( FUNCTION_NAME, "%s", _("scalar images only") );
return -1;
}
if( 1 != im-> Bands ){
im_error( FUNCTION_NAME, "%s", _("single band images only") );
return -1;
}
if( ! xpos || ! ypos || ! out ){
im_error( FUNCTION_NAME, "%s", _("invalid argument") );
return -1;
}
if( im_iterate( im, maxpos_avg_start, maxpos_avg_scan, maxpos_avg_stop, &master, NULL ) )
return -1;
*xpos= master. x_sum / master. occurrences;
*ypos= master. y_sum / master. occurrences;
return im_point_bilinear( im, *xpos, *ypos, 0, out );
#undef FUNCTION_NAME
}
static void *maxpos_avg_start( IMAGE *im, void *a, void *b ){
pos_avg_t *seq;
seq= IM_NEW( NULL, pos_avg_t );
if( ! seq )
return NULL;
seq-> x_sum= 0.0;
seq-> y_sum= 0.0;
seq-> val= 0.0;
seq-> occurrences= 0;
return (void *) seq;
}
/* should be void (always returns 0) */
static int maxpos_avg_scan( REGION *reg, void *vseq, void *a, void *b ) {
pos_avg_t *seq= (pos_avg_t *) vseq;
const int right= reg-> valid. left + reg-> valid. width;
const int bottom= reg-> valid. top + reg-> valid. height;
int x;
int y;
#define LOOPS(type){ \
type *read= (type*) IM_REGION_ADDR( reg, reg-> valid. left, reg-> valid. top ) - reg-> valid. left; \
size_t skip= IM_REGION_LSKIP( reg ) / sizeof( type ); \
\
for( y= reg-> valid. top; y < bottom; ++y, read+= skip ) \
for( x= reg-> valid. left; x < right; ++x ) \
if( !seq-> occurrences || \
read[x] > seq-> val ){ \
seq-> val= read[x]; \
seq-> x_sum= x; \
seq-> y_sum= y; \
seq-> occurrences= 1; \
} \
else if( read[x] == seq-> val ){ \
seq-> x_sum+= x; \
seq-> y_sum+= y; \
++ (seq-> occurrences); \
} \
}
switch( reg-> im-> BandFmt ){
case IM_BANDFMT_CHAR: LOOPS( gint8 ) break;
case IM_BANDFMT_UCHAR: LOOPS( guint8 ) break;
case IM_BANDFMT_SHORT: LOOPS( gint16 ) break;
case IM_BANDFMT_USHORT: LOOPS( guint16 ) break;
case IM_BANDFMT_INT: LOOPS( gint32 ) break;
case IM_BANDFMT_UINT: LOOPS( guint32 ) break;
case IM_BANDFMT_FLOAT: LOOPS( float ) break;
case IM_BANDFMT_DOUBLE: LOOPS( double ) break;
}
return 0;
#undef LOOPS
}
/* should be void (always returns 0) */
static int maxpos_avg_stop( void *vseq, void *a, void *b ) {
pos_avg_t *seq = (pos_avg_t *) vseq;
pos_avg_t *master = (pos_avg_t *) a;
if( !master->occurrences ||
seq-> val > master-> val ){
master-> val= seq-> val;
master-> x_sum= seq-> x_sum;
master-> y_sum= seq-> y_sum;
master-> occurrences= seq-> occurrences;
}
else if( seq-> val == master-> val ){
master-> x_sum+= seq-> x_sum;
master-> y_sum+= seq-> y_sum;
master-> occurrences+= seq-> occurrences;
}
im_free( seq );
return 0;
}

View File

@ -0,0 +1,470 @@
/* @(#) Find the coordinates and values of the n maxima of an image.
* @(#)
* @(#) int im_maxpos_vec(
* @(#) IMAGE *im,
* @(#) int *xpos,
* @(#) int *ypos,
* @(#) double *maxima,
* @(#) int n
* @(#) );
* @(#)
* @(#) Find the coordinates and values of the n minima of an image.
* @(#)
* @(#) int im_minpos_vec(
* @(#) IMAGE *im,
* @(#) int *xpos,
* @(#) int *ypos,
* @(#) double *minima,
* @(#) int n
* @(#) );
* @(#)
*
* Copyright: 2006, The Nottingham Trent University
* Copyright: 2006, Tom Vajzovic
*
* Author: Tom Vajzovic
*
* Written on: 2006-09-01
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/** HEADERS **/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <vips/intl.h>
#include <stdlib.h>
#include <float.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC */
/** TYPE DEFINITIONS **/
typedef struct {
int *xs;
int *ys;
double *vals;
int *ptrs;
int start;
} maxpos_list;
/** LOCAL FUNCTIONS DECLARATIONS **/
static maxpos_list *maxpos_list_alloc( int n );
static void maxpos_list_free( maxpos_list *list );
static void maxpos_list_init( maxpos_list *list, int n );
static void *maxpos_vec_start( IMAGE *unrequired, void *, void * );
static int maxpos_vec_scan( REGION *reg, void *seq, void *, void * );
static void add_to_maxpos_list( maxpos_list *list, int x, int y, double val );
static int maxpos_vec_stop( void *seq, void *, void * );
static void minpos_list_init( maxpos_list *list, int n );
static void *minpos_vec_start( IMAGE *unrequired, void *, void * );
static int minpos_vec_scan( REGION *reg, void *seq, void *, void * );
static void add_to_minpos_list( maxpos_list *list, int x, int y, double val );
static int minpos_vec_stop( void *seq, void *, void * );
/** EXPORTED FUNCTIONS **/
int im_maxpos_vec( IMAGE *im, int *xpos, int *ypos, double *maxima, int n ){
#define FUNCTION_NAME "im_maxpos_vec"
/* number of sequences used is beyond my control at this level, but I note that */
/* efficiency decreases as more sequences are used - speed may still increase */
int result;
int *pointers= im_malloc( NULL, n * sizeof( int* ) );
maxpos_list master_list= { xpos, ypos, maxima, pointers, 0 };
if( im_pincheck( im ) )
return -1;
if( !pointers )
return -1;
if( ! ( im_isint( im ) || im_isfloat( im ) ) ){
im_error( FUNCTION_NAME, "%s", _( "scalar images only" ) );
return -1;
}
if( 1 != im-> Bands ){
im_error( FUNCTION_NAME, "%s", _( "single band images only" ) );
return -1;
}
if( IM_CODING_NONE != im-> Coding ){
im_error( FUNCTION_NAME, "%s", _( "uncoded images only" ) );
return -1;
}
if( ! xpos || ! ypos || ! maxima || n < 1 ){
im_error( FUNCTION_NAME, "%s", _( "invalid argument" ) );
return -1;
}
maxpos_list_init( &master_list, n );
result= im_iterate( im, maxpos_vec_start, maxpos_vec_scan, maxpos_vec_stop, &n, &master_list );
im_free( pointers );
return result;
#undef FUNCTION_NAME
}
int im_minpos_vec( IMAGE *im, int *xpos, int *ypos, double *minima, int n ){
#define FUNCTION_NAME "im_minpos_vec"
/* number of sequences used is beyond my control at this level, but I note that */
/* effeciency decreases as more sequences are used - speed may still increase */
int result;
int *pointers= im_malloc( NULL, n * sizeof( int* ) );
maxpos_list master_list= { xpos, ypos, minima, pointers, 0 };
if( im_pincheck( im ) )
return -1;
if( !pointers )
return -1;
if( ! ( im_isint( im ) || im_isfloat( im ) ) ){
im_error( FUNCTION_NAME, "%s", _( "scalar images only" ) );
return -1;
}
if( 1 != im-> Bands ){
im_error( FUNCTION_NAME, "%s", _( "single band images only" ) );
return -1;
}
if( IM_CODING_NONE != im-> Coding ){
im_error( FUNCTION_NAME, "%s", _( "uncoded images only" ) );
return -1;
}
if( ! xpos || ! ypos || ! minima || n < 1 ){
im_error( FUNCTION_NAME, "%s", _( "invalid argument" ) );
return -1;
}
minpos_list_init( &master_list, n );
result= im_iterate( im, minpos_vec_start, minpos_vec_scan, minpos_vec_stop, &n, &master_list );
im_free( pointers );
return result;
#undef FUNCTION_NAME
}
/** LOCAL FUNCTION DEFINITIONS **/
static maxpos_list *maxpos_list_alloc( int n ){
maxpos_list *list= im_malloc( NULL, sizeof( maxpos_list ) );
if( ! list )
return NULL;
list-> xs= im_malloc( NULL, 3 * n * sizeof( int ) );
list-> vals= im_malloc( NULL, n * sizeof( double ) );
if( ! list-> xs || ! list-> vals ){
im_free( list-> xs );
im_free( list-> vals );
im_free( list );
return NULL;
}
list-> ys= list-> xs + n;
list-> ptrs= list-> ys + n;
return list;
}
static void maxpos_list_free( maxpos_list *list ){
im_free( list-> xs );
im_free( list-> vals );
im_free( list );
}
static void maxpos_list_init( maxpos_list *list, int n ){
int i;
for( i= 0; i < n; ++i ){
list-> xs[ i ]= 0;
list-> ys[ i ]= 0;
list-> vals[ i ]= 0;
list-> ptrs[ i ]= i + 1;
}
list-> ptrs[ n - 1 ]= -1;
list-> start= 0;
}
static void *maxpos_vec_start( IMAGE *unrequired, void *a, void *b ){
int *n = (int *) a;
maxpos_list *list= maxpos_list_alloc( *n );
if( ! list )
return NULL;
maxpos_list_init( list, *n );
return list;
}
static int maxpos_vec_scan( REGION *reg, void *seq, void *a, void *b ){
maxpos_list *list = (maxpos_list *) seq;
#define MAXPOS_VEC_SCAN( type ){ \
\
int y= reg-> valid. top; \
int x; \
int ymax= y + reg-> valid. height; \
int xmax= reg-> valid. left + reg-> valid. width; \
\
type *row= (type*)IM_REGION_ADDR( reg, reg-> valid. left, y ) - reg-> valid. left; \
size_t skip= IM_REGION_LSKIP( reg ) / sizeof( type ); \
\
for( ; y < ymax; ++y, row+= skip ) \
for( x= reg-> valid. left; x < xmax; ++x ) \
if( row[ x ] > list-> vals[ list-> start ] ) \
add_to_maxpos_list( list, x, y, row[ x ] ); \
}
switch( reg-> im-> BandFmt ){
case IM_BANDFMT_UCHAR: MAXPOS_VEC_SCAN( guint8 ) break;
case IM_BANDFMT_CHAR: MAXPOS_VEC_SCAN( gint8 ) break;
case IM_BANDFMT_USHORT: MAXPOS_VEC_SCAN( guint16 ) break;
case IM_BANDFMT_SHORT: MAXPOS_VEC_SCAN( gint16 ) break;
case IM_BANDFMT_UINT: MAXPOS_VEC_SCAN( guint32 ) break;
case IM_BANDFMT_INT: MAXPOS_VEC_SCAN( gint32 ) break;
case IM_BANDFMT_FLOAT: MAXPOS_VEC_SCAN( float ) break;
case IM_BANDFMT_DOUBLE: MAXPOS_VEC_SCAN( double ) break;
}
#undef MAXPOS_VEC_SCAN
return 0;
}
static void add_to_maxpos_list( maxpos_list *list, int x, int y, double val ){
int pointer= list-> start;
while( -1 != list-> ptrs[ pointer ] && val > list-> vals[ list-> ptrs[ pointer ] ] )
pointer= list-> ptrs[ pointer ];
list-> xs[ list-> start ]= x;
list-> ys[ list-> start ]= y;
list-> vals[ list-> start ]= val;
if( list-> start != pointer ){
/* we are adding mid-chain not at the very bottom */
int second= list-> ptrs[ list-> start ];
list-> ptrs[ list-> start ]= list-> ptrs[ pointer ];
list-> ptrs[ pointer ]= list-> start;
list-> start= second;
}
}
static int maxpos_vec_stop( void *seq, void *a, void *b ){
/* reverse list */
maxpos_list *list = (maxpos_list *) seq;
maxpos_list *master_list = (maxpos_list *) b;
int prev= -1;
int pointer= list-> start;
while( -1 != list-> ptrs[ pointer ] ){
int next= list-> ptrs[ pointer ];
list-> ptrs[ pointer ]= prev;
prev= pointer;
pointer= next;
}
list-> ptrs[ pointer ]= prev;
list-> start= pointer;
/* add to main list */
for( ; -1 != pointer; pointer= list-> ptrs[ pointer ] )
/* loop over all the ones found in this sequence */
if( list-> vals[ pointer ] > master_list-> vals[ master_list-> start ] )
add_to_maxpos_list( master_list, list-> xs[ pointer ], list-> ys[ pointer ], list-> vals[ pointer ] );
else
break;
/* since we are now high->low, if this one isn't big enough, none of the rest are */
maxpos_list_free( list );
return 0;
}
static void minpos_list_init( maxpos_list *list, int n ){
int i;
for( i= 0; i < n; ++i ){
list-> xs[ i ]= 0;
list-> ys[ i ]= 0;
list-> vals[ i ]= DBL_MAX;
list-> ptrs[ i ]= i + 1;
}
list-> ptrs[ n - 1 ]= -1;
list-> start= 0;
}
static void *minpos_vec_start( IMAGE *unrequired, void *a, void *b ){
int *n = (int *) a;
maxpos_list *list= maxpos_list_alloc( *n );
if( ! list )
return NULL;
minpos_list_init( list, *n );
return list;
}
static int minpos_vec_scan( REGION *reg, void *seq, void *a, void *b ){
maxpos_list *list = (maxpos_list *) seq;
#define MINPOS_VEC_SCAN( type ){ \
\
int y= reg-> valid. top; \
int x; \
int ymax= y + reg-> valid. height; \
int xmax= reg-> valid. left + reg-> valid. width; \
\
type *row= (type*)IM_REGION_ADDR( reg, reg-> valid. left, y ) - reg-> valid. left; \
size_t skip= IM_REGION_LSKIP( reg ) / sizeof( type ); \
\
for( ; y < ymax; ++y, row+= skip ) \
for( x= reg-> valid. left; x < xmax; ++x ) \
if( row[ x ] < list-> vals[ list-> start ] ) \
add_to_minpos_list( list, x, y, row[ x ] ); \
}
switch( reg-> im-> BandFmt ){
case IM_BANDFMT_UCHAR: MINPOS_VEC_SCAN( guint8 ) break;
case IM_BANDFMT_CHAR: MINPOS_VEC_SCAN( gint8 ) break;
case IM_BANDFMT_USHORT: MINPOS_VEC_SCAN( guint16 ) break;
case IM_BANDFMT_SHORT: MINPOS_VEC_SCAN( gint16 ) break;
case IM_BANDFMT_UINT: MINPOS_VEC_SCAN( guint32 ) break;
case IM_BANDFMT_INT: MINPOS_VEC_SCAN( gint32 ) break;
case IM_BANDFMT_FLOAT: MINPOS_VEC_SCAN( float ) break;
case IM_BANDFMT_DOUBLE: MINPOS_VEC_SCAN( double ) break;
}
#undef MINPOS_VEC_SCAN
return 0;
}
static void add_to_minpos_list( maxpos_list *list, int x, int y, double val ){
int pointer= list-> start;
while( -1 != list-> ptrs[ pointer ] && val < list-> vals[ list-> ptrs[ pointer ] ] )
pointer= list-> ptrs[ pointer ];
list-> xs[ list-> start ]= x;
list-> ys[ list-> start ]= y;
list-> vals[ list-> start ]= val;
if( list-> start != pointer ){
/* we are adding mid-chain not at the very bottom */
int second= list-> ptrs[ list-> start ];
list-> ptrs[ list-> start ]= list-> ptrs[ pointer ];
list-> ptrs[ pointer ]= list-> start;
list-> start= second;
}
}
static int minpos_vec_stop( void *seq, void *a, void *b ){
/* reverse list */
maxpos_list *list = (maxpos_list *) seq;
maxpos_list *master_list = (maxpos_list *) b;
int prev= -1;
int pointer= list-> start;
while( -1 != list-> ptrs[ pointer ] ){
int next= list-> ptrs[ pointer ];
list-> ptrs[ pointer ]= prev;
prev= pointer;
pointer= next;
}
list-> ptrs[ pointer ]= prev;
list-> start= pointer;
/* add to main list */
for( ; -1 != pointer; pointer= list-> ptrs[ pointer ] )
/* loop over all the ones found in this sequence */
if( list-> vals[ pointer ] < master_list-> vals[ master_list-> start ] )
add_to_minpos_list( master_list, list-> xs[ pointer ], list-> ys[ pointer ], list-> vals[ pointer ] );
else
break;
/* since we are now high->low, if this one isn't big enough, none of the rest are */
maxpos_list_free( list );
return 0;
}

View File

@ -0,0 +1,210 @@
/* Analyse a grid of colour patches, producing a DOUBLEMASK of averages.
* Pass an IMAGE, an IMAGE_BOX, the number of horizontal and vertical
* patches, an array giving the numbers of the patches to measure (patches are
* numbered left-to-right, top-to-bottom) and the name we should give the
* output mask. Return a DOUBLEMASK in which rows are patches and columns are
* bands.
*
* Example: 6 band image of 4x2 block of colour patches.
*
* +---+---+---+---+
* | 1 | 2 | 3 | 4 |
* +---+---+---+---+
* | 5 | 6 | 7 | 8 |
* +---+---+---+---+
*
* Then call im_measure( im, box, 4, 2, { 2, 4 }, 2, "fred" ) makes a mask
* "fred" which has 6 columns, two rows. The first row contains the averages
* for patch 2, the second for patch 4.
*
* Modified:
* 19/8/94 JC
* - now uses doubles for addressing
* - could miss by up to h pixels previously!
* - ANSIfied
* - now issues warning if any deviations are greater than 20% of the
* mean
* 31/10/95 JC
* - more careful about warning for averages <0, or averages near zero
* - can get these cases with im_measure() of IM_TYPE_LAB images
* 28/10/02 JC
* - number bands from zero in error messages
* 7/7/04
* - works on labq
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Measure into array.
*/
static int
measure_patches( IMAGE *im, double *coeff, IMAGE_BOX *box,
int h, int v, int *sel, int nsel )
{
IMAGE *tmp;
int patch;
IMAGE_BOX sub;
int i, j;
int m, n;
double avg, dev;
/* How large are the patches we are to measure?
*/
double pw = (double) box->xsize / (double) h;
double ph = (double) box->ysize / (double) v;
/* Set up sub to be the size we need for a patch.
*/
sub.xsize = (pw + 1) / 2;
sub.ysize = (ph + 1) / 2;
/* Loop through sel, picking out areas to measure.
*/
for( j = 0, patch = 0; patch < nsel; patch++ ) {
/* Sanity check. Is the patch number sensible?
*/
if( sel[patch] <= 0 || sel[patch] > h*v ) {
im_error( "im_measure",
_( "patch %d is out of range" ),
sel[patch] );
return( 1 );
}
/* Patch coordinates.
*/
m = (sel[patch] - 1) % h;
n = (sel[patch] - 1) / h;
/* Move sub to correct position.
*/
sub.xstart = box->xstart + m*pw + (pw + 2)/4;
sub.ystart = box->ystart + n*ph + (ph + 2)/4;
/* Loop through bands.
*/
for( i = 0; i < im->Bands; i++, j++ ) {
/* Make temp buffer to extract to.
*/
if( !(tmp = im_open( "patch", "t" )) )
return( -1 );
/* Extract and measure.
*/
sub.chsel = i;
if( im_extract( im, tmp, &sub ) ||
im_avg( tmp, &avg ) ||
im_deviate( tmp, &dev ) ) {
im_close( tmp );
return( -1 );
}
im_close( tmp );
/* Is the deviation large compared with the average?
* This could be a clue that our parameters have
* caused us to miss the patch. Look out for averages
* <0, or averages near zero (can get these if use
* im_measure() on IM_TYPE_LAB images).
*/
if( dev*5 > fabs( avg ) && fabs( avg ) > 3 )
im_warn( "im_measure",
_( "patch %d, band %d: "
"avg = %g, sdev = %g" ),
patch, i, avg, dev );
/* Save results.
*/
coeff[j] = avg;
}
}
return( 0 );
}
/* Measure up image.
*/
DOUBLEMASK *
im_measure( IMAGE *im, IMAGE_BOX *box, int h, int v,
int *sel, int nsel, const char *name )
{
DOUBLEMASK *mask;
/* Check input image.
*/
if( im->Coding == IM_CODING_LABQ ) {
IMAGE *t1;
if( !(t1 = im_open( "measure-temp", "p" )) )
return( NULL );
if( im_LabQ2Lab( im, t1 ) ||
!(mask = im_measure( t1,
box, h, v, sel, nsel, name )) ) {
im_close( t1 );
return( NULL );
}
im_close( t1 );
return( mask );
}
if( im->Coding != IM_CODING_NONE ) {
im_error( "im_measure", "%s", _( "not uncoded" ) );
return( NULL );
}
if( im_iscomplex( im ) ) {
im_error( "im_measure", "%s", _( "bad input type" ) );
return( NULL );
}
/* What size mask do we need?
*/
if( !(mask = im_create_dmask( name, im->Bands, nsel )) )
return( NULL );
/* Perform measure and return.
*/
if( measure_patches( im, mask->coeff, box, h, v, sel, nsel ) ) {
im_free_dmask( mask );
return( NULL );
}
return( mask );
}

246
libvips/arithmetic/im_min.c Normal file
View File

@ -0,0 +1,246 @@
/* @(#) Function to find the minimum of an image. Works for any
* @(#) image type. Returns a double.
* @(#)
* @(#) int im_min(in, min)
* @(#) IMAGE *in;
* @(#) double *min;
* @(#)
* @(#) Returns 0 on success and -1 on error
*
* Copyright: 1990, J. Cupitt
*
* Author: J. Cupitt
* Written on: 02/05/1990
* Modified on : 18/03/1991, N. Dessipris
* 7/7/93 JC
* - complex case fixed
* - im_incheck() call added
* 20/6/95 JC
* - now returns double
* - modernised a little
* - now returns min square amplitude rather than amplitude for complex
* 9/5/02 JC
* - partialed, based in im_max()
* 3/4/02 JC
* - random wrong result for >1 thread :-( (thanks Joe)
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Per-call state.
*/
typedef struct _MinInfo {
/* Parameters.
*/
IMAGE *in;
double *out;
/* Global min so far.
*/
double value;
int valid; /* zero means value is unset */
} MinInfo;
/* Per thread state.
*/
typedef struct _Seq {
MinInfo *inf;
double value;
int valid; /* zero means value is unset */
} Seq;
/* New sequence value.
*/
static void *
start_fn( IMAGE *im, void *a, void *b )
{
MinInfo *inf = (MinInfo *) a;
Seq *seq = IM_NEW( NULL, Seq );
seq->inf = inf;
seq->valid = 0;
return( seq );
}
/* Merge the sequence value back into the per-call state.
*/
static int
stop_fn( void *vseq, void *a, void *b )
{
Seq *seq = (Seq *) vseq;
MinInfo *inf = (MinInfo *) a;
if( seq->valid ) {
if( !inf->valid )
/* Just copy.
*/
inf->value = seq->value;
else
/* Merge.
*/
inf->value = IM_MIN( inf->value, seq->value );
inf->valid = 1;
}
im_free( seq );
return( 0 );
}
/* Loop over region, adding to seq.
*/
static int
scan_fn( REGION *reg, void *vseq, void *a, void *b )
{
Seq *seq = (Seq *) vseq;
Rect *r = &reg->valid;
IMAGE *im = reg->im;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int nel = IM_REGION_N_ELEMENTS( reg );
int x, y;
double m;
#ifdef DEBUG
printf( "im_min: left = %d, top = %d, width = %d, height = %d\n",
r->left, r->top, r->width, r->height );
#endif /*DEBUG*/
#define loop(TYPE) { \
m = *((TYPE *) IM_REGION_ADDR( reg, le, to )); \
\
for( y = to; y < bo; y++ ) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < nel; x++ ) { \
double v = p[x]; \
\
if( v < m ) \
m = v; \
} \
} \
}
#define complex_loop(TYPE) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, to ); \
double real = p[0]; \
double imag = p[1]; \
\
m = real * real + imag * imag; \
\
for( y = to; y < bo; y++ ) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < nel * 2; x += 2 ) { \
double mod; \
\
real = p[x]; \
imag = p[x + 1]; \
mod = real * real + imag * imag; \
\
if( mod < m ) \
m = mod; \
} \
} \
}
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop( unsigned char ); break;
case IM_BANDFMT_CHAR: loop( signed char ); break;
case IM_BANDFMT_USHORT: loop( unsigned short ); break;
case IM_BANDFMT_SHORT: loop( signed short ); break;
case IM_BANDFMT_UINT: loop( unsigned int ); break;
case IM_BANDFMT_INT: loop( signed int ); break;
case IM_BANDFMT_FLOAT: loop( float ); break;
case IM_BANDFMT_DOUBLE: loop( double ); break;
case IM_BANDFMT_COMPLEX: complex_loop( float ); break;
case IM_BANDFMT_DPCOMPLEX: complex_loop( double ); break;
default:
assert( 0 );
}
if( seq->valid ) {
seq->value = IM_MIN( seq->value, m );
}
else {
seq->value = m;
seq->valid = 1;
}
return( 0 );
}
int
im_min( IMAGE *in, double *out )
{
MinInfo inf;
inf.in = in;
inf.out = out;
inf.valid = 0;
if( im_pincheck( in ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_min", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iterate( in, start_fn, scan_fn, stop_fn, &inf, NULL ) )
return( -1 );
*out = inf.value;
return( 0 );
}

View File

@ -0,0 +1,143 @@
/* @(#) Function to find the minimim of an image. Works for any
* @(#) image type. Returns a double and the location of min
* @(#)
* @(#) Function im_minpos() assumes that input
* @(#) is either memory mapped or in a buffer.
* @(#)
* @(#) int im_minpos(in, xpos, ypos, out)
* @(#) IMAGE *in;
* @(#) int *xpos, *ypos;
* @(#) double *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
*
* Copyright: 1990, J. Cupitt
*
* Author: J. Cupitt
* Written on: 02/05/1990
* Modified on : 18/03/1991, N. Dessipris
* 23/11/92 JC
* - correct result for more than 1 band now.
* 23/7/93 JC
* - im_incheck() added
* 20/6/95 JC
* - now returns double for value, like im_max()
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Find the minimum of an image. Take any format, returns a double. */
int
im_minpos( IMAGE *in, int *xpos, int *ypos, double *out )
{
double m;
int xp=0, yp=0;
int os;
/* Check our args. */
if( im_incheck( in ) )
return( -1 );
if( in->Coding != IM_CODING_NONE )
{
im_error("im_minpos", "%s", _("input must be uncoded"));
return( -1 );
}
/* What type? First define the loop we want to perform for all types. */
#define loop(TYPE) \
{ TYPE *p = (TYPE *) in->data; \
int x, y; \
m = (double) *p; \
\
for ( y=0; y<in->Ysize; y++ ) \
for ( x=0; x<os; x++ ) {\
if( (double) *p < m ) {\
m = (double) *p; \
xp = x; yp = y; \
}\
p++ ;\
}\
}
#define loopcmplx(TYPE) \
{ TYPE *p = (TYPE *) in->data; \
double re=(double)*p;\
double im=(double)*(p+1);\
double mod = re * re + im * im;\
int x, y; \
m = mod; \
\
for ( y=0; y<in->Ysize; y++ ) \
for ( x=0; x<os; x++ ) {\
re = (double)*p++; im = (double)*p++; \
mod = re * re + im * im; \
if( mod < m ) {\
m = mod; \
xp = x; yp = y; \
}\
}\
}
/* Now generate code for all types. */
os = in->Xsize * in->Bands;
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR: loop(unsigned char); break;
case IM_BANDFMT_CHAR: loop(signed char); break;
case IM_BANDFMT_USHORT: loop(unsigned short); break;
case IM_BANDFMT_SHORT: loop(signed short); break;
case IM_BANDFMT_UINT: loop(unsigned int); break;
case IM_BANDFMT_INT: loop(signed int); break;
case IM_BANDFMT_FLOAT: loop(float); break;
case IM_BANDFMT_DOUBLE: loop(double); break;
case IM_BANDFMT_COMPLEX: loopcmplx(float); break;
case IM_BANDFMT_DPCOMPLEX: loopcmplx(double); break;
default:
assert( 0 );
}
/* Take out bands on x.
*/
*out = m;
*xpos = xp / in->Bands;
*ypos = yp;
return( 0 );
}

View File

@ -0,0 +1,262 @@
/* @(#) Multiply two images
* @(#) Images must have the same no of bands and can be of any type
* @(#) No check for overflow is carried out.
* @(#)
* @(#) int
* @(#) im_multiply(in1, in2, out)
* @(#) IMAGE *in1, *in2, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 29/4/93 JC
* - now works for partial images
* 1/7/93 JC
* - adapted for partial v2
* - ANSIfied
* 19/10/93 JC
* - coredump-inducing bug in complex*complex fixed
* 13/12/93
* - char*short bug fixed
* 12/6/95 JC
* - new im_add adapted to make new im_multiply
* 27/9/04
* - updated for 1 band $op n band image -> n band image case
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Swap two IMAGE pointers.
*/
#define SWAP(A,B) { \
IMAGE *t; \
t = (A); (A) = (B); (B) = t; \
}
/* Complex multiply.
*/
#define cloop(TYPE) \
{\
TYPE *p1 = (TYPE *) in[0];\
TYPE *p2 = (TYPE *) in[1];\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ ) {\
double x1 = p1[0];\
double y1 = p1[1];\
double x2 = p2[0];\
double y2 = p2[1];\
\
p1 += 2;\
p2 += 2;\
\
q[0] = x1 * x2 - y1 * y2;\
q[1] = x1 * y2 + x2 * y1;\
\
q += 2;\
}\
}
/* Real multiply.
*/
#define rloop(TYPE) \
{\
TYPE *p1 = (TYPE *) in[0];\
TYPE *p2 = (TYPE *) in[1];\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = p1[x] * p2[x];\
}
static void
multiply_buffer( PEL **in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Multiply all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR: rloop( signed char ); break;
case IM_BANDFMT_UCHAR: rloop( unsigned char ); break;
case IM_BANDFMT_SHORT: rloop( signed short ); break;
case IM_BANDFMT_USHORT: rloop( unsigned short ); break;
case IM_BANDFMT_INT: rloop( signed int ); break;
case IM_BANDFMT_UINT: rloop( unsigned int ); break;
case IM_BANDFMT_FLOAT:
#ifdef HAVE_LIBOIL
oil_multiply_f32( (float *) out,
(float *) in[0], (float *) in[1], sz );
#else /*!HAVE_LIBOIL*/
rloop( float );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: rloop( double ); break;
case IM_BANDFMT_COMPLEX: cloop( float ); break;
case IM_BANDFMT_DPCOMPLEX: cloop( double ); break;
default:
assert( 0 );
}
}
/* Save a bit of typing.
*/
#define UC IM_BANDFMT_UCHAR
#define C IM_BANDFMT_CHAR
#define US IM_BANDFMT_USHORT
#define S IM_BANDFMT_SHORT
#define UI IM_BANDFMT_UINT
#define I IM_BANDFMT_INT
#define F IM_BANDFMT_FLOAT
#define M IM_BANDFMT_COMPLEX
#define D IM_BANDFMT_DOUBLE
#define DM IM_BANDFMT_DPCOMPLEX
/* Type conversions for two integer inputs. Rules for float and complex
* encoded with ifs. We are sign and value preserving.
*/
static int iformat[6][6] = {
/* UC C US S UI I */
/* UC */ { US, S, UI, I, UI, I },
/* C */ { S, S, I, I, I, I },
/* US */ { UI, I, UI, I, UI, I },
/* S */ { I, I, I, I, I, I },
/* UI */ { UI, I, UI, I, UI, I },
/* I */ { I, I, I, I, I, I }
};
int
im_multiply( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
/* Basic checks.
*/
if( im_piocheck( in1, out ) || im_pincheck( in2 ) )
return( -1 );
if( in1->Xsize != in2->Xsize || in1->Ysize != in2->Ysize ) {
im_error( "im_multiply", "%s", _( "not same size" ) );
return( -1 );
}
if( in1->Bands != in2->Bands &&
(in1->Bands != 1 && in2->Bands != 1) ) {
im_error( "im_multiply",
"%s", _( "not same number of bands" ) );
return( -1 );
}
if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) {
im_error( "im_multiply", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_cp_descv( out, in1, in2, NULL ) )
return( -1 );
/* What number of bands will we write?
*/
out->Bands = IM_MAX( in1->Bands, in2->Bands );
/* Swap arguments to get the largest on the left.
*/
if( in1->Bbits < in2->Bbits )
SWAP( in1, in2 );
/* What output type will we write? int, float or complex.
*/
if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) {
/* Make sure we have complex on the left.
*/
if( !im_iscomplex( in1 ) )
SWAP( in1, in2 );
/* What kind of complex?
*/
if( in1->BandFmt == IM_BANDFMT_DPCOMPLEX )
/* Output will be DPCOMPLEX.
*/
out->BandFmt = IM_BANDFMT_DPCOMPLEX;
else
out->BandFmt = IM_BANDFMT_COMPLEX;
}
else if( im_isfloat( in1 ) || im_isfloat( in2 ) ) {
/* Make sure we have float on the left.
*/
if( !im_isfloat( in1 ) )
SWAP( in1, in2 );
/* What kind of float?
*/
if( in1->BandFmt == IM_BANDFMT_DOUBLE )
out->BandFmt = IM_BANDFMT_DOUBLE;
else
out->BandFmt = IM_BANDFMT_FLOAT;
}
else
/* Must be int+int = int.
*/
out->BandFmt = iformat[in2->BandFmt][in1->BandFmt];
/* And process!
*/
if( im__cast_and_call( in1, in2, out,
(im_wrapmany_fn) multiply_buffer, NULL ) )
return( -1 );
/* Success!
*/
return( 0 );
}

View File

@ -0,0 +1,127 @@
/* @(#) Find the value at (x,y) in given band of image.
* @(#) Use bilinear interpolation if x or y are non-integral.
* @(#)
* @(#) int im_maxpos_vec(
* @(#) IMAGE *im,
* @(#) double x,
* @(#) double y,
* @(#) int band,
* @(#) double *val
* @(#) );
* @(#)
*
* Copyright: 2006, The Nottingham Trent University
*
* Author: Tom Vajzovic
*
* Written on: 2006-09-26
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/** HEADERS **/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <vips/intl.h>
#include <vips/vips.h>
#include <vips/r_access.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC */
/** EXPORTED FUNCTION **/
int im_point_bilinear( IMAGE *im, double x, double y, int band, double *val ){
#define FUNCTION_NAME "im_point_bilinear"
double x_frac= x - (int) x;
double y_frac= y - (int) y;
Rect need= { x, y, ( x_frac ? 2 : 1 ), ( y_frac ? 2 : 1 ) };
REGION *reg;
if( im_pincheck( im ) )
return -1;
if( im-> Coding ){
im_error( FUNCTION_NAME, "%s", _("uncoded images only") );
return -1;
}
if( !( im_isint( im ) || im_isfloat( im ) ) ){
im_error( FUNCTION_NAME, "%s", _("scalar images only") );
return -1;
}
if( band >= im-> Bands || x < 0.0 || y < 0.0 || x > im-> Xsize || y > im-> Ysize ){
im_error( FUNCTION_NAME, "%s", _("coords outside image") );
return -1;
}
if( ! val ){
im_error( FUNCTION_NAME, "%s", _("invalid arguments") );
return -1;
}
reg= im_region_create( im );
if( ! reg || im_prepare( reg, &need ) )
return -1;
if( ! im_rect_includesrect( &reg-> valid, &need ) ){
im_error( FUNCTION_NAME, "%s", _("coords outside image") );
im_region_free( reg );
return -1;
}
if( x_frac )
if( y_frac )
*val= x_frac * y_frac * (double) IM_REGION_VALUE( reg, ((int)x + 1), ((int)y + 1), band )
+ x_frac * ( 1.0 - y_frac ) * (double) IM_REGION_VALUE( reg, ((int)x + 1), (int)y , band )
+ ( 1.0 - x_frac ) * y_frac * (double) IM_REGION_VALUE( reg, (int)x, ((int)y + 1), band )
+ ( 1.0 - x_frac ) * ( 1.0 - y_frac ) * (double) IM_REGION_VALUE( reg, (int)x, (int)y , band );
else
*val= x_frac * IM_REGION_VALUE( reg, ((int)x + 1), (int)y, band )
+ ( 1.0 - x_frac ) * IM_REGION_VALUE( reg, (int)x, (int)y, band );
else
if( y_frac )
*val= y_frac * IM_REGION_VALUE( reg, (int)x, ((int)y + 1), band )
+ ( 1.0 - y_frac ) * IM_REGION_VALUE( reg, (int)x, (int)y , band );
else
*val= IM_REGION_VALUE( reg, (int)x, (int)y, band );
im_region_free( reg );
return 0;
#undef FUNCTION_NAME
}

View File

@ -0,0 +1,235 @@
/* @(#) Finds the power of an image
* @(#) Function im_powtra() assumes that the imin file
* @(#) is either memory mapped or in a buffer.
* @(#) Output image pow(imin, exponent) depends on input
* @(#) If input is up to float, output is float
* @(#) else input is the same as output
* @(#) Works on any number of bands.
* @(#)
* @(#) int im_powtra( in, out, e )
* @(#) IMAGE *in, *out;
* @(#) double e;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 10/12/93 JC
* - now reports total number of x/0, rather than each one.
* 1/2/95 JC
* - rewritten for PIO with im_wrapone()
* - incorrect complex code removed
* - /0 reporting removed for ease of programming
* 15/4/97 JC
* - return( 0 ) missing, oops!
* 6/7/98 JC
* - _vec form added
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Parameters saved here.
*/
typedef struct {
int n;
double *e; /* Exponent value */
} PowtraInfo;
/* Define what we do for each band element type. Single constant.
*/
#define loop1(IN, OUT)\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < sz; x++ ) {\
double f = (double) p[x];\
\
if( f == 0.0 && e < 0.0 ) {\
/* Division by zero! Difficult to report tho'\
*/\
q[x] = 0.0;\
}\
else\
q[x] = pow( f, e );\
}\
}
/* Powtra a buffer.
*/
static int
powtra1_gen( PEL *in, PEL *out, int width, IMAGE *im, PowtraInfo *inf )
{
int sz = width * im->Bands;
double e = inf->e[0];
int x;
/* Powtra all non-complex input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop1(unsigned char, float); break;
case IM_BANDFMT_CHAR: loop1(signed char, float); break;
case IM_BANDFMT_USHORT: loop1(unsigned short, float); break;
case IM_BANDFMT_SHORT: loop1(signed short, float); break;
case IM_BANDFMT_UINT: loop1(unsigned int, float); break;
case IM_BANDFMT_INT: loop1(signed int, float); break;
case IM_BANDFMT_FLOAT: loop1(float, float); break;
case IM_BANDFMT_DOUBLE: loop1(double, double); break;
default:
assert( 0 );
}
return( 0 );
}
/* Define what we do for each band element type. One constant per band.
*/
#define loopn(IN, OUT)\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( i = 0, x = 0; x < width; x++ )\
for( k = 0; k < im->Bands; k++, i++ ) {\
double e = inf->e[k];\
double f = (double) p[i];\
\
if( f == 0.0 && e < 0.0 ) {\
q[i] = 0.0;\
}\
else\
q[i] = pow( f, e );\
}\
}
/* Powtra a buffer.
*/
static int
powtran_gen( PEL *in, PEL *out, int width, IMAGE *im, PowtraInfo *inf )
{
int x, k, i;
/* Powtra all non-complex input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loopn(unsigned char, float); break;
case IM_BANDFMT_CHAR: loopn(signed char, float); break;
case IM_BANDFMT_USHORT: loopn(unsigned short, float); break;
case IM_BANDFMT_SHORT: loopn(signed short, float); break;
case IM_BANDFMT_UINT: loopn(unsigned int, float); break;
case IM_BANDFMT_INT: loopn(signed int, float); break;
case IM_BANDFMT_FLOAT: loopn(float, float); break;
case IM_BANDFMT_DOUBLE: loopn(double, double); break;
default:
assert( 0 );
}
return( 0 );
}
int
im_powtra_vec( IMAGE *in, IMAGE *out, int n, double *e )
{
PowtraInfo *inf;
int i;
/* Check args.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_powtra_vec", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_powtra_vec", "%s", _( "not non-complex" ) );
return( -1 );
}
if( n != 1 && n != in->Bands ) {
im_error( "im_powtra_vec",
_( "not 1 or %d elements in vector" ), in->Bands );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
if( im_isint( in ) ) {
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
}
/* Make space for a little buffer.
*/
if( !(inf = IM_NEW( out, PowtraInfo )) ||
!(inf->e = IM_ARRAY( out, n, double )) )
return( -1 );
for( i = 0; i < n; i++ )
inf->e[i] = e[i];
inf->n = n;
/* Generate!
*/
if( n == 1 ) {
if( im_wrapone( in, out,
(im_wrapone_fn) powtra1_gen, in, inf ) )
return( -1 );
}
else {
if( im_wrapone( in, out,
(im_wrapone_fn) powtran_gen, in, inf ) )
return( -1 );
}
return( 0 );
}
int
im_powtra( IMAGE *in, IMAGE *out, double e )
{
return( im_powtra_vec( in, out, 1, &e ) );
}

View File

@ -0,0 +1,278 @@
/* @(#) Remainder after integer division
*
* 2/8/99 JC
* - im_divide adapted to make im_remainder
* 8/5/02 JC
* - im_remainderconst added
* - im_remainderconst_vec added
* 27/9/04
* - updated for 1 band $op n band image -> n band image case
* 26/2/07
* - oop, broken for _vec case :-(
* 14/5/08
* - better /0 test
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
#define loop(TYPE) {\
TYPE *p1 = (TYPE *) in[0];\
TYPE *p2 = (TYPE *) in[1];\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ )\
if( p2[x] )\
q[x] = p1[x] % p2[x];\
else\
q[x] = -1;\
}
static void
remainder_buffer( PEL **in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR: loop( signed char ); break;
case IM_BANDFMT_UCHAR: loop( unsigned char ); break;
case IM_BANDFMT_SHORT: loop( signed short ); break;
case IM_BANDFMT_USHORT: loop( unsigned short ); break;
case IM_BANDFMT_INT: loop( signed int ); break;
case IM_BANDFMT_UINT: loop( unsigned int ); break;
default:
assert( 0 );
}
}
int
im_remainder( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
/* Basic checks.
*/
if( im_piocheck( in1, out ) || im_pincheck( in2 ) )
return( -1 );
if( in1->Xsize != in2->Xsize || in1->Ysize != in2->Ysize ) {
im_error( "im_remainder", "%s", _( "not same size" ) );
return( -1 );
}
if( in1->Bands != in2->Bands &&
(in1->Bands != 1 && in2->Bands != 1) ) {
im_error( "im_remainder",
"%s", _( "not same number of bands" ) );
return( -1 );
}
if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) {
im_error( "im_remainder", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_cp_descv( out, in1, in2, NULL ) )
return( -1 );
/* What number of bands will we write?
*/
out->Bands = IM_MAX( in1->Bands, in2->Bands );
/* What output type will we write? Same as LHS type, except float
* and double become signed int.
*/
if( im_isfloat( in1 ) || im_iscomplex( in1 ) )
out->BandFmt = IM_BANDFMT_INT;
/* And process!
*/
if( im__cast_and_call( in1, in2, out,
(im_wrapmany_fn) remainder_buffer, NULL ) )
return( -1 );
/* Success!
*/
return( 0 );
}
/* Parameters saved here.
*/
typedef struct _Remainderconst {
IMAGE *in;
IMAGE *out;
int n;
int *c;
} Remainderconst;
#define const1_loop(TYPE) {\
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
\
for( x = 0; x < sz; x++ ) \
q[x] = p[x] % c; \
}
static void
remainderconst1_buffer( PEL *in, PEL *out, int width, Remainderconst *rc )
{
IMAGE *im = rc->in;
int sz = width * im->Bands;
int c = rc->c[0];
int x;
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR: const1_loop( signed char ); break;
case IM_BANDFMT_UCHAR: const1_loop( unsigned char ); break;
case IM_BANDFMT_SHORT: const1_loop( signed short ); break;
case IM_BANDFMT_USHORT: const1_loop( unsigned short ); break;
case IM_BANDFMT_INT: const1_loop( signed int ); break;
case IM_BANDFMT_UINT: const1_loop( unsigned int ); break;
default:
assert( 0 );
}
}
#define const_loop(TYPE) {\
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
\
for( i = 0, x = 0; x < width; x++ ) \
for( k = 0; k < b; k++, i++ ) \
q[i] = p[i] % c[k]; \
}
static void
remainderconst_buffer( PEL *in, PEL *out, int width, Remainderconst *rc )
{
IMAGE *im = rc->in;
int b = im->Bands;
int *c = rc->c;
int i, x, k;
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR: const_loop( signed char ); break;
case IM_BANDFMT_UCHAR: const_loop( unsigned char ); break;
case IM_BANDFMT_SHORT: const_loop( signed short ); break;
case IM_BANDFMT_USHORT: const_loop( unsigned short ); break;
case IM_BANDFMT_INT: const_loop( signed int ); break;
case IM_BANDFMT_UINT: const_loop( unsigned int ); break;
default:
assert( 0 );
}
}
int
im_remainderconst_vec( IMAGE *in, IMAGE *out, int n, double *c )
{
Remainderconst *rc;
int i;
/* Basic checks.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_remainderconst_vec", "%s", _( "not uncoded" ) );
return( -1 );
}
if( n != 1 && n != in->Bands ) {
im_error( "im_remainderconst_vec",
_( "not 1 or %d elements in vector" ), in->Bands );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
/* Make space for a little buffer.
*/
if( !(rc = IM_NEW( out, Remainderconst )) ||
!(rc->c = IM_ARRAY( out, n, int )) )
return( -1 );
rc->in = in;
rc->out = out;
rc->n = n;
for( i = 0; i < n; i++ ) {
/* Cast down to int ... we pass in double for consistency with
* the other _vec functions.
*/
rc->c[i] = c[i];
if( rc->c[i] == 0 ) {
im_error( "im_remainderconst_vec",
"%s", _( "division by zero" ) );
return( -1 );
}
}
/* What output type will we write? Same as input type, except float
* and double become signed int.
*/
if( im_isfloat( in ) || im_iscomplex( in ) ) {
IMAGE *t = im_open_local( out, "im_remainderconst:1", "p" );
out->BandFmt = IM_BANDFMT_INT;
out->Bbits = IM_BBITS_INT;
if( !t || im_clip2fmt( in, t, out->BandFmt ) )
return( -1 );
rc->in = in = t;
}
if( n == 1 ) {
if( im_wrapone( in, out,
(im_wrapone_fn) remainderconst1_buffer, rc, NULL ) )
return( -1 );
}
else {
if( im_wrapone( in, out,
(im_wrapone_fn) remainderconst_buffer, rc, NULL ) )
return( -1 );
}
return( 0 );
}
int
im_remainderconst( IMAGE *in, IMAGE *out, double c )
{
return( im_remainderconst_vec( in, out, 1, &c ) );
}

View File

@ -0,0 +1,114 @@
/* @(#) rint() an image ... no promotion, so output type == input type
* @(#)
* @(#) int
* @(#) im_rint( in, out )
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* 20/6/02 JC
* - adapted from im_floor()
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
#define rint_loop(TYPE)\
{\
TYPE *p = (TYPE *) in;\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = IM_RINT( p[x] );\
}
/* rint a buffer of PELs.
*/
static void
rint_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
switch( im->BandFmt ) {
case IM_BANDFMT_FLOAT: rint_loop(float); break;
case IM_BANDFMT_DOUBLE: rint_loop(double); break;
case IM_BANDFMT_COMPLEX: sz *= 2; rint_loop(float); break;
case IM_BANDFMT_DPCOMPLEX: sz *= 2; rint_loop(double); break;
default:
assert( 0 );
}
}
/* rint of image.
*/
int
im_rint( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_rint", "%s", _( "not uncoded" ) );
return( -1 );
}
/* Is this one of the int types? Degenerate to im_copy() if it
* is.
*/
if( im_isint( in ) )
return( im_copy( in, out ) );
/* Output type == input type.
*/
if( im_cp_desc( out, in ) )
return( -1 );
/* Generate!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) rint_gen, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,162 @@
/* @(#) Find the unit vector in the direction of the pixel.
* @(#)
* @(#) int im_sign(in, out)
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* 9/7/02 JC
* - from im_cmulnorm
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
#define sign_complex( IN, OUT ) \
{ \
IN *p = (IN *) in; \
OUT *q = (OUT *) out; \
int x; \
\
for( x = 0; x < n; x++ ) { \
IN re = p[0]; \
IN im = p[1]; \
double fac = sqrt( re * re + im * im ); \
\
p += 2; \
\
if( fac == 0.0 ) { \
q[0] = 0.0; \
q[1] = 0.0; \
} \
else { \
q[0] = re / fac; \
q[1] = im / fac; \
} \
\
q += 2; \
} \
}
#define sign( IN, OUT ) \
{ \
IN *p = (IN *) in; \
OUT *q = (OUT *) out; \
int x; \
\
for( x = 0; x < n; x++ ) { \
IN v = p[x]; \
\
if( v > 0 ) \
q[x] = 1; \
else if( v == 0 ) \
q[x] = 0; \
else \
q[x] = -1; \
} \
}
/* sign buffer processor.
*/
static void
buffer_sign( void *in, void *out, int w, IMAGE *im )
{
int n = w * im->Bands;
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR:
sign( unsigned char, signed char );
break;
case IM_BANDFMT_CHAR:
sign( signed char, signed char );
break;
case IM_BANDFMT_USHORT:
sign( unsigned short, signed char );
break;
case IM_BANDFMT_SHORT:
sign( signed short, signed char );
break;
case IM_BANDFMT_UINT:
sign( unsigned int, signed char );
break;
case IM_BANDFMT_INT:
sign( signed int, signed char );
break;
case IM_BANDFMT_FLOAT:
sign( float, signed char );
break;
case IM_BANDFMT_DOUBLE:
sign( double, signed char );
break;
case IM_BANDFMT_COMPLEX:
sign_complex( float, float );
break;
case IM_BANDFMT_DPCOMPLEX:
sign_complex( double, double );
break;
default:
assert( 0 );
}
}
int
im_sign( IMAGE *in, IMAGE *out )
{
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_sign", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
if( !im_iscomplex( in ) ) {
out->Bbits = IM_BBITS_BYTE;
out->BandFmt = IM_BANDFMT_CHAR;
}
/* Do the processing.
*/
if( im_wrapone( in, out, (im_wrapone_fn) buffer_sign, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,239 @@
/* @(#) Find sin of any non-complex image. Output is always float for integer
* @(#) input and double for double input. All angles in degrees.
* @(#)
* @(#) int
* @(#) im_sintra( in, out )
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris, based on im_powtra()
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 5/5/93 JC
* - adapted from im_lintra to work with partial images
* - incorrect implementation of complex logs removed
* 1/7/93 JC
* - adapted for partial v2
* - ANSIfied
* 24/2/95 JC
* - im_logtra() adapted to make im_sintra()
* - adapted for im_wrapone()
* 26/1/96 JC
* - im_asintra() added
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Define what we do for each band element type. Non-complex input, any
* output.
*/
#define loop( IN, OUT )\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = sin( IM_RAD( (double) p[x] ) );\
}
/* sin a buffer of PELs.
*/
static void
sintra_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Switch for all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop( unsigned char, float ); break;
case IM_BANDFMT_CHAR: loop( signed char, float ); break;
case IM_BANDFMT_USHORT: loop( unsigned short, float ); break;
case IM_BANDFMT_SHORT: loop( signed short, float ); break;
case IM_BANDFMT_UINT: loop( unsigned int, float ); break;
case IM_BANDFMT_INT: loop( signed int, float ); break;
case IM_BANDFMT_FLOAT: loop( float, float ); break;
case IM_BANDFMT_DOUBLE: loop( double, double ); break;
default:
assert( 0 );
}
}
/* Sin transform.
*/
int
im_sintra( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_sintra", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_sintra", "%s", _( "not non-complex" ) );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
break;
default:
assert( 0 );
}
/* Generate!
*/
if( im_wrapone( in, out, (im_wrapone_fn) sintra_gen, in, NULL ) )
return( -1 );
return( 0 );
}
/* And asin().
*/
#define aloop( IN, OUT )\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = IM_DEG( asin( (double) p[x] ) );\
}
/* asin a buffer of PELs.
*/
static void
asintra_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Switch for all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: aloop( unsigned char, float ); break;
case IM_BANDFMT_CHAR: aloop( signed char, float ); break;
case IM_BANDFMT_USHORT: aloop( unsigned short, float ); break;
case IM_BANDFMT_SHORT: aloop( signed short, float ); break;
case IM_BANDFMT_UINT: aloop( unsigned int, float ); break;
case IM_BANDFMT_INT: aloop( signed int, float ); break;
case IM_BANDFMT_FLOAT: aloop( float, float ); break;
case IM_BANDFMT_DOUBLE: aloop( double, double ); break;
default:
assert( 0 );
}
}
/* Asin transform.
*/
int
im_asintra( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_asintra", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_asintra", "%s", _( "not non-complex" ) );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
break;
default:
assert( 0 );
}
/* Generate!
*/
if( im_wrapone( in, out, (im_wrapone_fn) asintra_gen, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,280 @@
/* @(#) im_stats: find general image statistics for all bands separately
(C) Kirk Martinez 1993
23/4/93 J.Cupitt
- adapted to partial images
- special struct abandoned; now returns DOUBLEMASK.
1/7/93 JC
- adapted for partial v2
- ANSIfied
27/7/93 JC
- init of mask changed to use actual values, not IM_MAXDOUBLE and
(-IM_MAXDOUBLE). These caused problems when assigned to floats.
funny business with offset==42, yuk!
31/8/93 JC
- forgot to init global max/min properly! sorry.
21/6/95 JC
- still did not init max and min correctly --- now fixed for good
* 13/1/05
* - use 64 bit arithmetic
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Make and initialise a DOUBLEMASK suitable for grabbing statistics.
*/
static void *
make_mask( IMAGE *im, void *a, void *b )
{
DOUBLEMASK *out;
/* Make temp output.
*/
if( !(out = im_create_dmask( "stats", 6, im->Bands + 1 )) )
return( NULL );
/* Set offset to magic value: 42 indicates we have not yet initialised
* max and min for this mask.
*/
out->offset = 42;
return( out );
}
/* Merge a temp DOUBLEMASK into the real DOUBLEMASK. Row 0 is unused, row 1
* has the stats for band 1. These are: (minimum, maximum, sum, sum^2). If the
* offset of out if 42, then it has not been inited yet and we just copy.
*/
static int
merge_mask( void *seq, void *a, void *b )
{
DOUBLEMASK *tmp = (DOUBLEMASK *) seq;
DOUBLEMASK *out = (DOUBLEMASK *) a;
double *rowi, *rowo;
int z;
/* Merge, or just copy?
*/
if( out->offset != 42 )
/* Add info from tmp.
*/
for( z = 1; z < tmp->ysize; z++ ) {
rowi = tmp->coeff + z * 6;
rowo = out->coeff + z * 6;
rowo[0] = IM_MIN( rowi[0], rowo[0] );
rowo[1] = IM_MAX( rowi[1], rowo[1] );
rowo[2] += rowi[2];
rowo[3] += rowi[3];
}
else {
/* Copy info from tmp.
*/
for( z = 1; z < tmp->ysize; z++ ) {
rowi = tmp->coeff + z * 6;
rowo = out->coeff + z * 6;
rowo[0] = rowi[0];
rowo[1] = rowi[1];
rowo[2] = rowi[2];
rowo[3] = rowi[3];
}
out->offset = 0;
}
/* Can now free tmp.
*/
im_free_dmask( tmp );
return( 0 );
}
/* Loop over region, adding information to the appropriate fields of tmp.
* We set max, min, sum, sum of squares. Our caller fills in the rest.
*/
static int
scan_fn( REGION *reg, void *seq, void *a, void *b )
{
DOUBLEMASK *tmp = (DOUBLEMASK *) seq;
Rect *r = &reg->valid;
IMAGE *im = reg->im;
int bands = im->Bands;
int le = r->left;
int ri = IM_RECT_RIGHT(r);
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int x, y, z;
/* What type? First define the loop we want to perform for all types.
* We scan lines bands times to avoid repeating band loops.
* Use temp variables of same type for min/max for faster comparisons.
* Use double to sum bands.
*/
#define non_complex_loop(TYPE) \
{ TYPE *p, *q; \
TYPE value, small, big; \
double *row; \
\
/* Have min and max been initialised? \
*/ \
if( tmp->offset == 42 ) { \
/* Init min and max for each band. \
*/ \
p = (TYPE *) IM_REGION_ADDR( reg, le, to ); \
for( z = 1; z < bands + 1; z++ ) { \
row = tmp->coeff + z * 6; \
row[0] = p[z - 1]; \
row[1] = p[z - 1]; \
} \
tmp->offset = 0; \
} \
\
for( y = to; y < bo; y++ ) { \
p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( z = 0; z < bands; z++ ) { \
q = p + z; \
row = tmp->coeff + (z + 1)*6; \
small = row[0]; \
big = row[1]; \
\
for( x = le; x < ri; x++ ) { \
value = *q; \
q += bands; \
row[2] += value;\
row[3] += (double)value*(double)value;\
if( value > big ) \
big = value; \
else if( value < small ) \
small = value;\
}\
\
row[0] = small; \
row[1] = big; \
}\
}\
}
/* Now generate code for all types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: non_complex_loop(unsigned char); break;
case IM_BANDFMT_CHAR: non_complex_loop(signed char); break;
case IM_BANDFMT_USHORT: non_complex_loop(unsigned short); break;
case IM_BANDFMT_SHORT: non_complex_loop(signed short); break;
case IM_BANDFMT_UINT: non_complex_loop(unsigned int); break;
case IM_BANDFMT_INT: non_complex_loop(signed int); break;
case IM_BANDFMT_DOUBLE: non_complex_loop(double); break;
case IM_BANDFMT_FLOAT: non_complex_loop(float); break;
default:
assert( 0 );
}
return( 0 );
}
/* Find the statistics of an image. Take any non-complex format. Write the
* stats to a DOUBLEMASK of size 6 by (in->Bands+1). We hold a row for each
* band, plus one row for all bands. Row n has 6 elements, which are, in
* order, (minimum, maximum, sum, sum^2, mean, deviation) for band n. Row 0 has
* the figures for all bands together.
*/
DOUBLEMASK *
im_stats( IMAGE *in )
{
DOUBLEMASK *out;
double *row, *base;
gint64 pels, vals, z;
/* Check our args.
*/
if( im_pincheck( in ) )
return( NULL );
if( im_iscomplex( in ) ) {
im_error( "im_stats", "%s", _( "bad input type" ) );
return( NULL );
}
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_stats", "%s", _( "not uncoded" ) );
return( NULL );
}
/* Make output.
*/
pels = (gint64) in->Xsize * in->Ysize;
vals = pels * in->Bands;
if( !(out = make_mask( in, NULL, NULL )) )
return( NULL );
/* Loop over input, calculating min, max, sum, sum^2 for each band
* separately.
*/
if( im_iterate( in, make_mask, scan_fn, merge_mask, out, NULL ) ) {
im_free_dmask( out );
return( NULL );
}
/* Calculate mean, deviation, plus overall stats.
*/
base = out->coeff;
base[0] = base[6]; /* Init global max/min */
base[1] = base[7];
for( z = 0; z < in->Bands; z++ ) {
row = base + (z + 1) * 6;
base[0] = IM_MIN( base[0], row[0] );
base[1] = IM_MAX( base[1], row[1] );
base[2] += row[2];
base[3] += row[3];
row[4] = row[2] / pels;
row[5] = sqrt( fabs( row[3] - (row[2] * row[2] / pels) ) /
(pels - 1) );
}
base[4] = base[2] / vals;
base[5] = sqrt( fabs( base[3] - (base[2] * base[2] / vals) ) /
(vals - 1) );
return( out );
}

View File

@ -0,0 +1,233 @@
/* @(#) Subtract two images
* @(#) Images must have the same no of bands and can be of any type
* @(#) No check for overflow is carried out.
* @(#)
* @(#) int
* @(#) im_subtract( in1, in2, out)
* @(#) IMAGE *in1, *in2, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 29/4/93 J.Cupitt
* - now works for partial images
* 1/7/93 JC
* - adapted for partial v2
* 9/5/95 JC
* - simplified: now just handles 10 cases (instead of 50), using
* im_clip2*() to help
* - now uses im_wrapmany() rather than im_generate()
* 12/6/95 JC
* - new im_add() adapted to make this
* 31/5/96 JC
* - what was this SWAP() stuff? failed for small - big!
* 22/8/03 JC
* - cast up more quickly to help accuracy
* 27/9/04
* - updated for 1 band $op n band image -> n band image case
* 8/12/06
* - add liboil support
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef HAVE_LIBOIL
#include <liboil/liboil.h>
#endif /*HAVE_LIBOIL*/
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Complex subtract.
*/
#define cloop(TYPE) \
{\
TYPE *p1 = (TYPE *) in[0];\
TYPE *p2 = (TYPE *) in[1];\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ ) {\
double rp1 = p1[0];\
double ip1 = p1[1];\
\
double rp2 = p2[0];\
double ip2 = p2[1];\
\
p1 += 2;\
p2 += 2;\
\
q[0] = rp1 - rp2;\
q[1] = ip1 - ip2;\
\
q += 2;\
}\
}
/* Real subtract.
*/
#define rloop(TYPE) \
{\
TYPE *p1 = (TYPE *) in[0];\
TYPE *p2 = (TYPE *) in[1];\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = p1[x] - p2[x];\
}
static void
subtract_buffer( PEL **in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Subtract all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR: rloop( signed char ); break;
case IM_BANDFMT_UCHAR: rloop( unsigned char ); break;
case IM_BANDFMT_SHORT: rloop( signed short ); break;
case IM_BANDFMT_USHORT: rloop( unsigned short ); break;
case IM_BANDFMT_INT: rloop( signed int ); break;
case IM_BANDFMT_UINT: rloop( unsigned int ); break;
case IM_BANDFMT_FLOAT:
#ifdef HAVE_LIBOIL
oil_subtract_f32( (float *) out,
(float *) in[0], (float *) in[1], sz );
#else /*!HAVE_LIBOIL*/
rloop( float );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: rloop( double ); break;
case IM_BANDFMT_COMPLEX: cloop( float ); break;
case IM_BANDFMT_DPCOMPLEX: cloop( double ); break;
default:
assert( 0 );
}
}
/* Save a bit of typing.
*/
#define S IM_BANDFMT_SHORT
#define I IM_BANDFMT_INT
#define D IM_BANDFMT_DOUBLE
/* Type conversions for two integer inputs. Rules for float and complex
* input encoded with ifs. We are sign and value preserving.
*/
static int iformat[6][6] = {
/* UC C US S UI I */
/* UC */ { S, S, I, I, I, I },
/* C */ { S, S, I, I, I, I },
/* US */ { I, I, I, I, I, I },
/* S */ { I, I, I, I, I, I },
/* UI */ { I, I, I, I, I, I },
/* I */ { I, I, I, I, I, I }
};
int
im_subtract( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
/* Basic checks.
*/
if( im_piocheck( in1, out ) || im_pincheck( in2 ) )
return( -1 );
if( in1->Bands != in2->Bands &&
(in1->Bands != 1 && in2->Bands != 1) ) {
im_error( "im_subtract",
"%s", _( "not same number of bands" ) );
return( -1 );
}
if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) {
im_error( "im_subtract", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_cp_descv( out, in1, in2, NULL ) )
return( -1 );
/* What number of bands will we write?
*/
out->Bands = IM_MAX( in1->Bands, in2->Bands );
/* What output type will we write? int, float or complex.
*/
if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) {
/* What kind of complex?
*/
if( in1->BandFmt == IM_BANDFMT_DPCOMPLEX ||
in2->BandFmt == IM_BANDFMT_DPCOMPLEX )
/* Output will be DPCOMPLEX.
*/
out->BandFmt = IM_BANDFMT_DPCOMPLEX;
else
out->BandFmt = IM_BANDFMT_COMPLEX;
}
else if( im_isfloat( in1 ) || im_isfloat( in2 ) ) {
/* What kind of float?
*/
if( in1->BandFmt == IM_BANDFMT_DOUBLE ||
in2->BandFmt == IM_BANDFMT_DOUBLE )
out->BandFmt = IM_BANDFMT_DOUBLE;
else
out->BandFmt = IM_BANDFMT_FLOAT;
}
else
/* Must be int+int -> int.
*/
out->BandFmt = iformat[in1->BandFmt][in2->BandFmt];
/* And process!
*/
if( im__cast_and_call( in1, in2, out,
(im_wrapmany_fn) subtract_buffer, NULL ) )
return( -1 );
/* Success!
*/
return( 0 );
}

View File

@ -0,0 +1,240 @@
/* @(#) Find tan of any non-complex image. Output is always float for integer
* @(#) input and double for double input. All angles in degrees.
* @(#)
* @(#) int
* @(#) im_tantra( in, out )
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris, based on im_powtra()
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on:
* 5/5/93 JC
* - adapted from im_lintra to work with partial images
* - incorrect implementation of complex logs removed
* 1/7/93 JC
* - adapted for partial v2
* - ANSIfied
* 24/2/95 JC
* - im_logtra() adapted to make im_tantra()
* - adapted for im_wrapone()
* 26/1/96 JC
* - atan() added
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Define what we do for each band element type. Non-complex input, any
* output.
*/
#define loop( IN, OUT )\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = tan( IM_RAD( (double) p[x] ) );\
}
/* tan a buffer of PELs.
*/
static void
tantra_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Switch for all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: loop( unsigned char, float ); break;
case IM_BANDFMT_CHAR: loop( signed char, float ); break;
case IM_BANDFMT_USHORT: loop( unsigned short, float ); break;
case IM_BANDFMT_SHORT: loop( signed short, float ); break;
case IM_BANDFMT_UINT: loop( unsigned int, float ); break;
case IM_BANDFMT_INT: loop( signed int, float ); break;
case IM_BANDFMT_FLOAT: loop( float, float ); break;
case IM_BANDFMT_DOUBLE: loop( double, double ); break;
default:
assert( 0 );
}
}
/* Tan transform.
*/
int
im_tantra( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_tantra", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_tantra", "%s", _( "not non-complex" ) );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
break;
default:
assert( 0 );
}
/* Generate!
*/
if( im_wrapone( in, out, (im_wrapone_fn) tantra_gen, in, NULL ) )
return( -1 );
return( 0 );
}
/* Define what we do for each band element type. Non-complex input, any
* output.
*/
#define aloop( IN, OUT )\
{\
IN *p = (IN *) in;\
OUT *q = (OUT *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = IM_DEG( atan( (double) p[x] ) );\
}
/* atan a buffer of PELs.
*/
static void
atantra_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Switch for all input types.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_UCHAR: aloop( unsigned char, float ); break;
case IM_BANDFMT_CHAR: aloop( signed char, float ); break;
case IM_BANDFMT_USHORT: aloop( unsigned short, float ); break;
case IM_BANDFMT_SHORT: aloop( signed short, float ); break;
case IM_BANDFMT_UINT: aloop( unsigned int, float ); break;
case IM_BANDFMT_INT: aloop( signed int, float ); break;
case IM_BANDFMT_FLOAT: aloop( float, float ); break;
case IM_BANDFMT_DOUBLE: aloop( double, double ); break;
default:
assert( 0 );
}
}
/* Atan transform.
*/
int
im_atantra( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_atantra", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iscomplex( in ) ) {
im_error( "im_atantra", "%s", _( "not non-complex" ) );
return( -1 );
}
/* Prepare output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
case IM_BANDFMT_CHAR:
case IM_BANDFMT_USHORT:
case IM_BANDFMT_SHORT:
case IM_BANDFMT_UINT:
case IM_BANDFMT_INT:
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_DOUBLE:
break;
default:
assert( 0 );
}
/* Generate!
*/
if( im_wrapone( in, out, (im_wrapone_fn) atantra_gen, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,7 @@
noinst_LTLIBRARIES = libboolean.la
libboolean_la_SOURCES = \
bool_dispatch.c \
boolean.c
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

View File

@ -0,0 +1,316 @@
/* VIPS function dispatch tables for conversion.
*
* J. Cupitt, 8/4/93.
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Two images in, one out.
*/
static im_arg_desc two_in_one_out[] = {
IM_INPUT_IMAGE( "in1" ),
IM_INPUT_IMAGE( "in2" ),
IM_OUTPUT_IMAGE( "out" )
};
/* One image plus one constant in, one image out.
*/
static im_arg_desc const_in_one_out[] = {
IM_INPUT_IMAGE( "in1" ),
IM_OUTPUT_IMAGE( "out" ),
IM_INPUT_INT( "c" )
};
/* One image plus doublevec in, one image out.
*/
static im_arg_desc vec_in_one_out[] = {
IM_INPUT_IMAGE( "in" ),
IM_OUTPUT_IMAGE( "out" ),
IM_INPUT_DOUBLEVEC( "vec" )
};
/* Call im_and via arg vector.
*/
static int
and_vec( im_object *argv )
{
return( im_andimage( argv[0], argv[1], argv[2] ) );
}
/* Description of im_and.
*/
static im_function and_desc = {
"im_andimage", /* Name */
"bitwise and of two images", /* Description */
IM_FN_PTOP | IM_FN_PIO, /* Flags */
and_vec, /* Dispatch function */
IM_NUMBER( two_in_one_out ), /* Size of arg list */
two_in_one_out /* Arg list */
};
/* Call im_andconst via arg vector.
*/
static int
andconst_vec( im_object *argv )
{
int c = *((int *) argv[2]);
return( im_andconst( argv[0], argv[1], c ) );
}
/* Description of im_andconst.
*/
static im_function andconst_desc = {
"im_andimageconst", /* Name */
"bitwise and of an image with a constant",
IM_FN_PTOP | IM_FN_PIO, /* Flags */
andconst_vec, /* Dispatch function */
IM_NUMBER( const_in_one_out ), /* Size of arg list */
const_in_one_out /* Arg list */
};
/* Call im_and_vec via arg vector.
*/
static int
and_vec_vec( im_object *argv )
{
im_doublevec_object *rv = (im_doublevec_object *) argv[2];
return( im_and_vec( argv[0], argv[1], rv->n, rv->vec ) );
}
/* Description of im_andconst.
*/
static im_function and_vec_desc = {
"im_andimage_vec", /* Name */
"bitwise and of an image with a vector constant",
IM_FN_PTOP | IM_FN_PIO, /* Flags */
and_vec_vec, /* Dispatch function */
IM_NUMBER( vec_in_one_out ), /* Size of arg list */
vec_in_one_out /* Arg list */
};
/* Call im_or via arg vector.
*/
static int
or_vec( im_object *argv )
{
return( im_orimage( argv[0], argv[1], argv[2] ) );
}
/* Description of im_or.
*/
static im_function or_desc = {
"im_orimage", /* Name */
"bitwise or of two images", /* Description */
IM_FN_PTOP | IM_FN_PIO, /* Flags */
or_vec, /* Dispatch function */
IM_NUMBER( two_in_one_out ), /* Size of arg list */
two_in_one_out /* Arg list */
};
/* Call im_orconst via arg vector.
*/
static int
orconst_vec( im_object *argv )
{
int c = *((int *) argv[2]);
return( im_orconst( argv[0], argv[1], c ) );
}
/* Description of im_orconst.
*/
static im_function orconst_desc = {
"im_orimageconst", /* Name */
"bitwise or of an image with a constant",
IM_FN_PTOP | IM_FN_PIO, /* Flags */
orconst_vec, /* Dispatch function */
IM_NUMBER( const_in_one_out ), /* Size of arg list */
const_in_one_out /* Arg list */
};
/* Call im_or_vec via arg vector.
*/
static int
or_vec_vec( im_object *argv )
{
im_doublevec_object *rv = (im_doublevec_object *) argv[2];
return( im_or_vec( argv[0], argv[1], rv->n, rv->vec ) );
}
/* Description of im_orconst.
*/
static im_function or_vec_desc = {
"im_orimage_vec", /* Name */
"bitwise or of an image with a vector constant",
IM_FN_PTOP | IM_FN_PIO, /* Flags */
or_vec_vec, /* Dispatch function */
IM_NUMBER( vec_in_one_out ), /* Size of arg list */
vec_in_one_out /* Arg list */
};
/* Call im_eor via arg vector.
*/
static int
eor_vec( im_object *argv )
{
return( im_eorimage( argv[0], argv[1], argv[2] ) );
}
/* Description of im_eor.
*/
static im_function eor_desc = {
"im_eorimage", /* Name */
"bitwise eor of two images", /* Description */
IM_FN_PTOP | IM_FN_PIO, /* Flags */
eor_vec, /* Dispatch function */
IM_NUMBER( two_in_one_out ), /* Size of arg list */
two_in_one_out /* Arg list */
};
/* Call im_eorconst via arg vector.
*/
static int
eorconst_vec( im_object *argv )
{
int c = *((int *) argv[2]);
return( im_eorconst( argv[0], argv[1], c ) );
}
/* Description of im_eorconst.
*/
static im_function eorconst_desc = {
"im_eorimageconst", /* Name */
"bitwise eor of an image with a constant",
IM_FN_PTOP | IM_FN_PIO, /* Flags */
eorconst_vec, /* Dispatch function */
IM_NUMBER( const_in_one_out ), /* Size of arg list */
const_in_one_out /* Arg list */
};
/* Call im_eor_vec via arg vector.
*/
static int
eor_vec_vec( im_object *argv )
{
im_doublevec_object *rv = (im_doublevec_object *) argv[2];
return( im_eor_vec( argv[0], argv[1], rv->n, rv->vec ) );
}
/* Description of im_eorconst.
*/
static im_function eor_vec_desc = {
"im_eorimage_vec", /* Name */
"bitwise eor of an image with a vector constant",
IM_FN_PTOP | IM_FN_PIO, /* Flags */
eor_vec_vec, /* Dispatch function */
IM_NUMBER( vec_in_one_out ), /* Size of arg list */
vec_in_one_out /* Arg list */
};
/* Call im_shiftleft via arg vector.
*/
static int
shiftleft_vec( im_object *argv )
{
int n = *((int *) argv[2]);
return( im_shiftleft( argv[0], argv[1], n ) );
}
/* Description of im_shiftleft.
*/
static im_function shiftleft_desc = {
"im_shiftleft", /* Name */
"shift integer image n bits to left",
IM_FN_PTOP | IM_FN_PIO, /* Flags */
shiftleft_vec, /* Dispatch function */
IM_NUMBER( const_in_one_out ), /* Size of arg list */
const_in_one_out /* Arg list */
};
/* Call im_shiftright via arg vector.
*/
static int
shiftright_vec( im_object *argv )
{
int n = *((int *) argv[2]);
return( im_shiftright( argv[0], argv[1], n ) );
}
/* Description of im_shiftright.
*/
static im_function shiftright_desc = {
"im_shiftright", /* Name */
"shift integer image n bits to right",
IM_FN_PTOP | IM_FN_PIO, /* Flags */
shiftright_vec, /* Dispatch function */
IM_NUMBER( const_in_one_out ), /* Size of arg list */
const_in_one_out /* Arg list */
};
/* Package up all these functions.
*/
static im_function *bool_list[] = {
&and_desc,
&andconst_desc,
&and_vec_desc,
&or_desc,
&orconst_desc,
&or_vec_desc,
&eor_desc,
&eorconst_desc,
&eor_vec_desc,
&shiftleft_desc,
&shiftright_desc
};
/* Package of functions.
*/
im_package im__boolean = {
"boolean",
IM_NUMBER( bool_list ),
bool_list
};

664
libvips/boolean/boolean.c Normal file
View File

@ -0,0 +1,664 @@
/* @(#) Bitwise operations on VASARI images. Inputs must be some
* @(#) integer type and have the same size and number of bands. Use
* @(#) im_eorconst( in, out, -1 ) for im_not.
* @(#)
* @(#) int im_andimage( a, b, out ) int im_andconst( a, out, c )
* @(#) IMAGE *a, *b, *out; IMAGE *a, *out;
* @(#) unsigned char c;
* @(#)
* @(#) int im_orimage( a, b, out ) int im_orconst( a, out, c )
* @(#) IMAGE *a, *b, *out; IMAGE *a, *out;
* @(#) unsigned char c;
* @(#)
* @(#) int im_eorimage( a, b, out ) int im_eorconst( a, out, c )
* @(#) IMAGE *a, *b, *out; IMAGE *a, *out;
* @(#) unsigned char c;
* @(#)
* @(#) int im_shiftleft( in, out, n ) int im_shiftright( in, out, n )
* @(#) IMAGE *in, *out; IMAGE *in, *out;
* @(#) int n; int n;
* @(#)
* @(#) Returns either 0 (success) or -1 (fail).
*
* Modified:
* 15/12/94 JC
* - ANSIfied
* - adapted to partials with im_wrap...
* 25/1/95 JC
* - added check1ary(), check2ary()
* 8/2/95 JC
* - new im_wrapmany
* 19/7/95 JC
* - added im_shiftleft() and im_shiftright()
* 6/7/98 JC
* - added _vec forms
* - removed *p++ stuff
* 10/9/99 JC
* - and/or/eor now do all int types
* 10/10/02 JC
* - renamed im_and() etc. as im_andimage() to remove breakage in the C++
* layer if operator names are turned on
* 30/6/04
* - now cast float/complex args to int
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Save a bit of typing.
*/
#define UC IM_BANDFMT_UCHAR
#define C IM_BANDFMT_CHAR
#define US IM_BANDFMT_USHORT
#define S IM_BANDFMT_SHORT
#define UI IM_BANDFMT_UINT
#define I IM_BANDFMT_INT
#define F IM_BANDFMT_FLOAT
#define M IM_BANDFMT_COMPLEX
#define D IM_BANDFMT_DOUBLE
#define DM IM_BANDFMT_DPCOMPLEX
/* Type conversions for boolean.
*/
static int iformat[10][10] = {
/* UC C US S UI I F M D DM */
/* UC */ { UC, C, US, S, UI, I, I, I, I, I },
/* C */ { C, C, S, S, I, I, I, I, I, I },
/* US */ { US, S, US, S, UI, I, I, I, I, I },
/* S */ { S, S, S, S, I, I, I, I, I, I },
/* UI */ { UI, I, UI, I, UI, I, I, I, I, I },
/* I */ { I, I, I, I, I, I, I, I, I, I },
/* F */ { I, I, I, I, I, I, I, I, I, I },
/* M */ { I, I, I, I, I, I, I, I, I, I },
/* D */ { I, I, I, I, I, I, I, I, I, I },
/* DM */ { I, I, I, I, I, I, I, I, I, I }
};
/* Check args. Cast inputs to matching integer format.
*/
static int
check( IMAGE **in, IMAGE *out )
{
int i, n;
int fmt;
/* Count args.
*/
for( n = 0; in[n]; n++ ) {
if( in[n]->Coding != IM_CODING_NONE ) {
im_error( "boolean",
"%s", _( "uncoded images only" ) );
return( -1 );
}
}
/* Check sizes match.
*/
for( i = 1; i < n; i++ )
if( in[0]->Bands != in[i]->Bands ||
in[0]->Xsize != in[i]->Xsize ||
in[0]->Ysize != in[i]->Ysize ) {
im_error( "boolean",
"%s", _( "images differ in size" ) );
return( -1 );
}
/* Calculate type conversion ... just 1ary and 2ary.
*/
switch( n ) {
case 1:
fmt = iformat[0][in[0]->BandFmt];
break;
case 2:
fmt = iformat[in[1]->BandFmt][in[0]->BandFmt];
break;
default:
assert( FALSE );
}
for( i = 0; i < n; i++ ) {
IMAGE *t = im_open_local( out, "check-1", "p" );
if( !t || im_clip2fmt( in[i], t, fmt ) )
return( -1 );
in[i] = t;
}
/* Prepare the output image.
*/
if( im_cp_desc_array( out, in ) )
return( -1 );
return( 0 );
}
/* A selection of main loops. As with im_add(), only implement monotype
* operations. TYPE is some integer type, signed or unsigned.
*/
#define AND2( TYPE ) { \
TYPE *tq = (TYPE *) q; \
TYPE *tp1 = (TYPE *) p1; \
TYPE *tp2 = (TYPE *) p2; \
\
for( x = 0; x < ne; x++ ) \
tq[x] = tp1[x] & tp2[x]; \
}
#define OR2( TYPE ) { \
TYPE *tq = (TYPE *) q; \
TYPE *tp1 = (TYPE *) p1; \
TYPE *tp2 = (TYPE *) p2; \
\
for( x = 0; x < ne; x++ ) \
tq[x] = tp1[x] | tp2[x]; \
}
#define EOR2( TYPE ) { \
TYPE *tq = (TYPE *) q; \
TYPE *tp1 = (TYPE *) p1; \
TYPE *tp2 = (TYPE *) p2; \
\
for( x = 0; x < ne; x++ ) \
tq[x] = tp1[x] ^ tp2[x]; \
}
#define ANDCONST( TYPE ) { \
TYPE *tq = (TYPE *) q; \
TYPE *tp = (TYPE *) p; \
TYPE *tc = (TYPE *) c; \
\
for( i = 0, x = 0; x < n; x++ ) \
for( b = 0; b < bands; b++, i++ ) \
tq[i] = tp[i] & tc[b]; \
}
#define ORCONST( TYPE ) { \
TYPE *tq = (TYPE *) q; \
TYPE *tp = (TYPE *) p; \
TYPE *tc = (TYPE *) c; \
\
for( i = 0, x = 0; x < n; x++ ) \
for( b = 0; b < bands; b++, i++ ) \
tq[i] = tp[i] | tc[b]; \
}
#define EORCONST( TYPE ) { \
TYPE *tq = (TYPE *) q; \
TYPE *tp = (TYPE *) p; \
TYPE *tc = (TYPE *) c; \
\
for( i = 0, x = 0; x < n; x++ ) \
for( b = 0; b < bands; b++, i++ ) \
tq[i] = tp[i] ^ tc[b]; \
}
/* The above, wrapped up as buffer processing functions.
*/
static void
and_buffer( PEL **p, PEL *q, int n, IMAGE *im )
{
int x;
int bands = im->Bands;
int ne = n * bands;
PEL *p1 = p[0];
PEL *p2 = p[1];
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR: AND2( signed char ); break;
case IM_BANDFMT_UCHAR: AND2( unsigned char ); break;
case IM_BANDFMT_SHORT: AND2( signed short ); break;
case IM_BANDFMT_USHORT: AND2( unsigned short ); break;
case IM_BANDFMT_INT: AND2( signed int ); break;
case IM_BANDFMT_UINT: AND2( unsigned int ); break;
default:
error_exit( "im_and: internal error" );
}
}
static void
or_buffer( PEL **p, PEL *q, int n, IMAGE *in1 )
{
int x;
int bands = in1->Bands;
int ne = n * bands;
PEL *p1 = p[0];
PEL *p2 = p[1];
switch( in1->BandFmt ) {
case IM_BANDFMT_CHAR: OR2( signed char ); break;
case IM_BANDFMT_UCHAR: OR2( unsigned char ); break;
case IM_BANDFMT_SHORT: OR2( signed short ); break;
case IM_BANDFMT_USHORT: OR2( unsigned short ); break;
case IM_BANDFMT_INT: OR2( signed int ); break;
case IM_BANDFMT_UINT: OR2( unsigned int ); break;
default:
error_exit( "im_or: internal error" );
}
}
static void
eor_buffer( PEL **p, PEL *q, int n, IMAGE *in1 )
{
int x;
int bands = in1->Bands;
int ne = n * bands;
PEL *p1 = p[0];
PEL *p2 = p[1];
switch( in1->BandFmt ) {
case IM_BANDFMT_CHAR: EOR2( signed char ); break;
case IM_BANDFMT_UCHAR: EOR2( unsigned char ); break;
case IM_BANDFMT_SHORT: EOR2( signed short ); break;
case IM_BANDFMT_USHORT: EOR2( unsigned short ); break;
case IM_BANDFMT_INT: EOR2( signed int ); break;
case IM_BANDFMT_UINT: EOR2( unsigned int ); break;
default:
error_exit( "im_eor: internal error" );
}
}
static void
andconst_buffer( PEL *p, PEL *q, int n, IMAGE *in, PEL *c )
{
int x, i, b;
int bands = in->Bands;
switch( in->BandFmt ) {
case IM_BANDFMT_CHAR: ANDCONST( signed char ); break;
case IM_BANDFMT_UCHAR: ANDCONST( unsigned char ); break;
case IM_BANDFMT_SHORT: ANDCONST( signed short ); break;
case IM_BANDFMT_USHORT: ANDCONST( unsigned short ); break;
case IM_BANDFMT_INT: ANDCONST( signed int ); break;
case IM_BANDFMT_UINT: ANDCONST( unsigned int ); break;
default:
error_exit( "im_andconst: internal error" );
}
}
static void
orconst_buffer( PEL *p, PEL *q, int n, IMAGE *in, PEL *c )
{
int x, i, b;
int bands = in->Bands;
switch( in->BandFmt ) {
case IM_BANDFMT_CHAR: ORCONST( signed char ); break;
case IM_BANDFMT_UCHAR: ORCONST( unsigned char ); break;
case IM_BANDFMT_SHORT: ORCONST( signed short ); break;
case IM_BANDFMT_USHORT: ORCONST( unsigned short ); break;
case IM_BANDFMT_INT: ORCONST( signed int ); break;
case IM_BANDFMT_UINT: ORCONST( unsigned int ); break;
default:
error_exit( "im_orconst: internal error" );
}
}
static void
eorconst_buffer( PEL *p, PEL *q, int n, IMAGE *in, PEL *c )
{
int x, i, b;
int bands = in->Bands;
switch( in->BandFmt ) {
case IM_BANDFMT_CHAR: EORCONST( signed char ); break;
case IM_BANDFMT_UCHAR: EORCONST( unsigned char ); break;
case IM_BANDFMT_SHORT: EORCONST( signed short ); break;
case IM_BANDFMT_USHORT: EORCONST( unsigned short ); break;
case IM_BANDFMT_INT: EORCONST( signed int ); break;
case IM_BANDFMT_UINT: EORCONST( unsigned int ); break;
default:
error_exit( "im_eorconst: internal error" );
}
}
/* The above, wrapped up as im_*() functions.
*/
int
im_andimage( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
IMAGE *invec[3];
/* Check images.
*/
invec[0] = in1; invec[1] = in2; invec[2] = NULL;
if( check( invec, out ) )
return( -1 );
/* Process!
*/
if( im_wrapmany( invec, out, (im_wrapmany_fn) and_buffer, out, NULL ) )
return( -1 );
return( 0 );
}
int
im_orimage( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
IMAGE *invec[3];
invec[0] = in1; invec[1] = in2; invec[2] = NULL;
if( check( invec, out ) )
return( -1 );
if( im_wrapmany( invec, out, (im_wrapmany_fn) or_buffer, out, NULL ) )
return( -1 );
return( 0 );
}
int
im_eorimage( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
IMAGE *invec[3];
invec[0] = in1; invec[1] = in2; invec[2] = NULL;
if( check( invec, out ) )
return( -1 );
if( im_wrapmany( invec, out, (im_wrapmany_fn) eor_buffer, out, NULL ) )
return( -1 );
return( 0 );
}
/* Cast a vector of double to a vector of TYPE.
*/
#define CAST( TYPE ) { \
TYPE *tq = (TYPE *) q; \
\
for( i = 0; i < out->Bands; i++ ) \
tq[i] = (TYPE) p[i]; \
}
/* Make a pixel of output type from a realvec.
*/
static PEL *
make_pixel( IMAGE *out, int fmt, double *p )
{
PEL *q;
int i;
if( !(q = IM_ARRAY( out, IM_IMAGE_SIZEOF_PEL( out ), PEL )) )
return( NULL );
switch( fmt ) {
case IM_BANDFMT_CHAR: CAST( signed char ); break;
case IM_BANDFMT_UCHAR: CAST( unsigned char ); break;
case IM_BANDFMT_SHORT: CAST( signed short ); break;
case IM_BANDFMT_USHORT: CAST( unsigned short ); break;
case IM_BANDFMT_INT: CAST( signed int ); break;
case IM_BANDFMT_UINT: CAST( unsigned int ); break;
default:
error_exit( "make_pixel: internal error" );
}
return( q );
}
int
im_and_vec( IMAGE *in, IMAGE *out, int n, double *c )
{
IMAGE *invec[2];
PEL *cb;
invec[0] = in; invec[1] = NULL;
if( check( invec, out ) )
return( -1 );
in = invec[0];
if( n != in->Bands ) {
im_error( "im_and_vec",
"%s", _( "vec size does not match bands" ) );
return( -1 );
}
if( !(cb = make_pixel( out, in->BandFmt, c )) )
return( -1 );
if( im_wrapone( in, out,
(im_wrapone_fn) andconst_buffer, (void *) in, (void *) cb ) )
return( -1 );
return( 0 );
}
int
im_or_vec( IMAGE *in, IMAGE *out, int n, double *c )
{
IMAGE *invec[2];
PEL *cb;
invec[0] = in; invec[1] = NULL;
if( check( invec, out ) )
return( -1 );
in = invec[0];
if( n != in->Bands ) {
im_error( "im_or_vec",
"%s", _( "vec size does not match bands" ) );
return( -1 );
}
if( !(cb = make_pixel( out, in->BandFmt, c )) )
return( -1 );
if( im_wrapone( in, out,
(im_wrapone_fn) orconst_buffer, (void *) in, (void *) cb ) )
return( -1 );
return( 0 );
}
int
im_eor_vec( IMAGE *in, IMAGE *out, int n, double *c )
{
IMAGE *invec[2];
PEL *cb;
invec[0] = in; invec[1] = NULL;
if( check( invec, out ) )
return( -1 );
in = invec[0];
if( n != in->Bands ) {
im_error( "im_eor_vec",
"%s", _( "vec size does not match bands" ) );
return( -1 );
}
if( !(cb = make_pixel( out, in->BandFmt, c )) )
return( -1 );
if( im_wrapone( in, out,
(im_wrapone_fn) eorconst_buffer, (void *) in, (void *) cb ) )
return( -1 );
return( 0 );
}
/* Cast a double to a vector of TYPE.
*/
#define CCAST( TYPE ) { \
TYPE *tq = (TYPE *) q; \
\
for( i = 0; i < in->Bands; i++ ) \
tq[i] = (TYPE) p; \
}
/* Make a pixel of output type from a single double.
*/
static double *
make_pixel_const( IMAGE *in, IMAGE *out, double p )
{
double *q;
int i;
if( !(q = IM_ARRAY( out, in->Bands, double )) )
return( NULL );
for( i = 0; i < in->Bands; i++ )
q[i] = p;
return( q );
}
int
im_andconst( IMAGE *in, IMAGE *out, double c )
{
double *v = make_pixel_const( in, out, c );
return( !v || im_and_vec( in, out, in->Bands, v ) );
}
int
im_orconst( IMAGE *in, IMAGE *out, double c )
{
double *v = make_pixel_const( in, out, c );
return( !v || im_or_vec( in, out, in->Bands, v ) );
}
int
im_eorconst( IMAGE *in, IMAGE *out, double c )
{
double *v = make_pixel_const( in, out, c );
return( !v || im_eor_vec( in, out, in->Bands, v ) );
}
/* Assorted shift operations.
*/
#define SHIFTL( TYPE ) { \
TYPE *pt = (TYPE *) p;\
TYPE *qt = (TYPE *) q;\
\
for( x = 0; x < ne; x++ )\
qt[x] = pt[x] << n;\
}
/* The above as buffer ops.
*/
static void
shiftleft_buffer( PEL *p, PEL *q, int len, IMAGE *in, int n )
{
int x;
int ne = len * in->Bands;
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR: SHIFTL( unsigned char ); break;
case IM_BANDFMT_CHAR: SHIFTL( signed char ); break;
case IM_BANDFMT_USHORT: SHIFTL( unsigned short ); break;
case IM_BANDFMT_SHORT: SHIFTL( signed short ); break;
case IM_BANDFMT_UINT: SHIFTL( unsigned int ); break;
case IM_BANDFMT_INT: SHIFTL( signed int ); break;
default:
error_exit( "im_shiftleft: internal error" );
/*NOTREACHED*/
}
}
/* The above as im_*() functions.
*/
int
im_shiftleft( IMAGE *in, IMAGE *out, int n )
{
IMAGE *invec[2];
invec[0] = in; invec[1] = NULL;
if( check( invec, out ) )
return( -1 );
in = invec[0];
if( im_wrapone( in, out,
(im_wrapone_fn) shiftleft_buffer, in, GINT_TO_POINTER( n ) ) )
return( -1 );
return( 0 );
}
#define SHIFTR( TYPE ) { \
TYPE *pt = (TYPE *) p; \
TYPE *qt = (TYPE *) q; \
\
for( x = 0; x < ne; x++ ) \
qt[x] = pt[x] >> n; \
}
static void
shiftright_buffer( PEL *p, PEL *q, int len, IMAGE *in, int n )
{
int x;
int ne = len * in->Bands;
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR: SHIFTR( unsigned char ); break;
case IM_BANDFMT_CHAR: SHIFTR( signed char ); break;
case IM_BANDFMT_USHORT: SHIFTR( unsigned short ); break;
case IM_BANDFMT_SHORT: SHIFTR( signed short ); break;
case IM_BANDFMT_UINT: SHIFTR( unsigned int ); break;
case IM_BANDFMT_INT: SHIFTR( signed int ); break;
default:
error_exit( "im_shiftright: internal error" );
/*NOTREACHED*/
}
}
int
im_shiftright( IMAGE *in, IMAGE *out, int n )
{
IMAGE *invec[2];
invec[0] = in; invec[1] = NULL;
if( check( invec, out ) )
return( -1 );
in = invec[0];
if( im_wrapone( in, out,
(im_wrapone_fn) shiftright_buffer, in, GINT_TO_POINTER( n ) ) )
return( -1 );
return( 0 );
}

22226
libvips/cimg/CImg.h Normal file

File diff suppressed because it is too large Load Diff

24
libvips/cimg/Makefile.am Normal file
View File

@ -0,0 +1,24 @@
noinst_LTLIBRARIES = libcimg.la
libcimg_la_SOURCES = \
CImg.h \
cimg_dispatch.c \
cimg.cpp
# various cimg settings as well
# we need to change these a bit for win32
if OS_WIN32
AM_CPPFLAGS = \
-Dcimg_strict \
-Dcimg_OS=0 \
-Dcimg_display_type=0 \
-DLOCALEDIR=\""$(LOCALEDIR)"\"
else
AM_CPPFLAGS = \
-Dcimg_strict \
-Dcimg_OS=1 \
-Dcimg_display_type=0 \
-DLOCALEDIR=\""$(LOCALEDIR)"\"
endif
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

288
libvips/cimg/cimg.cpp Normal file
View File

@ -0,0 +1,288 @@
/* @(#) Pass VIPS images through CImg
*
* JC, 15/10/07
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <vips/vips.h>
#include <vips/internal.h>
/* CImg needs to call pthread directly, this is the preproc magic they
* prefer.
*/
#if defined(sun) || defined(__sun) || defined(linux) || defined(__linux) \
|| defined(__linux__) || defined(__CYGWIN__) || defined(BSD) || defined(__FreeBSD__) \
|| defined(__OPENBSD__) || defined(__MACOSX__) || defined(__APPLE__) || defined(sgi) \
|| defined(__sgi)
#include <pthread.h>
#endif
#include "CImg.h"
using namespace cimg_library;
/* Save params here.
*/
struct Greyc {
IMAGE *in;
IMAGE *out;
IMAGE *mask;
IMAGE **arry;
int iterations;
float amplitude;
float sharpness;
float anisotropy;
float alpha;
float sigma;
float dl;
float da;
float gauss_prec;
int interpolation;
bool fast_approx;
};
// copy part of a vips region into a cimg
template<typename T> static CImg<T> *
vips_to_cimg( REGION *in, Rect *area )
{
IMAGE *im = in->im;
CImg<T> *img = new CImg<T>( area->width, area->height, 1, im->Bands );
for( int y = 0; y < area->height; y++ ) {
T *p = (T *) IM_REGION_ADDR( in, area->left, area->top + y );
for( int x = 0; x < area->width; x++ ) {
for( int z = 0; z < im->Bands; z++ )
(*img)( x, y, z ) = p[z];
p += im->Bands;
}
}
return( img );
}
// write a CImg to a vips region
// fill out->valid, img has pixels in img_rect
template<typename T> static void
cimg_to_vips( CImg<T> *img, Rect *img_rect, REGION *out )
{
IMAGE *im = out->im;
Rect *valid = &out->valid;
g_assert( im_rect_includesrect( img_rect, valid ) );
int x_off = valid->left - img_rect->left;
int y_off = valid->top - img_rect->top;
for( int y = 0; y < valid->height; y++ ) {
T *p = (T *) IM_REGION_ADDR( out, valid->left, valid->top + y );
for( int x = 0; x < valid->width; x++ ) {
for( int z = 0; z < im->Bands; z++ )
p[z] = static_cast<T>( (*img)(
x + x_off, y + y_off, z ) );
p += im->Bands;
}
}
}
template<typename T> static int
greyc_gen( REGION *out, REGION **in, IMAGE **arry, Greyc *greyc )
{
static const float gfact = (sizeof( T ) == 2) ? 1.0 / 256 : 1.0;
static const int tile_border = 4;
Rect *ir = &out->valid;
Rect need;
Rect image;
CImg<T> *img;
CImg<unsigned char> *msk;
need = *ir;
im_rect_marginadjust( &need, tile_border );
image.left = 0;
image.top = 0;
image.width = in[0]->im->Xsize;
image.height = in[0]->im->Ysize;
im_rect_intersectrect( &need, &image, &need );
if( im_prepare( in[0], &need ) )
return( -1 );
if( in[1] && im_prepare( in[1], &need ) )
return( -1 );
img = NULL;
msk = NULL;
try {
img = vips_to_cimg<T>( in[0], &need );
if( in[1] )
msk = vips_to_cimg<unsigned char>( in[1], &need );
else
// empty mask
msk = new CImg<unsigned char>();
for( int i = 0; i < greyc->iterations; i++ )
img->blur_anisotropic( *msk,
greyc->amplitude, greyc->sharpness,
greyc->anisotropy,
greyc->alpha, greyc->sigma, greyc->dl,
greyc->da, greyc->gauss_prec,
greyc->interpolation, greyc->fast_approx,
gfact );
cimg_to_vips<T>( img, &need, out );
}
catch( CImgException e ) {
if( img )
delete( img );
if( msk )
delete( msk );
im_error( "GREYCstoration", "%s", e.message );
return( -1 );
}
if( img )
delete( img );
if( msk )
delete( msk );
return( 0 );
}
// Hmm, strange double-cast needed
typedef int (*generate_fn)( REGION *out, REGION **in,
IMAGE **im, Greyc *greyc );
// as a plain C function
int
im_greyc_mask( IMAGE *in, IMAGE *out, IMAGE *mask,
int iterations,
float amplitude, float sharpness, float anisotropy,
float alpha, float sigma,
float dl, float da, float gauss_prec,
int interpolation, int fast_approx )
{
IMAGE **arry;
Greyc *greyc;
if( im_piocheck( in, out ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "GREYCstoration", "%s", _( "uncoded only" ) );
return( -1 );
}
if( mask ) {
if( mask->Coding != IM_CODING_NONE ) {
im_error( "GREYCstoration", "%s", _( "uncoded only" ) );
return( -1 );
}
if( mask->Xsize != in->Xsize ||
mask->Ysize != in->Ysize ) {
im_error( "GREYCstoration",
"%s", _( "mask size does not match input" ) );
return( -1 );
}
if( mask->BandFmt != IM_BANDFMT_UCHAR ) {
im_error( "GREYCstoration",
"%s", _( "mask must be uchar" ) );
return( -1 );
}
}
im_cp_desc( out, in );
if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) )
return( -1 );
if( !(arry = im_allocate_input_array( out, in, mask, NULL )) )
return( -1 );
if( !(greyc = IM_NEW( out, Greyc )) )
return( -1 );
greyc->in = in;
greyc->out = out;
greyc->mask = mask;
greyc->arry = arry;
greyc->iterations = iterations;
greyc->amplitude = amplitude;
greyc->sharpness = sharpness;
greyc->anisotropy = anisotropy;
greyc->alpha = alpha;
greyc->sigma = sigma;
greyc->dl = dl;
greyc->da = da;
greyc->gauss_prec = gauss_prec;
greyc->interpolation = interpolation;
greyc->fast_approx = fast_approx;
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
if( im_generate( out,
im_start_many,
// double-cast to give g++ enough context to expand the
// template correctly
(im_generate_fn) (
(generate_fn) greyc_gen<unsigned char>),
im_stop_many, arry, greyc ) )
return( -1 );
break;
case IM_BANDFMT_USHORT:
if( im_generate( out,
im_start_many,
(im_generate_fn) (
(generate_fn) greyc_gen<unsigned short>),
im_stop_many, arry, greyc ) )
return( -1 );
break;
case IM_BANDFMT_FLOAT:
if( im_generate( out,
im_start_many,
(im_generate_fn) (
(generate_fn) greyc_gen<float>),
im_stop_many, arry, greyc ) )
return( -1 );
break;
default:
im_error( "GREYCstoration",
"%s", _( "unsupported type: "
"uchar, ushort and float only" ) );
return( -1 );
}
return( 0 );
}

View File

@ -0,0 +1,164 @@
/* Function dispatch tables for cimg wrappers.
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
static int
greyc_vec( im_object *argv )
{
IMAGE *src = (IMAGE *) argv[0];
IMAGE *dst = (IMAGE *) argv[1];
int iterations = *((int *) argv[2]);
double amplitude = *((double *) argv[3]);
double sharpness = *((double *) argv[4]);
double anisotropy = *((double *) argv[5]);
double alpha = *((double *) argv[6]);
double sigma = *((double *) argv[7]);
double dl = *((double *) argv[8]);
double da = *((double *) argv[9]);
double gauss_prec = *((double *) argv[10]);
int interpolation = *((int *) argv[11]);
int fast_approx = *((int *) argv[12]);
if( im_greyc_mask( src, dst, NULL,
iterations,
amplitude, sharpness, anisotropy,
alpha, sigma,
dl, da, gauss_prec,
interpolation, fast_approx ) )
return( -1 );
return( 0 );
}
static im_arg_desc greyc_arg_types[] = {
IM_INPUT_IMAGE( "src" ),
IM_OUTPUT_IMAGE( "dst" ),
IM_INPUT_INT( "iterations" ),
IM_INPUT_DOUBLE( "amplitude" ),
IM_INPUT_DOUBLE( "sharpness" ),
IM_INPUT_DOUBLE( "anisotropy" ),
IM_INPUT_DOUBLE( "alpha" ),
IM_INPUT_DOUBLE( "sigma" ),
IM_INPUT_DOUBLE( "dl" ),
IM_INPUT_DOUBLE( "da" ),
IM_INPUT_DOUBLE( "gauss_prec" ),
IM_INPUT_INT( "interpolation" ),
IM_INPUT_INT( "fast_approx" )
};
static im_function greyc_desc = {
"im_greyc", /* Name */
"noise-removing filter", /* Description */
(im_fn_flags) (IM_FN_TRANSFORM | IM_FN_PIO),/* Flags */
greyc_vec, /* Dispatch function */
IM_NUMBER( greyc_arg_types ), /* Size of arg list */
greyc_arg_types /* Arg list */
};
static int
greyc_mask_vec( im_object *argv )
{
IMAGE *src = (IMAGE *) argv[0];
IMAGE *dst = (IMAGE *) argv[1];
IMAGE *mask = (IMAGE *) argv[2];
int iterations = *((int *) argv[3]);
double amplitude = *((double *) argv[4]);
double sharpness = *((double *) argv[5]);
double anisotropy = *((double *) argv[6]);
double alpha = *((double *) argv[7]);
double sigma = *((double *) argv[8]);
double dl = *((double *) argv[9]);
double da = *((double *) argv[10]);
double gauss_prec = *((double *) argv[11]);
int interpolation = *((int *) argv[12]);
int fast_approx = *((int *) argv[13]);
if( im_greyc_mask( src, dst, mask,
iterations,
amplitude, sharpness, anisotropy,
alpha, sigma,
dl, da, gauss_prec,
interpolation, fast_approx ) )
return( -1 );
return( 0 );
}
static im_arg_desc greyc_mask_arg_types[] = {
IM_INPUT_IMAGE( "src" ),
IM_OUTPUT_IMAGE( "dst" ),
IM_INPUT_IMAGE( "mask" ),
IM_INPUT_INT( "iterations" ),
IM_INPUT_DOUBLE( "amplitude" ),
IM_INPUT_DOUBLE( "sharpness" ),
IM_INPUT_DOUBLE( "anisotropy" ),
IM_INPUT_DOUBLE( "alpha" ),
IM_INPUT_DOUBLE( "sigma" ),
IM_INPUT_DOUBLE( "dl" ),
IM_INPUT_DOUBLE( "da" ),
IM_INPUT_DOUBLE( "gauss_prec" ),
IM_INPUT_INT( "interpolation" ),
IM_INPUT_INT( "fast_approx" )
};
static im_function greyc_mask_desc = {
"im_greyc_mask", /* Name */
"noise-removing filter, with a mask", /* Description */
(im_fn_flags) (IM_FN_TRANSFORM | IM_FN_PIO),/* Flags */
greyc_mask_vec, /* Dispatch function */
IM_NUMBER( greyc_mask_arg_types ),/* Size of arg list */
greyc_mask_arg_types /* Arg list */
};
static im_function *function_list[] = {
&greyc_desc,
&greyc_mask_desc
};
/* Package of functions.
*/
im_package im__cimg = {
"cimg",
IM_NUMBER( function_list ),
function_list
};

View File

@ -0,0 +1,32 @@
noinst_LTLIBRARIES = libcolour.la
libcolour_la_SOURCES = \
colour.c \
colour_dispatch.c \
derived.c \
im_icc_transform.c \
im_LCh2Lab.c \
im_LCh2UCS.c \
im_Lab2LCh.c \
im_Lab2LabQ.c \
im_Lab2LabS.c \
im_Lab2XYZ.c \
im_LabQ2Lab.c \
im_LabQ2LabS.c \
im_LabQ2disp.c \
im_LabS2LabQ.c \
im_LabS2Lab.c \
im_lab_morph.c \
im_UCS2LCh.c \
im_XYZ2Lab.c \
im_XYZ2Yxy.c \
im_float2rad.c \
im_Yxy2XYZ.c \
im_XYZ2disp.c \
im_dE00_fromLab.c \
im_dECMC_fromLab.c \
im_dE_fromLab.c \
im_disp2XYZ.c \
im_rad2float.c
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

1125
libvips/colour/colour.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

214
libvips/colour/derived.c Normal file
View File

@ -0,0 +1,214 @@
/* Derived colour space functions.
*
* 14/9/95 JC
* - horrible error killed im_dE_fromXYZ() and im_dE_fromdisp()
* 4/3/98 JC
* - sRGB added
* 17/6/99 JC
* - minor reformatting
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* LabQ to XYZ.
*/
int
im_LabQ2XYZ( IMAGE *in, IMAGE *out )
{
IMAGE *t1;
if( !(t1 = im_open_local( out, "im_LabQ2XYZ:1", "p" )) ||
im_LabQ2Lab( in, t1 ) ||
im_Lab2XYZ( t1, out ) )
return( -1 );
return( 0 );
}
/* Lab to UCS.
*/
int
im_Lab2UCS( IMAGE *in, IMAGE *out )
{
IMAGE *t1;
if( !(t1 = im_open_local( out, "im_Lab2UCS:1", "p" )) ||
im_Lab2LCh( in, t1 ) ||
im_LCh2UCS( t1, out ) )
return( -1 );
return( 0 );
}
int
im_UCS2Lab( IMAGE *in, IMAGE *out )
{
IMAGE *t1;
if( !(t1 = im_open_local( out, "im_UCS2Lab intermediate", "p" )) ||
im_UCS2LCh( in, t1 ) ||
im_LCh2Lab( t1, out ) )
return( -1 );
return( 0 );
}
int
im_UCS2XYZ( IMAGE *in, IMAGE *out )
{
IMAGE *t1;
if( !(t1 = im_open_local( out, "im_UCS2XYZ intermediate", "p" )) ||
im_UCS2Lab( in, t1 ) ||
im_Lab2XYZ( t1, out ) )
return( -1 );
return( 0 );
}
int
im_XYZ2UCS( IMAGE *in, IMAGE *out )
{
IMAGE *t1;
if( !(t1 = im_open_local( out, "im_XYZ2UCS intermediate", "p" )) ||
im_XYZ2Lab( in, t1 ) ||
im_Lab2UCS( t1, out ) )
return( -1 );
return( 0 );
}
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 );
}
int
im_XYZ2sRGB( IMAGE *in, IMAGE *out )
{
if( im_XYZ2disp( in, out, im_col_displays( 7 ) ) )
return( -1 );
out->Type = IM_TYPE_sRGB;
return( 0 );
}
int
im_sRGB2XYZ( IMAGE *in, IMAGE *out )
{
if( im_disp2XYZ( in, out, im_col_displays( 7 ) ) )
return( -1 );
return( 0 );
}
int
im_dECMC_fromdisp( IMAGE *im1, IMAGE *im2,
IMAGE *out, struct im_col_display *d )
{
IMAGE *t1, *t2, *t3, *t4;
if( !(t1 = im_open_local( out, "im_dECMC_fromdisp:1", "p" )) ||
!(t2 = im_open_local( out, "im_dECMC_fromdisp:2", "p" )) ||
!(t3 = im_open_local( out, "im_dECMC_fromdisp:3", "p" )) ||
!(t4 = im_open_local( out, "im_dECMC_fromdisp:4", "p" )) ||
im_disp2XYZ( im1, t1, d ) ||
im_XYZ2Lab( t1, t2 ) ||
im_disp2XYZ( im2, t3, d ) ||
im_XYZ2Lab( t3, t4 ) ||
im_dECMC_fromLab( t2, t4, out ) )
return( -1 );
return( 0 );
}
int
im_dE_fromXYZ( IMAGE *im1, IMAGE *im2, IMAGE *out )
{
IMAGE *t1, *t2;
if( !(t1 = im_open_local( out, "im_dE_fromXYZ:1", "p" )) ||
!(t2 = im_open_local( out, "im_dE_fromXYZ:2", "p" )) ||
im_XYZ2Lab( im1, t1 ) ||
im_XYZ2Lab( im2, t2 ) ||
im_dE_fromLab( t1, t2, out ) )
return( -1 );
return( 0 );
}
int
im_dE_fromdisp( IMAGE *im1, IMAGE *im2, IMAGE *out, struct im_col_display *d )
{
IMAGE *t1, *t2;
if( !(t1 = im_open_local( out, "im_dE_fromdisp:1", "p" )) ||
!(t2 = im_open_local( out, "im_dE_fromdisp:2", "p" )) ||
im_disp2XYZ( im1, t1, d ) ||
im_disp2XYZ( im2, t2, d ) ||
im_dE_fromXYZ( t1, t2, out ) )
return( -1 );
return( 0 );
}
int
im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *d )
{
IMAGE *t1;
if( !(t1 = im_open_local( out, "im_disp2Lab:1", "p" )) ||
im_disp2XYZ( in, t1, d ) ||
im_XYZ2Lab( t1, out ) )
return( -1 );
return( 0 );
}

108
libvips/colour/im_LCh2Lab.c Normal file
View File

@ -0,0 +1,108 @@
/* @(#) Turn LCh to Lab.
* @(#)
* @(#) Usage:
* @(#) im_LCh2Lab( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* 15/11/94 JC
* - error messages added
* - memory leak fixed
* 16/11/94 JC
* - uses im_wrap_oneonebuf() now
* 8/2/95 JC
* - im_wrap v2
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Process a buffer of data.
*/
void
imb_LCh2Lab( float *p, float *q, int n )
{
int x;
for( x = 0; x < n; x++ ) {
float L = p[0];
float C = p[1];
float h = p[2];
float a, b;
p += 3;
a = C * cos( IM_RAD( h ) );
b = C * sin( IM_RAD( h ) );
q[0] = L;
q[1] = a;
q[2] = b;
q += 3;
}
}
int
im_LCh2Lab( IMAGE *in, IMAGE *out )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_LCh2Lab: 3-band float uncoded input only" );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_LAB;
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LCh2Lab, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,99 @@
/* @(#) Turn LCh to UCS.
* @(#)
* @(#) Usage:
* @(#) im_LCh2UCS( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* Modified:
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Our main loop.
*/
void
imb_LCh2UCS( float *p, float *q, int n )
{
int x;
for( x = 0; x < n; x++ ) {
float L = p[0];
float C = p[1];
float h = p[2];
p += 3;
/* Turn to UCS.
*/
q[0] = im_col_L2Lucs( L );
q[1] = im_col_C2Cucs( C );
q[2] = im_col_Ch2hucs( C, h );
q += 3;
}
}
int
im_LCh2UCS( IMAGE *in, IMAGE *out )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_LCh2UCS: 3-band uncoded float input only" );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_UCS;
/* Process!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LCh2UCS, NULL, NULL ) )
return( -1 );
return( 0 );
}

102
libvips/colour/im_Lab2LCh.c Normal file
View File

@ -0,0 +1,102 @@
/* @(#) Turn Lab to LCh
* @(#)
* @(#) Usage:
* @(#) im_Lab2LCh( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Our main loop.
*/
void
imb_Lab2LCh( float *p, float *q, int n )
{
int x;
for( x = 0; x < n; x++ ) {
float L = p[0];
float a = p[1];
float b = p[2];
float C, h;
p += 3;
C = sqrt( a * a + b * b );
h = im_col_ab2h( a, b );
q[0] = L;
q[1] = C;
q[2] = h;
q += 3;
}
}
int
im_Lab2LCh( IMAGE *in, IMAGE *out )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_Lab2LCh: 3-band uncoded float input only" );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_LCH;
/* Process!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_Lab2LCh, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,158 @@
/* @(#) im_Lab2LabQ: quantise FLOAT Lab image into 10 11 11 format
* 4 bytes per pel: l a b lsbs
* this is an image wrapper which calls line-wise packing
* Copyright K.Martinez 3/5/93
* Modified:
* 7/6/93 JC
* - adapted for partial v2
* 5/5/94 JC
* - some nint->+0.5, for speed and to ease portability
* - other nint->rint
* - now inclues <math.h>!
* 15/11/94 JC
* - all nint(), rint() removed for speed
* - now -128 rather than -127 for a, b
* - checks input type properly
* 16/11/94 JC
* - uses new im_wrap_oneonebuf()
* 22/5/95 JC
* - changed L to scale by 10.24, not 10.23
* 11/7/95 JC
* - now uses IM_RINT() for rounding
* 4/9/97 JC
* - L* = 100.0 now allowed
* 5/11/00 JC
* - go int earlier for speed up
* 20/6/02 JC
* - oops, were not clipping a/b range correctly
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* @(#) convert float Lab to packed Lab32 format 10 11 11 bits
* works only on buffers, not IMAGEs
* Copyright 1993 K.Martinez
* Modified: 3/5/93, 16/6/93
*/
void
imb_Lab2LabQ( float *inp, unsigned char *outbuf, int n )
{
float *f, fval;
int lsbs, intv;
int Xc;
unsigned char *out;
out = outbuf;
f = inp;
for( Xc = 0; Xc < n; Xc++) {
/* Scale L up to 10 bits. Add 0.5 rather than call IM_RINT for
* speed. This will not round negatives correctly! But this
* does not matter, since L is >0. L*=100.0 -> 1023.
*/
intv = 10.23 * f[0] + 0.5; /* scale L up to 10 bits */
if( intv > 1023 )
intv = 1023;
if( intv < 0 )
intv = 0;
lsbs = (intv & 0x3) << 6; /* 00000011 -> 11000000 */
out[0] = (intv >> 2); /* drop bot 2 bits and store */
fval = 8.0 * f[1]; /* do a */
intv = IM_RINT( fval );
if( intv > 1023 )
intv = 1023;
else if( intv < -1024 )
intv = -1024;
/* Break into bits.
*/
lsbs |= (intv & 0x7) << 3; /* 00000111 -> 00111000 */
out[1] = (intv >> 3); /* drop bot 3 bits & store */
fval = 8.0 * f[2]; /* do b */
intv = IM_RINT( fval );
if( intv > 1023 )
intv = 1023;
else if( intv < -1024 )
intv = -1024;
lsbs |= (intv & 0x7);
out[2] = (intv >> 3);
out[3] = lsbs; /* store lsb band */
f += 3;
out += 4;
}
}
int
im_Lab2LabQ( IMAGE *labim, IMAGE *outim )
{
/* Check for uncoded Lab type
*/
if( labim->Coding != IM_CODING_NONE ) {
im_errormsg( "im_Lab2LabQ: uncoded input only" );
return( -1 );
}
if( labim->BandFmt != IM_BANDFMT_FLOAT || labim->Bands != 3 ) {
im_errormsg( "im_Lab2LabQ: three-band float input only" );
return( -1 );
}
/* Set up output image.
*/
if( im_cp_desc( outim, labim ) )
return( -1 );
outim->Bands = 4;
outim->Type = IM_TYPE_LAB;
outim->BandFmt = IM_BANDFMT_UCHAR;
outim->Bbits = 8;
outim->Coding = IM_CODING_LABQ;
/* Process.
*/
if( im_wrapone( labim, outim,
(im_wrapone_fn) imb_Lab2LabQ, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,92 @@
/* @(#) im_Lab2LabS: quantise FLOAT Lab image into signed short format
* 12/12/02 JC
* - from im_Lab2LabQ
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
void
imb_Lab2LabS( float *in, signed short *out, int n )
{
float *p = in;
signed short *q = out;
int c;
for( c = 0; c < n; c++ ) {
q[0] = p[0] * (32767.0 / 100.0);
q[1] = p[1] * (32768.0 / 128.0);
q[2] = p[2] * (32768.0 / 128.0);
q += 3;
p += 3;
}
}
int
im_Lab2LabS( IMAGE *labim, IMAGE *outim )
{
/* Check for uncoded Lab type
*/
if( labim->Coding != IM_CODING_NONE ) {
im_errormsg( "im_Lab2LabS: uncoded input only" );
return( -1 );
}
if( labim->BandFmt != IM_BANDFMT_FLOAT || labim->Bands != 3 ) {
im_errormsg( "im_Lab2LabS: three-band float input only" );
return( -1 );
}
/* Set up output image.
*/
if( im_cp_desc( outim, labim ) )
return( -1 );
outim->Type = IM_TYPE_LABS;
outim->BandFmt = IM_BANDFMT_SHORT;
outim->Bbits = IM_BBITS_SHORT;
/* Process.
*/
if( im_wrapone( labim, outim,
(im_wrapone_fn) imb_Lab2LabS, NULL, NULL ) )
return( -1 );
return( 0 );
}

147
libvips/colour/im_Lab2XYZ.c Normal file
View File

@ -0,0 +1,147 @@
/* @(#) Turn Lab to XYZ colourspace.
* @(#)
* @(#) Usage:
* @(#) im_Lab2XYZ( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* Modified:
* 15/11/94 JC
* - ANSIfied
* - sets Type of output
* - better error messages
* 16/11/94 JC
* - partialed
* - in-line conversion
* 8/2/95 JC
* - new im_wrapone function
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Process a buffer of data.
*/
void
imb_Lab2XYZ( float *p, float *q, int n, im_colour_temperature *temp )
{
int x;
for( x = 0; x < n; x++ ) {
float L, a, b;
float X, Y, Z;
double cby, tmp;
L = p[0];
a = p[1];
b = p[2];
p += 3;
if( L < 8.0 ) {
Y = (L * temp->Y0) / 903.3;
cby = 7.787 * (Y / temp->Y0) + 16.0 / 116.0;
}
else {
cby = (L + 16.0) / 116.0;
Y = temp->Y0 * cby * cby * cby;
}
tmp = a / 500.0 + cby;
if( tmp < 0.2069 )
X = temp->X0 * (tmp - 0.13793) / 7.787;
else
X = temp->X0 * tmp * tmp * tmp;
tmp = cby - b / 200.0;
if( tmp < 0.2069 )
Z = temp->Z0 * (tmp - 0.13793) / 7.787;
else
Z = temp->Z0 * tmp * tmp * tmp;
/* Write.
*/
q[0] = X;
q[1] = Y;
q[2] = Z;
q += 3;
}
}
int
im_Lab2XYZ_temp( IMAGE *in, IMAGE *out, double X0, double Y0, double Z0 )
{
im_colour_temperature *temp;
/* Check input image.
*/
if( !(temp = IM_NEW( out, im_colour_temperature )) )
return( -1 );
if( in->Bands != 3 ||
in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_Lab2XYZ", "%s", _( "not 3-band uncoded float" ) );
return( -1 );
}
/* Prepare the output image.
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_XYZ;
/* Process!
*/
temp->X0 = X0;
temp->Y0 = Y0;
temp->Z0 = Z0;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_Lab2XYZ, temp, NULL ) )
return( -1 );
return( 0 );
}
int
im_Lab2XYZ( IMAGE *in, IMAGE *out )
{
return( im_Lab2XYZ_temp( in, out, IM_D65_X0, IM_D65_Y0, IM_D65_Z0 ) );
}

View File

@ -0,0 +1,133 @@
/* @(#) LabQ2Lab convert Lab 32bit packed format to float Lab
@(#) uses imb_LabQ2Lab
Copyright Kirk Martinez 2/5/1993
Modified: 16/6/93
* 7/6/93 JC
* - adapted for partial v2
* 16/11/94 JC
* - adapted to new im_wrap_oneonebuf() function.
* 9/2/95 JC
* - new im_wrapone function
* 22/5/95 JC
* - changed char to unsigned char for RS/6000
* - small tidies and speed-ups
* 4/9/97 JC
* - L* = 100.0 now handled correctly
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* imb_LabQ2Lab: CONVERT n pels from packed 32bit Lab to float values
* in a buffer
* ARGS: PEL *inp pointer to first byte of Lab32 buffer
* float *outbuf destination buffer
* int n number of pels to process
* (C) K.Martinez 2/5/93
*/
void
imb_LabQ2Lab( PEL *inp, float *outbuf, int n )
{
signed char *b; /* to read input bytes */
int l;
int lsbs; /* for lsbs byte */
int c; /* counter */
float *out;
/* Read input with a signed pointer to get signed ab easily.
*/
b = (signed char *) inp;
out = outbuf;
for( c = 0; c < n; c++ ) {
/* Get extra bits.
*/
lsbs = ((unsigned char *) b)[3];
/* Build L.
*/
l = ((unsigned char *)b)[0];
l = (l << 2) | (lsbs >> 6);
out[0] = (float) l * (100.0 / 1023.0);
/* Build a.
*/
l = (b[1] << 3) | ((lsbs >> 3) & 0x7);
out[1] = (float) l * 0.125;
/* And b.
*/
l = (b[2] << 3) | (lsbs & 0x7);
out[2] = (float) l * 0.125;
b += 4;
out += 3;
}
}
/* unpack a Lab32 ie 10,11,11 Lab image into float image
this is a wrapper around the buffer processing function
(C) K.Martinez 2/5/93
*/
int
im_LabQ2Lab( IMAGE *labim, IMAGE *outim )
{
/* check for coded Lab type
*/
if( labim->Coding != IM_CODING_LABQ ) {
im_errormsg( "im_LabQ2Lab: not a packed Lab image" );
return( -1 );
}
/* set up output image
*/
if( im_cp_desc( outim, labim ) )
return( -1 );
outim->Bands = 3;
outim->Type = IM_TYPE_LAB;
outim->BandFmt = IM_BANDFMT_FLOAT;
outim->Bbits = 32;
outim->Coding = IM_CODING_NONE;
if( im_wrapone( labim, outim,
(im_wrapone_fn) imb_LabQ2Lab, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,125 @@
/* @(#) im_LabQ2LabS() - convert IM_CODING_LABQ format to three band signed short.
* @(#) Justify to get msb in bit 15.
* @(#)
* @(#) int im_LabQ2LabS( IMAGE *in, IMAGE *out )
* @(#)
* @(#)
*
* 17/11/93 JC
* - adapted from im_LabQ2Lab()
* 16/11/94 JC
* - uses new im_wrap_oneonebuf() fn
* 9/2/95 JC
* - new im_wrapone function
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* CONVERT n pels from packed 32bit Lab to signed short.
*/
void
imb_LabQ2LabS( unsigned char *in, signed short *out, int n )
{
int c;
unsigned char *p = in;
unsigned char ext;
signed short *q = out;
signed short l, a, b;
for( c = 0; c < n; c++ ) {
/* Get most significant 8 bits of lab.
*/
l = p[0] << 7;
a = p[1] << 8;
b = p[2] << 8;
/* Get x-tra bits.
*/
ext = p[3];
p += 4;
/* Shift and mask in to lab.
*/
l |= (unsigned char) (ext & 0xc0) >> 1;
a |= (ext & 0x38) << 2;
b |= (ext & 0x7) << 5;
/* Write!
*/
q[0] = l;
q[1] = a;
q[2] = b;
q += 3;
}
}
/* unpack a Lab32 ie 10,11,11 Lab image into signed short image
this is a wrapper around the buffer processing function
(C) K.Martinez 2/5/93
*/
int
im_LabQ2LabS( IMAGE *labim, IMAGE *outim )
{
/* check for coded Lab type
*/
if( labim->Coding != IM_CODING_LABQ ) {
im_errormsg( "im_LabQ2LabS: not a packed Lab image" );
return( -1 );
}
/* set up output image
*/
if( im_cp_desc( outim, labim ) )
return( -1 );
outim->Bands = 3;
outim->Type = IM_TYPE_LABS;
outim->BandFmt = IM_BANDFMT_SHORT;
outim->Bbits = IM_BBITS_SHORT;
outim->Coding = IM_CODING_NONE;
/* Produce output.
*/
if( im_wrapone( labim, outim,
(im_wrapone_fn) imb_LabQ2LabS, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,209 @@
/* @(#) Turn Lab 32bit packed format into displayable rgb. Fast, but very
* @(#) inaccurate: for display only!
* @(#)
* @(#) Usage:
* @(#) int im_LabQ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d )
* @(#)
* @(#) Returns: -1 on error, else 0
*
* 5/11/97 Steve Perry
* - adapted from old ip code
* 7/11/97 JC
* - small tidies, added to VIPS
* - LUT build split into separate function
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Hold a display characterisation, and a set of tables
* computed from that.
*/
typedef struct {
struct im_col_display *disp;
struct im_col_tab_disp *dtab;
PEL red[ 64 * 64 * 64 ];
PEL green[ 64 * 64 * 64 ];
PEL blue[ 64 * 64 * 64 ];
} CalibrateInfo;
/* Do our own indexing of the arrays, to make sure we get efficient mults.
*/
#define index( L, A, B ) (L + (A << 6) + (B << 12))
/* Process a buffer of data.
*/
static void
imb_LabQ2disp( PEL *p, PEL *q, int n, CalibrateInfo *cal )
{
int x, t;
/* Current error.
*/
int le = 0;
int ae = 0;
int be = 0;
for( x = 0; x < n; x++ ) {
/* Get colour, add in error from previous pixel.
*/
int L = p[0] + le;
int A = (signed char) p[1] + ae;
int B = (signed char) p[2] + be;
p += 4;
/* Look out for overflow.
*/
L = IM_MIN( 255, L );
A = IM_MIN( 127, A );
B = IM_MIN( 127, B );
/* Find new quant error. This will always be +ve.
*/
le = L & 3;
ae = A & 3;
be = B & 3;
/* Scale to 0-63.
*/
L = (L >> 2) & 63;
A = (A >> 2) & 63;
B = (B >> 2) & 63;
/* Convert to RGB.
*/
t = index( L, A, B );
q[0] = cal->red[t];
q[1] = cal->green[t];
q[2] = cal->blue[t];
q += 3;
}
}
/* Build Lab->disp tables.
*/
void *
im_LabQ2disp_build_table( IMAGE *out, struct im_col_display *d )
{
CalibrateInfo *cal;
int l, a, b;
int t;
if( !(cal = IM_NEW( out, CalibrateInfo )) )
return( NULL );
cal->disp = d;
if( !(cal->dtab = im_col_make_tables_RGB( out, d ) ) ) {
if( !out )
im_free( cal );
return( NULL );
}
/* Build our tables.
*/
for( l = 0; l < 64; l++ ) {
for( a = 0; a < 64; a++ ) {
for( b = 0; b < 64; b++ ) {
/* Scale to lab space.
*/
float L = (l << 2) * (100.0/256.0);
float A = (signed char) (a << 2);
float B = (signed char) (b << 2);
float X, Y, Z;
int rb, gb, bb;
int oflow;
/* Convert to XYZ.
*/
im_col_Lab2XYZ( L, A, B, &X, &Y, &Z );
/* Convert to display.
*/
im_col_XYZ2rgb( cal->disp, cal->dtab,
X, Y, Z, &rb, &gb, &bb, &oflow );
/* Save RGB.
*/
t = index( l, a, b );
cal->red[t] = rb;
cal->green[t] = gb;
cal->blue[t] = bb;
}
}
}
return( (void *) cal );
}
int
im_LabQ2disp_table( IMAGE *in, IMAGE *out, void *table )
{
CalibrateInfo *cal = (CalibrateInfo *) table;
if ( in->Coding != IM_CODING_LABQ ) {
im_errormsg( "im_LabQ2Lab: not a packed Lab image" );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Bands = 3;
out->Bbits = IM_BBITS_BYTE;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Coding = IM_CODING_NONE;
out->Type = IM_TYPE_RGB;
if( im_wrapone( in, out, (im_wrapone_fn) imb_LabQ2disp, cal, NULL ) )
return( -1 );
return( 0 );
}
int
im_LabQ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d )
{
void *table;
if( !(table = im_LabQ2disp_build_table( out, d )) ||
im_LabQ2disp_table( in, out, table ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,96 @@
/* @(#) im_LabS2Lab() - convert short LAB format to Lab.
* @(#)
* @(#) int im_LabS2Lab( IMAGE *in, IMAGE *out )
* @(#)
* @(#)
*
* 12/12/02 JC
* - adapted from im_LabS2LabQ()
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Convert n pels from signed short to Lab.
*/
void
imb_LabS2Lab( signed short *in, float *out, int n )
{
signed short *p = in;
float *q = out;
int c;
for( c = 0; c < n; c++ ) {
q[0] = p[0] / (32767.0 / 100.0);
q[1] = p[1] / (32768.0 / 128.0);
q[2] = p[2] / (32768.0 / 128.0);
p += 3;
q += 3;
}
}
int
im_LabS2Lab( IMAGE *in, IMAGE *out )
{
/* Check type.
*/
if( in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_LabS2Lab: not an uncoded image" );
return( -1 );
}
if( in->BandFmt != IM_BANDFMT_SHORT || in->Bands != 3 ) {
im_errormsg( "im_LabS2Lab: not a 3-band signed short image" );
return( -1 );
}
/* Set up output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Bbits = IM_BBITS_FLOAT;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LabS2Lab, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,151 @@
/* @(#) im_LabS2LabQ() - convert short LAB format to IM_CODING_LABQ.
* @(#)
* @(#) int im_LabS2LabQ( IMAGE *in, IMAGE *out )
* @(#)
* @(#)
*
* 17/11/93 JC
* - adapted from im_LabQ2LabS()
* 16/11/94 JC
* - adapted to new im_wrap_oneonebuf() function
* 15/6/95 JC
* - oops! rounding was broken
* 6/6/95 JC
* - added round-to-nearest
* - somewhat slower ...
* 21/12/99 JC
* - a/b ==0 rounding was broken
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Convert n pels from signed short to IM_CODING_LABQ.
*/
void
imb_LabS2LabQ( signed short *in, unsigned char *out, int n )
{
int c;
signed short *p = in;
int l, a, b;
unsigned char *q = out;
unsigned char ext;
for( c = 0; c < n; c++ ) {
/* Get LAB, rounding to 10, 11, 11.
*/
l = p[0] + 16;
if( l < 0 )
l = 0;
else if( l > 32767 )
l = 32767;
l >>= 5;
/* Make sure we round -ves in the right direction!
*/
a = p[1];
if( a >= 0 )
a += 16;
else
a -= 16;
if( a < -32768 )
a = -32768;
else if( a > 32767 )
a = 32767;
a >>= 5;
b = p[2];
if( b >= 0 )
b += 16;
else
b -= 16;
if( b < -32768 )
b = -32768;
else if( b > 32767 )
b = 32767;
b >>= 5;
p += 3;
/* Extract top 8 bits.
*/
q[0] = l >> 2;
q[1] = a >> 3;
q[2] = b >> 3;
/* Form extension byte.
*/
ext = (l << 6) & 0xc0;
ext |= (a << 3) & 0x38;
ext |= b & 0x7;
q[3] = ext;
q += 4;
}
}
int
im_LabS2LabQ( IMAGE *in, IMAGE *out )
{
/* Check type.
*/
if( in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_LabS2LabQ: not an uncoded image" );
return( -1 );
}
if( in->BandFmt != IM_BANDFMT_SHORT || in->Bands != 3 ) {
im_errormsg( "im_LabS2LabQ: not a 3-band signed short image" );
return( -1 );
}
/* Set up output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Bands = 4;
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = 8;
out->Coding = IM_CODING_LABQ;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LabS2LabQ, NULL, NULL ) )
return( -1 );
return( 0 );
}

109
libvips/colour/im_UCS2LCh.c Normal file
View File

@ -0,0 +1,109 @@
/* @(#) Turn UCS to LCh
* @(#)
* @(#) Usage:
* @(#) im_UCS2LCh( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* 15/11/94 JC
* - error messages added
* - memory leak fixed
* 16/11/94 JC
* - uses im_wrap_oneonebuf() now
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Process a buffer of data.
*/
void
imb_UCS2LCh( float *p, float *q, int n )
{
int x;
for( x = 0; x < n; x++ ) {
float Lucs = p[0];
float Cucs = p[1];
float hucs = p[2];
/* Turn from UCS.
*/
float C = im_col_Cucs2C( Cucs );
float h = im_col_Chucs2h( C, hucs );
float L = im_col_Lucs2L( Lucs );
p += 3;
q[0] = L;
q[1] = C;
q[2] = h;
q += 3;
}
}
int
im_UCS2LCh( IMAGE *in, IMAGE *out )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_UCS2LCh: 3-band float uncoded input only" );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in) )
return( -1 );
out->Type = IM_TYPE_LCH;
/* Do the processing.
*/
im_col_make_tables_UCS();
if( im_wrapone( in, out,
(im_wrapone_fn) imb_UCS2LCh, NULL, NULL ) )
return( -1 );
return( 0 );
}

190
libvips/colour/im_XYZ2Lab.c Normal file
View File

@ -0,0 +1,190 @@
/* @(#) Turn XYZ to Lab colourspace.
* @(#)
* @(#) Usage:
* @(#) im_XYZ2Lab( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* Modifed:
* 16/11/94 JC
* - uses im_wrapone()
* - in-line conversion
* 27/1/03 JC
* - swapped cbrt() for pow(), more portable
* 12/11/04
* - swapped pow() for cbrt() again, pow() is insanely slow on win32
* - added a configure test for cbrt().
* 23/11/04
* - use a large LUT instead, about 5x faster
* 23/11/06
* - ahem, build the LUT outside the eval thread
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
#ifndef HAVE_CBRT
#define cbrt( X ) pow( (X), 1.0 / 3.0 )
#endif /*!HAVE_CBRT*/
/* Lookup table size.
*/
#define QUANT_ELEMENTS (100000)
float cbrt_table[QUANT_ELEMENTS];
void
imb_XYZ2Lab_tables( void )
{
static int built_tables = 0;
int was_built;
int i;
g_mutex_lock( im__global_lock );
was_built = built_tables;
built_tables = 1;
g_mutex_unlock( im__global_lock );
if( was_built )
return;
for( i = 0; i < QUANT_ELEMENTS; i++ ) {
float Y = (double) i / QUANT_ELEMENTS;
if( Y < 0.008856 )
cbrt_table[i] = 7.787 * Y + (16.0 / 116.0);
else
cbrt_table[i] = cbrt( Y );
}
}
/* Process a buffer of data.
*/
void
imb_XYZ2Lab( float *p, float *q, int n, im_colour_temperature *temp )
{
int x;
for( x = 0; x < n; x++ ) {
float nX, nY, nZ;
int i;
float f;
float cbx, cby, cbz;
nX = QUANT_ELEMENTS * p[0] / temp->X0;
nY = QUANT_ELEMENTS * p[1] / temp->Y0;
nZ = QUANT_ELEMENTS * p[2] / temp->Z0;
p += 3;
i = (int) nX;
if( i < 0 )
i = 0;
if( i > QUANT_ELEMENTS - 2 )
i = QUANT_ELEMENTS - 2;
f = nX - i;
cbx = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]);
i = (int) nY;
if( i < 0 )
i = 0;
if( i > QUANT_ELEMENTS - 2 )
i = QUANT_ELEMENTS - 2;
f = nY - i;
cby = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]);
i = (int) nZ;
if( i < 0 )
i = 0;
if( i > QUANT_ELEMENTS - 2 )
i = QUANT_ELEMENTS - 2;
f = nZ - i;
cbz = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]);
q[0] = 116.0 * cby - 16.0;
q[1] = 500.0 * (cbx - cby);
q[2] = 200.0 * (cby - cbz);
q += 3;
}
}
int
im_XYZ2Lab_temp( IMAGE *in, IMAGE *out,
double X0, double Y0, double Z0 )
{
im_colour_temperature *temp;
/* Check input image.
*/
if( !(temp = IM_NEW( out, im_colour_temperature )) )
return( -1 );
if( in->Bands != 3 ||
in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_XYZ2Lab", "%s", _( "not 3-band uncoded float" ) );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in) )
return( -1 );
out->Type = IM_TYPE_LAB;
/* Do the processing.
*/
imb_XYZ2Lab_tables();
temp->X0 = X0;
temp->Y0 = Y0;
temp->Z0 = Z0;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_XYZ2Lab, temp, NULL ) )
return( -1 );
return( 0 );
}
int
im_XYZ2Lab( IMAGE *in, IMAGE *out )
{
return( im_XYZ2Lab_temp( in, out, IM_D65_X0, IM_D65_Y0, IM_D65_Z0 ) );
}

101
libvips/colour/im_XYZ2Yxy.c Normal file
View File

@ -0,0 +1,101 @@
/* @(#) Turn XYZ to Yxy colourspace.
* @(#)
* @(#) Usage:
* @(#) im_XYZ2Yxy( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* Modified:
* 29/5/02 JC
* - from lab2xyz
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Process a buffer of data.
*/
void
imb_XYZ2Yxy( float *p, float *q, int n )
{
int i;
for( i = 0; i < n; i++ ) {
float X = p[0];
float Y = p[1];
float Z = p[2];
double total = X + Y + Z;
float x, y;
p += 3;
x = X / total;
y = Y / total;
q[0] = Y;
q[1] = x;
q[2] = y;
q += 3;
}
}
int
im_XYZ2Yxy( IMAGE *in, IMAGE *out )
{
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_XYZ2Yxy: 3-band uncoded float input only" );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_YXY;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_XYZ2Yxy, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,165 @@
/* @(#) Turn XYZ files into displayable rgb.
* @(#)
* @(#) Usage:
* @(#) int im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d )
* @(#)
* @(#) Returns: -1 on error, else 0
*
* Author: J-P. Laurent
* Modified:
* 15/11/94 JC
* - error message added
* - out->Type set to IM_TYPE_RGB
* - memory leak fixed
* 16/11/94 JC
* - uses im_wrapone()
* 15/2/95 JC
* - oops! now uses PEL, not float for output pointer
* 2/1/96 JC
* - sometimes produced incorrect result at extrema
* - reformatted
* - now uses IM_RINT() and clip()
* 18/9/96 JC
* - some speed-ups ... 3x faster
* - slightly less accurate, but who cares
* - added out-of-mem check for table build
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Process a buffer of data.
*/
void
imb_XYZ2disp( float *p, PEL *q, int n,
struct im_col_tab_disp *table, struct im_col_display *d )
{
int x;
float rstep = (d->d_YCR - d->d_Y0R) / 1500.0;
float gstep = (d->d_YCG - d->d_Y0G) / 1500.0;
float bstep = (d->d_YCB - d->d_Y0B) / 1500.0;
for( x = 0; x < n; x++ ) {
float Yr, Yg, Yb;
int i;
int r, g, b;
float X = p[0];
float Y = p[1];
float Z = p[2];
p += 3;
/* Multiply through the matrix to get luminosity values.
*/
Yr = table->mat_XYZ2lum[0][0] * X
+ table->mat_XYZ2lum[0][1] * Y
+ table->mat_XYZ2lum[0][2] * Z;
Yg = table->mat_XYZ2lum[1][0] * X
+ table->mat_XYZ2lum[1][1] * Y
+ table->mat_XYZ2lum[1][2] * Z;
Yb = table->mat_XYZ2lum[2][0] * X
+ table->mat_XYZ2lum[2][1] * Y
+ table->mat_XYZ2lum[2][2] * Z;
/* Clip -ves.
*/
Yr = IM_MAX( Yr, d->d_Y0R );
Yg = IM_MAX( Yg, d->d_Y0G );
Yb = IM_MAX( Yb, d->d_Y0B );
/* Turn luminosity to colour value.
*/
i = IM_MIN( 1500, (Yr - d->d_Y0R) / rstep );
r = table->t_Yr2r[i];
i = IM_MIN( 1500, (Yg - d->d_Y0G) / gstep );
g = table->t_Yg2g[i];
i = IM_MIN( 1500, (Yb - d->d_Y0B) / bstep );
b = table->t_Yb2b[i];
/* Clip output.
*/
r = IM_MIN( r, d->d_Vrwr );
g = IM_MIN( g, d->d_Vrwg );
b = IM_MIN( b, d->d_Vrwb );
q[0] = r;
q[1] = g;
q[2] = b;
q += 3;
}
}
int
im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d )
{
struct im_col_tab_disp *table;
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_XYZ2disp",
"%s", _( "3-band uncoded float only" ) );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Bbits = IM_BBITS_BYTE;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Type = IM_TYPE_RGB;
/* Build the lookup tables
*/
if( !(table = im_col_make_tables_RGB( out, d )) )
return( -1 );
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_XYZ2disp, table, d ) )
return( -1 );
return( 0 );
}

102
libvips/colour/im_Yxy2XYZ.c Normal file
View File

@ -0,0 +1,102 @@
/* @(#) Turn Yxy to XYZ colourspace.
* @(#)
* @(#) Usage:
* @(#) im_Yxy2XYZ( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* Modified:
* 29/5/02 JC
* - from lab2xyz
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Process a buffer of data.
*/
void
imb_Yxy2XYZ( float *p, float *q, int n )
{
int i;
for( i = 0; i < n; i++ ) {
float Y = p[0];
float x = p[1];
float y = p[2];
double total;
float X, Z;
p += 3;
total = Y / y;
X = x * total;
Z = (X - x * X - x * Y) / x;
q[0] = X;
q[1] = Y;
q[2] = Z;
q += 3;
}
}
int
im_Yxy2XYZ( IMAGE *in, IMAGE *out )
{
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_Yxy2XYZ: 3-band uncoded float input only" );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_XYZ;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_Yxy2XYZ, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,110 @@
/* @(#) Calculate dE00 from two Lab images
* @(#)
* @(#) Usage:
* @(#) im_dE00_fromLab( im1, im2, im_out )
* @(#) IMAGE *im1, *im2, *im_out;
* @(#)
* @(#) float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* 10/10/02 JC
* - from dECMC
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Process a buffer.
*/
void
imb_dE00_fromLab( float **p, float *q, int n )
{
float *p1 = p[0];
float *p2 = p[1];
int x;
for( x = 0; x < n; x++ ) {
float L1 = p1[0];
float a1 = p1[1];
float b1 = p1[2];
float L2 = p2[0];
float a2 = p2[1];
float b2 = p2[2];
p1 += 3;
p2 += 3;
q[x] = im_col_dE00( L1, a1, b1, L2, a2, b2 );
}
}
int
im_dE00_fromLab( IMAGE *im1, IMAGE *im2, IMAGE *out )
{
IMAGE *invec[3];
/* Check input types.
*/
if( im1->Bands != 3 || im1->BandFmt != IM_BANDFMT_FLOAT ||
im1->Coding != IM_CODING_NONE ||
im2->Bands != 3 || im2->BandFmt != IM_BANDFMT_FLOAT ||
im2->Coding != IM_CODING_NONE ) {
im_errormsg( "im_dE00_fromLab: 3-band float only" );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_descv( out, im1, im2, NULL ) )
return( -1 );
out->Bbits = IM_BBITS_FLOAT;
out->Bands = 1;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Type = IM_TYPE_B_W;
/* Do the processing.
*/
invec[0] = im1; invec[1] = im2; invec[2] = NULL;
if( im_wrapmany( invec, out,
(im_wrapmany_fn) imb_dE00_fromLab, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,110 @@
/* @(#) Calculate dECMC from two Lab images
* @(#)
* @(#) Usage:
* @(#) im_dECMC_fromLab( im1, im2, im_out )
* @(#) IMAGE *im1, *im2, *im_out;
* @(#)
* @(#) float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* 5/8/98 JC
* - oops, wasn't testing input args correctly
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Process a buffer.
*/
void
imb_dECMC_fromLab( float **p, float *q, int n )
{
float *p1 = p[0];
float *p2 = p[1];
int x;
for( x = 0; x < n; x++ ) {
float L1 = p1[0];
float a1 = p1[1];
float b1 = p1[2];
float L2 = p2[0];
float a2 = p2[1];
float b2 = p2[2];
p1 += 3;
p2 += 3;
q[x] = im_col_dECMC( L1, a1, b1, L2, a2, b2 );
}
}
int
im_dECMC_fromLab( IMAGE *im1, IMAGE *im2, IMAGE *out )
{
IMAGE *invec[3];
/* Check input types.
*/
if( im1->Bands != 3 || im1->BandFmt != IM_BANDFMT_FLOAT ||
im1->Coding != IM_CODING_NONE ||
im2->Bands != 3 || im2->BandFmt != IM_BANDFMT_FLOAT ||
im2->Coding != IM_CODING_NONE ) {
im_errormsg( "im_dECMC_fromLab: 3-band float only" );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_descv( out, im1, im2, NULL ) )
return( -1 );
out->Bbits = IM_BBITS_FLOAT;
out->Bands = 1;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Type = IM_TYPE_B_W;
/* Do the processing.
*/
invec[0] = im1; invec[1] = im2; invec[2] = NULL;
if( im_wrapmany( invec, out,
(im_wrapmany_fn) imb_dECMC_fromLab, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,116 @@
/* @(#) Calculate dE (CIELAB standard) from two LAB images.
* @(#)
* @(#) Usage:
* @(#) im_dE_fromLab( im1, *im2, im_out )
* @(#) IMAGE *im1, *im2, *im_out;
* @(#)
* @(#) float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* Modified:
* 16/11/94 JC
* - partialed!
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Find the difference between two buffers of LAB data.
*/
void
imb_dE_fromLab( float **p, float *q, int n )
{
float *p1 = p[0];
float *p2 = p[1];
int x;
for( x = 0; x < n; x++ ) {
float L1 = p1[0];
float a1 = p1[1];
float b1 = p1[2];
float L2 = p2[0];
float a2 = p2[1];
float b2 = p2[2];
float dL, da, db;
p1 += 3;
p2 += 3;
dL = L1 - L2;
da = a1 - a2;
db = b1 - b2;
*q++ = sqrt( dL*dL + da*da + db*db );
}
}
int
im_dE_fromLab( IMAGE *im1, IMAGE *im2, IMAGE *out )
{
IMAGE *invec[3];
/* Check input image.
*/
if( im1->Bands != 3 || im1->BandFmt != IM_BANDFMT_FLOAT ||
im1->Coding != IM_CODING_NONE ||
im2->Bands != 3 || im2->BandFmt != IM_BANDFMT_FLOAT ||
im2->Coding != IM_CODING_NONE ) {
im_errormsg( "im_dE_fromLab: inputs should be 3 band float");
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_descv( out, im1, im2, NULL ) )
return( -1 );
out->Bbits = IM_BBITS_FLOAT;
out->Bands = 1;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Type = IM_TYPE_B_W;
/* Do the processing.
*/
invec[0] = im1; invec[1] = im2; invec[2] = NULL;
if( im_wrapmany( invec, out,
(im_wrapmany_fn) imb_dE_fromLab, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,116 @@
/* @(#) Turn displayable rgb files to XYZ.
* @(#)
* @(#) Usage:
* @(#) im_disp2XYZ( imagein, imageout, display )
* @(#) IMAGE *imagein, *imageout;
* @(#) struct im_col_display *display;
* @(#)
* @(#) uchar in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* Modified:
* 15/11/94 JC
* - memory leak fixed
* - error message added
* 16/11/94 JC
* - partialed
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Convert a buffer.
*/
void
imb_disp2XYZ( PEL *p, float *q, int n,
struct im_col_display *d, struct im_col_tab_disp *table )
{
int x;
for( x = 0; x < n; x++ ) {
int r = p[0];
int g = p[1];
int b = p[2];
float X, Y, Z;
p += 3;
im_col_rgb2XYZ(d, table, r, g, b, &X, &Y, &Z);
q[0] = X;
q[1] = Y;
q[2] = Z;
q += 3;
}
}
int
im_disp2XYZ( IMAGE *in, IMAGE *out, struct im_col_display *d )
{
struct im_col_tab_disp *table; /* pointer to the lookup tables */
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_UCHAR ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_disp2XYZ",
"%s", _( "input not 3-band uncoded char" ) );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Bbits = IM_BBITS_FLOAT;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Type = IM_TYPE_XYZ;
/* Prepare the lookup tables
*/
table = im_col_make_tables_RGB( out, d );
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_disp2XYZ, d, table ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,207 @@
/* Convert float to Radiance 32bit packed format
* 23/3/09
* - from im_rad2float and Radiance sources
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
Sections of this file from Greg Ward and Radiance with kind
permission. The Radience copyright notice appears below.
*/
/* ====================================================================
* The Radiance Software License, Version 1.0
*
* Copyright (c) 1990 - 2009 The Regents of the University of California,
* through Lawrence Berkeley National Laboratory. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes Radiance software
* (http://radsite.lbl.gov/)
* developed by the Lawrence Berkeley National Laboratory
* (http://www.lbl.gov/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
* and "The Regents of the University of California" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact radiance@radsite.lbl.gov.
*
* 5. Products derived from this software may not be called "Radiance",
* nor may "Radiance" appear in their name, without prior written
* permission of Lawrence Berkeley National Laboratory.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of Lawrence Berkeley National Laboratory. For more
* information on Lawrence Berkeley National Laboratory, please see
* <http://www.lbl.gov/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Begin copy-paste from Radiance sources.
*/
#define RED 0
#define GRN 1
#define BLU 2
#define CIEX 0 /* or, if input is XYZ... */
#define CIEY 1
#define CIEZ 2
#define EXP 3 /* exponent same for either format */
#define COLXS 128 /* excess used for exponent */
#define WHT 3 /* used for RGBPRIMS type */
#undef BYTE
#define BYTE unsigned char /* 8-bit unsigned integer */
typedef BYTE COLR[4]; /* red, green, blue (or X,Y,Z), exponent */
typedef float COLORV;
typedef COLORV COLOR[3]; /* red, green, blue (or X,Y,Z) */
#define copycolor(c1,c2) ((c1)[0]=(c2)[0],(c1)[1]=(c2)[1],(c1)[2]=(c2)[2])
static void
setcolr( COLR clr, double r, double g, double b ) /* assign a short color value */
{
double d;
int e;
d = r > g ? r : g;
if (b > d) d = b;
if (d <= 1e-32) {
clr[RED] = clr[GRN] = clr[BLU] = 0;
clr[EXP] = 0;
return;
}
d = frexp(d, &e) * 255.9999 / d;
if (r > 0.0)
clr[RED] = r * d;
else
clr[RED] = 0;
if (g > 0.0)
clr[GRN] = g * d;
else
clr[GRN] = 0;
if (b > 0.0)
clr[BLU] = b * d;
else
clr[BLU] = 0;
clr[EXP] = e + COLXS;
}
/* End copy-paste from Radiance sources.
*/
static void
float2rad( COLOR *inp, COLR *outbuf, int n )
{
while (n-- > 0) {
setcolr( outbuf[0], inp[0][RED], inp[0][GRN], inp[0][BLU] );
inp++;
outbuf++;
}
}
int
im_float2rad( IMAGE *in, IMAGE *out )
{
/* Must be 3-band float.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_float2rad", "%s",
_( "3-band float uncoded only" ) );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Bands = 4;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = im_bits_of_fmt( out->BandFmt );
out->Coding = IM_CODING_RAD;
if( im_wrapone( in, out,
(im_wrapone_fn) float2rad, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,821 @@
/* @(#) Transform images with little cms
* @(#)
*
* 26/4/02 JC
* 26/8/05
* - attach profiles and intents to output images
* - added im_icc_import_embedded() to import with an embedded profile
* 12/5/06
* - lock around cmsDoTransform
* 23/1/07
* - set RGB16 on 16-bit RGB export
* 6/4/09
* - catch lcms error messages
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#ifndef HAVE_LCMS
#include <vips/vips.h>
#include <vips/thread.h>
int
im_icc_present( void )
{
return( 0 );
}
int
im_icc_transform( IMAGE *in, IMAGE *out,
const char *input_profile_filename,
const char *output_profile_filename,
int intent )
{
im_error( "im_icc_transform", "%s",
_( "lcms library not linked to this VIPS" ) );
return( -1 );
}
int
im_icc_import( IMAGE *in, IMAGE *out,
const char *input_profile_filename, int intent )
{
im_error( "im_icc_import", "%s",
_( "lmcs library not linked to this VIPS" ) );
return( -1 );
}
int
im_icc_import_embedded( IMAGE *in, IMAGE *out, int intent )
{
im_error( "im_icc_import", "%s",
_( "lmcs library not linked to this VIPS" ) );
return( -1 );
}
int
im_icc_export_depth( IMAGE *in, IMAGE *out, int depth,
const char *output_profile_filename, int intent )
{
im_error( "im_icc_export_depth", "%s",
_( "lmcs library not linked to this VIPS" ) );
return( -1 );
}
int
im_icc_export( IMAGE *in, IMAGE *out,
const char *output_profile_filename, int intent )
{
im_error( "im_icc_export", "%s",
_( "lmcs library not linked to this VIPS" ) );
return( -1 );
}
int
im_icc_ac2rc( IMAGE *in, IMAGE *out, const char *profile_filename )
{
im_error( "im_icc_ac2rc", "%s",
_( "lmcs library not linked to this VIPS" ) );
return( -1 );
}
#else
#include <stdio.h>
#include <math.h>
#include <assert.h>
/* Has to be before VIPS to avoid nameclashes.
*/
#include <lcms.h>
#include <icc34.h>
#include <vips/vips.h>
#include <vips/colour.h>
#include <vips/region.h>
#include <vips/util.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Call lcms with up to this many pixels at once.
*/
#define PIXEL_BUFFER_SIZE (10000)
static const char *
decode_intent( int intent )
{
switch( intent ) {
case IM_INTENT_PERCEPTUAL: return( "PERCEPTUAL" );
case IM_INTENT_RELATIVE_COLORIMETRIC: return( "RELATIVE" );
case IM_INTENT_SATURATION: return( "SATURATION" );
case IM_INTENT_ABSOLUTE_COLORIMETRIC: return( "ABSOLUTE" );
default: return( "<unknown>" );
}
}
int
im_icc_present( void )
{
return( 1 );
}
/* Global state for a transform.
*/
typedef struct {
IMAGE *in;
IMAGE *out;
const char *input_profile_filename;
const char *output_profile_filename;
int intent;
cmsHPROFILE in_profile;
cmsHPROFILE out_profile;
cmsHTRANSFORM trans;
/* We need to single-thread calls to LCMS.
*/
GMutex *lock;
} Icc;
/* Error from lcms.
*/
static int
icc_error( int code, const char *text )
{
if( code == LCMS_ERRC_WARNING )
im_warn( "im_icc", "%s", text );
else
im_error( "im_icc", "%s", text );
return( 0 );
}
static int
icc_destroy( Icc *icc )
{
IM_FREEF( cmsDeleteTransform, icc->trans );
IM_FREEF( cmsCloseProfile, icc->in_profile );
IM_FREEF( cmsCloseProfile, icc->out_profile );
IM_FREEF( g_mutex_free, icc->lock );
return( 0 );
}
static Icc *
icc_new( IMAGE *in, IMAGE *out, int intent )
{
Icc *icc;
/* Ask lcms not to abort on error.
*/
cmsErrorAction( LCMS_ERROR_IGNORE );
cmsSetErrorHandler( icc_error );
if( !(icc = IM_NEW( out, Icc )) )
return( NULL );
icc->in = in;
icc->out = out;
icc->input_profile_filename = NULL;
icc->output_profile_filename = NULL;
icc->intent = intent;
icc->in_profile = 0;
icc->out_profile = 0;
icc->trans = 0;
icc->lock = g_mutex_new();
if( im_add_close_callback( out,
(im_callback_fn) icc_destroy, icc, NULL ) )
return( NULL );
return( icc );
}
static Icc *
icc_new_file( IMAGE *in, IMAGE *out,
const char *input_profile_filename,
const char *output_profile_filename,
int intent )
{
Icc *icc;
if( !(icc = icc_new( in, out, intent )) )
return( NULL );
if( input_profile_filename ) {
icc->input_profile_filename =
im_strdup( out, input_profile_filename );
if( !(icc->in_profile = cmsOpenProfileFromFile(
input_profile_filename, "r" )) )
im_error( "im_icc_transform",
_( "unable to open profile \"%s\"" ),
input_profile_filename );
}
if( output_profile_filename ) {
icc->output_profile_filename =
im_strdup( out, output_profile_filename );
if( !(icc->out_profile = cmsOpenProfileFromFile(
output_profile_filename, "r" )) )
im_error( "im_icc_transform",
_( "unable to open profile \"%s\"" ),
output_profile_filename );
}
if( !output_profile_filename )
icc->out_profile = cmsCreateLabProfile( NULL );
if( !input_profile_filename )
icc->in_profile = cmsCreateLabProfile( NULL );
if( !icc->in_profile || !icc->out_profile ) {
im_error( "im_icc_transform",
"%s", _( "unable to create profiles" ) );
return( NULL );
}
return( icc );
}
static Icc *
icc_new_mem( IMAGE *in, IMAGE *out,
void *data, int data_length,
int intent )
{
Icc *icc;
if( !(icc = icc_new( in, out, intent )) )
return( NULL );
if( !(icc->in_profile = cmsOpenProfileFromMem( data, data_length )) ) {
im_error( "im_icc_transform",
"%s", _( "unable to read profile" ) );
return( NULL );
}
icc->out_profile = cmsCreateLabProfile( NULL );
return( icc );
}
/* Pack a buffer of floats into lcms's fixed-point formats. Cut from
* lcms-1.0.8.
*/
static void
encode_lab( float *lab, WORD *fixed, int n )
{
int i;
for( i = 0; i < n; i++ ) {
float L = lab[0];
float a = lab[1];
float b = lab[2];
if( L < 0 )
L = 0;
if( L > 100. )
L = 100.;
if( a < -128. )
a = -128;
if( a > 127.9961 )
a = 127.9961;
if( b < -128. )
b = -128;
if( b > 127.9961 )
b = 127.9961;
fixed[0] = L * 652.800 + 0.5;
fixed[1] = (a + 128.0) * 256.0 + 0.5;
fixed[2] = (b + 128.0) * 256.0 + 0.5;
lab += 3;
fixed += 3;
}
}
static void
decode_lab( WORD *fixed, float *lab, int n )
{
int i;
for( i = 0; i < n; i++ ) {
lab[0] = (double) fixed[0] / 652.800;
lab[1] = ((double) fixed[1] / 256.0) - 128.0;
lab[2] = ((double) fixed[2] / 256.0) - 128.0;
lab += 3;
fixed += 3;
}
}
static void
transform_buf( PEL *in, PEL *out, int n, Icc *icc )
{
g_mutex_lock( icc->lock );
cmsDoTransform( icc->trans, in, out, n );
g_mutex_unlock( icc->lock );
}
static int
attach_profile( IMAGE *im, const char *filename )
{
char *data;
unsigned int data_length;
if( !(data = im__file_read_name( filename, &data_length )) )
return( -1 );
if( im_meta_set_blob( im, IM_META_ICC_NAME,
(im_callback_fn) im_free, data, data_length ) ) {
im_free( data );
return( -1 );
}
return( 0 );
}
int
im_icc_transform( IMAGE *in, IMAGE *out,
const char *input_profile_filename,
const char *output_profile_filename,
int intent )
{
Icc *icc;
DWORD in_icc_format;
DWORD out_icc_format;
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_icc_transform", "%s", _( "uncoded input only" ) );
return( -1 );
}
if( !(icc = icc_new_file( in, out,
input_profile_filename, output_profile_filename, intent )) )
return( -1 );
if( !cmsIsIntentSupported( icc->in_profile,
intent, LCMS_USED_AS_INPUT ) )
im_warning( "im_icc_transform: intent %d (%s) not supported by "
"profile \"%s\"; falling back to default intent "
"(usually PERCEPTUAL)",
intent, decode_intent( intent ),
input_profile_filename );
if( !cmsIsIntentSupported( icc->out_profile,
intent, LCMS_USED_AS_OUTPUT ) )
im_warning( "im_icc_transform: intent %d (%s) not supported by "
"profile \"%s\"; falling back to default intent "
"(usually PERCEPTUAL)",
intent, decode_intent( intent ),
output_profile_filename );
switch( cmsGetColorSpace( icc->in_profile ) ) {
case icSigCmykData:
if( in->Bands != 4 ) {
im_error( "im_icc_transform",
"%s", _( "CMYK input profile "
"needs a 4 band input image" ) );
return( -1 );
}
in_icc_format = COLORSPACE_SH( PT_CMYK ) | CHANNELS_SH( 4 );
break;
case icSigRgbData:
if( in->Bands != 3 ) {
im_error( "im_icc_transform",
"%s", _( "RGB input profile "
"needs a 3 band input image" ) );
return( -1 );
}
in_icc_format = COLORSPACE_SH( PT_RGB ) | CHANNELS_SH( 3 );
break;
default:
im_error( "im_icc_transform", _( "unimplemented input colour "
"space 0x%x" ), cmsGetColorSpace( icc->in_profile ) );
return( -1 );
}
/* Prepare the output image.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( cmsGetColorSpace( icc->out_profile ) ) {
case icSigCmykData:
out->Type = IM_TYPE_CMYK;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = IM_BBITS_BYTE;
out->Bands = 4;
out_icc_format = TYPE_CMYK_8;
break;
case icSigRgbData:
out->Type = IM_TYPE_RGB;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = IM_BBITS_BYTE;
out->Bands = 3;
out_icc_format = TYPE_RGB_8;
break;
default:
im_error( "im_icc_transform", _( "unimplemented output colour "
"space 0x%x" ), cmsGetColorSpace( icc->out_profile ) );
return( -1 );
}
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
in_icc_format |= BYTES_SH( 1 );
break;
case IM_BANDFMT_USHORT:
in_icc_format |= BYTES_SH( 2 );
break;
default:
im_error( "im_icc_transform",
"%s", _( "uchar or ushort input only" ) );
return( -1 );
}
if( !(icc->trans = cmsCreateTransform( icc->in_profile, in_icc_format,
icc->out_profile, out_icc_format, intent, 0 )) )
return( -1 );
/* Process!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) transform_buf, icc, NULL ) )
return( -1 );
if( attach_profile( out, output_profile_filename ) )
return( -1 );
return( 0 );
}
static void
import_buf( PEL *in, float *out, int n, Icc *icc )
{
/* Buffer of encoded 16-bit pixels we write to.
*/
WORD encoded[3 * PIXEL_BUFFER_SIZE];
while( n > 0 ) {
const int chunk = IM_MIN( n, PIXEL_BUFFER_SIZE );
g_mutex_lock( icc->lock );
cmsDoTransform( icc->trans, in, encoded, chunk );
g_mutex_unlock( icc->lock );
decode_lab( encoded, out, chunk );
in += chunk * IM_IMAGE_SIZEOF_PEL( icc->in );
out += chunk * 3;
n -= chunk;
}
}
static int
icc_import( IMAGE *in, IMAGE *out, Icc *icc )
{
DWORD icc_format;
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_icc_import", "%s", _( "uncoded input only" ) );
return( -1 );
}
if( !cmsIsIntentSupported( icc->in_profile,
icc->intent, LCMS_USED_AS_INPUT ) )
im_warn( "im_icc_import", _( "intent %d (%s) not supported by "
"profile; falling back to default intent "
"(usually PERCEPTUAL)" ),
icc->intent, decode_intent( icc->intent ) );
/* Prepare the output image.
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Bbits = IM_BBITS_FLOAT;
out->Bands = 3;
switch( cmsGetColorSpace( icc->in_profile ) ) {
case icSigCmykData:
if( in->Bands != 4 ) {
im_error( "im_icc_import",
"%s", _( "CMYK profile needs a "
"4 band input image" ) );
return( -1 );
}
icc_format = COLORSPACE_SH( PT_CMYK ) | CHANNELS_SH( 4 );
break;
case icSigRgbData:
if( in->Bands != 3 ) {
im_error( "im_icc_import",
"%s", _( "RGB profile needs a "
"3 band input image" ) );
return( -1 );
}
icc_format = COLORSPACE_SH( PT_RGB ) | CHANNELS_SH( 3 );
break;
default:
im_error( "im_icc_import", _( "unimplemented input colour "
"space 0x%x" ), cmsGetColorSpace( icc->in_profile ) );
return( -1 );
}
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
icc_format |= BYTES_SH( 1 );
break;
case IM_BANDFMT_USHORT:
icc_format |= BYTES_SH( 2 );
break;
default:
im_error( "im_icc_transform",
"%s", _( "uchar or ushort input only" ) );
return( -1 );
}
if( !(icc->trans = cmsCreateTransform( icc->in_profile, icc_format,
icc->out_profile, TYPE_Lab_16, icc->intent, 0 )) )
return( -1 );
/* Process!
*/
if( im_wrapone( in, out, (im_wrapone_fn) import_buf, icc, NULL ) )
return( -1 );
return( 0 );
}
int
im_icc_import( IMAGE *in, IMAGE *out,
const char *input_profile_filename, int intent )
{
Icc *icc;
if( !(icc = icc_new_file( in, out,
input_profile_filename, NULL, intent )) ||
icc_import( in, out, icc ) )
return( -1 );
return( 0 );
}
int
im_icc_import_embedded( IMAGE *in, IMAGE *out, int intent )
{
Icc *icc;
void *data;
size_t data_length;
if( im_header_get_typeof( in, IM_META_ICC_NAME ) == 0 ) {
im_error( "im_icc_import_embedded",
"%s", _( "no embedded profile" ) );
return( -1 );
}
if( im_meta_get_blob( in, IM_META_ICC_NAME, &data, &data_length ) ||
!(icc = icc_new_mem( in, out, data, data_length, intent )) ||
icc_import( in, out, icc ) )
return( -1 );
return( 0 );
}
static void
export_buf( float *in, PEL *out, int n, Icc *icc )
{
/* Buffer of encoded 16-bit pixels we transform.
*/
WORD encoded[3 * PIXEL_BUFFER_SIZE];
while( n > 0 ) {
const int chunk = IM_MIN( n, PIXEL_BUFFER_SIZE );
encode_lab( in, encoded, chunk );
g_mutex_lock( icc->lock );
cmsDoTransform( icc->trans, encoded, out, chunk );
g_mutex_unlock( icc->lock );
in += chunk * 3;
out += chunk * IM_IMAGE_SIZEOF_PEL( icc->out );
n -= chunk;
}
}
int
im_icc_export_depth( IMAGE *in, IMAGE *out, int depth,
const char *output_profile_filename, int intent )
{
Icc *icc;
DWORD icc_format;
/* Do IM_CODING_LABQ too.
*/
if( in->Coding == IM_CODING_LABQ ) {
IMAGE *t1 = im_open_local( out, "im_icc_export:1", "p" );
if( !t1 || im_LabQ2Lab( in, t1 ) )
return( -1 );
in = t1;
}
/* Do IM_CODING_RAD.
*/
if( in->Coding == IM_CODING_RAD ) {
IMAGE *t1 = im_open_local( out, "im_icc_export:1", "p" );
if( !t1 || im_rad2float( in, t1 ) )
return( -1 );
in = t1;
}
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_icc_export",
"%s", _( "3-band uncoded Lab float only" ) );
return( -1 );
}
if( depth != 8 && depth != 16 ) {
im_error( "im_icc_export", "%s", _( "unsupported bit depth" ) );
return( -1 );
}
if( !(icc = icc_new_file( in, out,
NULL, output_profile_filename, intent )) )
return( -1 );
if( !cmsIsIntentSupported( icc->out_profile,
intent, LCMS_USED_AS_OUTPUT ) )
im_warning( "im_icc_export: intent %d (%s) not supported by "
"profile \"%s\"; falling back to default intent "
"(usually PERCEPTUAL)",
intent, decode_intent( intent ),
output_profile_filename );
/* Prepare the output image.
*/
if( im_cp_desc( out, in ) )
return( -1 );
switch( cmsGetColorSpace( icc->out_profile ) ) {
case icSigCmykData:
out->Type = IM_TYPE_CMYK;
out->BandFmt = depth == 8 ?
IM_BANDFMT_UCHAR : IM_BANDFMT_USHORT;
out->Bbits = depth == 8 ? IM_BBITS_BYTE : IM_BBITS_SHORT;
out->Bands = 4;
icc_format = depth == 8 ? TYPE_CMYK_8 : TYPE_CMYK_16;
break;
case icSigRgbData:
out->Type = depth == 8 ?
IM_TYPE_RGB : IM_TYPE_RGB16;
out->BandFmt = depth == 8 ?
IM_BANDFMT_UCHAR : IM_BANDFMT_USHORT;
out->Bbits = depth == 8 ? IM_BBITS_BYTE : IM_BBITS_SHORT;
out->Bands = 3;
icc_format = depth == 8 ? TYPE_RGB_8 : TYPE_RGB_16;
break;
default:
im_error( "im_icc_export", _( "unimplemented output colour "
"space 0x%x" ), cmsGetColorSpace( icc->out_profile ) );
return( -1 );
}
if( !(icc->trans = cmsCreateTransform( icc->in_profile, TYPE_Lab_16,
icc->out_profile, icc_format, intent, 0 )) )
return( -1 );
/* Process!
*/
if( im_wrapone( in, out, (im_wrapone_fn) export_buf, icc, NULL ) )
return( -1 );
if( attach_profile( out, output_profile_filename ) )
return( -1 );
return( 0 );
}
int
im_icc_export( IMAGE *in, IMAGE *out,
const char *output_profile_filename, int intent )
{
return( im_icc_export_depth( in, out,
8, output_profile_filename, intent ) );
}
int
im_icc_ac2rc( IMAGE *in, IMAGE *out, const char *profile_filename )
{
cmsHPROFILE profile;
cmsCIEXYZ media;
double add[3];
double mul[3];
IMAGE *t[2];
if( !(profile = cmsOpenProfileFromFile( profile_filename, "r" )) )
return( -1 );
if( !cmsTakeMediaWhitePoint( &media, profile ) ) {
im_error( "im_icc_ac2rc", "%s", _( "unable to get media "
"white point" ) );
return( -1 );
}
cmsCloseProfile( profile );
add[0] = 0.0;
add[1] = 0.0;
add[2] = 0.0;
mul[0] = IM_D50_X0 / (media.X * 100.0);
mul[1] = IM_D50_Y0 / (media.Y * 100.0);
mul[2] = IM_D50_Z0 / (media.Z * 100.0);
/* Do IM_CODING_LABQ too.
*/
if( in->Coding == IM_CODING_LABQ ) {
IMAGE *t1 = im_open_local( out, "im_icc_ac2rc-1", "p" );
if( !t1 || im_LabQ2Lab( in, t1 ) )
return( -1 );
in = t1;
}
/* Do IM_CODING_RAD.
*/
if( in->Coding == IM_CODING_RAD ) {
IMAGE *t1 = im_open_local( out, "im_icc_export:1", "p" );
if( !t1 || im_rad2float( in, t1 ) )
return( -1 );
in = t1;
}
if( im_open_local_array( out, t, 2, "im_icc_ac2rc-2", "p" ) ||
im_Lab2XYZ_temp( in, t[0], IM_D50_X0, IM_D50_Y0, IM_D50_Z0 ) ||
im_lintra_vec( 3, mul, t[0], add, t[1] ) ||
im_XYZ2Lab_temp( t[1], out, IM_D50_X0, IM_D50_Y0, IM_D50_Z0 ) )
return( -1 );
return( 0 );
}
#endif /*HAVE_LCMS*/

View File

@ -0,0 +1,257 @@
/* Morph a lab image ... adjust:
*
* - cast
* Pass in a MASK containing CIELAB readings for a neutral greyscale ...
* eg.
*
* 3 4
* 14.23 4.8 -3.95
* 18.74 2.76 -2.62
* 23.46 1.4 -1.95
* 27.53 1.76 -2.01
*
* interpolation from this makes cast corrector ... interpolate top and
* tail towards [0,0,0] and [100,0,0] ... can be in any order (ie. need
* not be sorted on L*)
*
* - L*
* Pass in scale and offset for L* ... L*' = (L* + offset) * scale
*
* - saturation
* scale a and b by these amounts ... eg. 1.5 increases saturation ...
* useful for some gammut mapping
*
* Find the top two by generating and printing a greyscale ... find the bottom
* by printing a Macbeth and looking at a/b spread
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
typedef struct {
IMAGE *in, *out;
double L_scale, L_offset;
double a_offset[101], b_offset[101];
double a_scale, b_scale;
} Params;
static int
morph_init( Params *parm,
IMAGE *in, IMAGE *out,
double L_scale, double L_offset,
DOUBLEMASK *mask, double a_scale, double b_scale )
{
int i, j;
parm->in = in;
parm->out = out;
parm->L_scale = L_scale;
parm->L_offset = L_offset;
parm->a_scale = a_scale;
parm->b_scale = b_scale;
if( mask->xsize != 3 || mask->ysize < 1 || mask->ysize > 100 ) {
im_errormsg( "im_lab_morph: bad greyscale mask size" );
return( -1 );
}
for( i = 0; i < mask->ysize; i++ ) {
double L = mask->coeff[i*3];
double a = mask->coeff[i*3 + 1];
double b = mask->coeff[i*3 + 2];
if( L < 0 || L > 100 || a < -120 || a > 120 ||
b < -120 || b > 120 ) {
im_errormsg( "im_lab_morph: bad greyscale mask "
"value, row %d", i );
return( -1 );
}
}
/* Generate a/b offsets.
*/
for( i = 0; i <= 100; i++ ) {
double L_low = 0;
double a_low = 0;
double b_low = 0;
double L_high = 100;
double a_high = 0;
double b_high = 0;
/* Search for greyscale L just below i. Don't assume sorted by
* L*.
*/
for( j = 0; j < mask->ysize; j++ ) {
double L = mask->coeff[j*3];
double a = mask->coeff[j*3 + 1];
double b = mask->coeff[j*3 + 2];
if( L < i && L > L_low ) {
L_low = L;
a_low = a;
b_low = b;
}
}
/* Search for greyscale L just above i.
*/
for( j = mask->ysize - 1; j >= 0; j-- ) {
double L = mask->coeff[j*3];
double a = mask->coeff[j*3 + 1];
double b = mask->coeff[j*3 + 2];
if( L >= i && L < L_high ) {
L_high = L;
a_high = a;
b_high = b;
}
}
/* Interpolate.
*/
parm->a_offset[i] = a_low +
(a_high - a_low) * ((i - L_low) / (L_high - L_low));
parm->b_offset[i] = b_low +
(b_high - b_low) * ((i - L_low) / (L_high - L_low));
}
return( 0 );
}
#define loop( TYPE ) \
{ \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
\
for( x = 0; x < width; x++ ) { \
double L = p[0]; \
double a = p[1]; \
double b = p[2]; \
\
L = IM_CLIP( 0, L, 100 ); \
a -= parm->a_offset[(int) L]; \
b -= parm->b_offset[(int) L]; \
\
L = (L + parm->L_offset) * parm->L_scale; \
L = IM_CLIP( 0, L, 100 ); \
\
a *= parm->a_scale; \
b *= parm->b_scale; \
\
q[0] = L; \
q[1] = a; \
q[2] = b; \
\
p += 3; \
q += 3; \
} \
}
static void
morph_buffer( float *in, float *out, int width, Params *parm )
{
int x;
switch( parm->in->BandFmt ) {
case IM_BANDFMT_FLOAT: loop( float ); break;
case IM_BANDFMT_DOUBLE: loop( double ); break;
default: assert( 0 );
}
}
/* Morph an image.
*/
int
im_lab_morph( IMAGE *in, IMAGE *out,
DOUBLEMASK *mask,
double L_offset, double L_scale,
double a_scale, double b_scale )
{
Params *parm;
/* Recurse for coded images.
*/
if( in->Coding == IM_CODING_LABQ ) {
IMAGE *t1 = im_open_local( out, "im_lab_morph:1", "p" );
IMAGE *t2 = im_open_local( out, "im_lab_morph:2", "p" );
if( !t1 || !t2 ||
im_LabQ2Lab( in, t1 ) ||
im_lab_morph( t1, t2,
mask, L_offset, L_scale, a_scale, b_scale ) ||
im_Lab2LabQ( t2, out ) )
return( -1 );
return( 0 );
}
if( in->Coding != IM_CODING_NONE ) {
im_errormsg( "im_lab_morph: must be uncoded or IM_CODING_LABQ" );
return( -1 );
}
if( in->BandFmt != IM_BANDFMT_FLOAT && in->BandFmt != IM_BANDFMT_DOUBLE ) {
im_errormsg( "im_lab_morph: must be uncoded float or double" );
return( -1 );
}
if( in->Bands != 3 ) {
im_errormsg( "im_lab_morph: must be 3 bands" );
return( -1 );
}
if( !(parm = IM_NEW( out, Params )) ||
morph_init( parm,
in, out, L_scale, L_offset, mask, a_scale, b_scale ) )
return( -1 );
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_LAB;
if( im_wrapone( in, out,
(im_wrapone_fn) morph_buffer, parm, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,194 @@
/* Convert Radiance 32bit packed format to float.
* 3/3/09
* - from LabQ2Lab and Radiance sources
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
Sections of this file from Greg Ward and Radiance with kind
permission. The Radience copyright notice appears below.
*/
/* ====================================================================
* The Radiance Software License, Version 1.0
*
* Copyright (c) 1990 - 2009 The Regents of the University of California,
* through Lawrence Berkeley National Laboratory. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes Radiance software
* (http://radsite.lbl.gov/)
* developed by the Lawrence Berkeley National Laboratory
* (http://www.lbl.gov/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
* and "The Regents of the University of California" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact radiance@radsite.lbl.gov.
*
* 5. Products derived from this software may not be called "Radiance",
* nor may "Radiance" appear in their name, without prior written
* permission of Lawrence Berkeley National Laboratory.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of Lawrence Berkeley National Laboratory. For more
* information on Lawrence Berkeley National Laboratory, please see
* <http://www.lbl.gov/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Begin copy-paste from Radiance sources.
*/
#define RED 0
#define GRN 1
#define BLU 2
#define CIEX 0 /* or, if input is XYZ... */
#define CIEY 1
#define CIEZ 2
#define EXP 3 /* exponent same for either format */
#define COLXS 128 /* excess used for exponent */
#define WHT 3 /* used for RGBPRIMS type */
#undef BYTE
#define BYTE unsigned char /* 8-bit unsigned integer */
typedef BYTE COLR[4]; /* red, green, blue (or X,Y,Z), exponent */
typedef float COLORV;
typedef COLORV COLOR[3]; /* red, green, blue (or X,Y,Z) */
#define copycolor(c1,c2) ((c1)[0]=(c2)[0],(c1)[1]=(c2)[1],(c1)[2]=(c2)[2])
static void
colr_color(col, clr) /* convert short to float color */
register COLOR col;
register COLR clr;
{
double f;
if (clr[EXP] == 0)
col[RED] = col[GRN] = col[BLU] = 0.0;
else {
f = ldexp(1.0, (int)clr[EXP]-(COLXS+8));
col[RED] = (clr[RED] + 0.5)*f;
col[GRN] = (clr[GRN] + 0.5)*f;
col[BLU] = (clr[BLU] + 0.5)*f;
}
}
/* End copy-paste from Radiance sources.
*/
static void
rad2float( COLR *inp, COLOR *outbuf, int n )
{
colr_color(outbuf[0], inp[0]);
while (--n > 0) {
outbuf++; inp++;
if (inp[0][RED] == inp[-1][RED] &&
inp[0][GRN] == inp[-1][GRN] &&
inp[0][BLU] == inp[-1][BLU] &&
inp[0][EXP] == inp[-1][EXP])
copycolor(outbuf[0], outbuf[-1]);
else
colr_color(outbuf[0], inp[0]);
}
}
int
im_rad2float( IMAGE *in, IMAGE *out )
{
/* Must be 4-band uchar.
*/
if( in->Bands != 4 || in->BandFmt != IM_BANDFMT_UCHAR ||
in->Coding != IM_CODING_RAD ) {
im_error( "im_rad2float", "%s",
_( "4-band uchar Radiance-coded images only" ) );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Bands = 3;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Bbits = im_bits_of_fmt( out->BandFmt );
out->Coding = IM_CODING_NONE;
if( im_wrapone( in, out,
(im_wrapone_fn) rad2float, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,45 @@
noinst_LTLIBRARIES = libconversion.la
libconversion_la_SOURCES = \
im_bernd.c \
conver_dispatch.c \
im_bandjoin.c \
im_black.c \
im_c2amph.c \
im_c2rect.c \
im_c2imag.c \
im_c2ps.c \
im_c2real.c \
im_clip.c \
im_copy.c \
im_extract.c \
im_falsecolour.c \
im_fliphor.c \
im_flipver.c \
im_gbandjoin.c \
im_insert.c \
im_lrjoin.c \
im_mask2vips.c \
im_msb.c \
im_recomb.c \
im_replicate.c \
im_grid.c \
im_ri2c.c \
im_rightshift_size.c \
im_rot180.c \
im_rot270.c \
im_rot90.c \
im_scale.c \
im_scaleps.c \
im_slice.c \
im_subsample.c \
im_system.c \
im_print.c \
im_tbjoin.c \
im_text.c \
im_thresh.c \
im_vips2mask.c \
im_wrap.c \
im_zoom.c
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,162 @@
/* @(#) Function to perform a band-wise join of two images. If the two images
* @(#) have n and m bands respectively, then the output image will have n+m
* @(#) bands, with the first n coming from the first image and the last m
* @(#) from the second. Works for any image type.
* @(#)
* @(#) Function im_bandjoin() assumes that the imin image
* @(#) is either memory mapped or in the buffer pimin->data.
* @(#)
* @(#) int im_bandjoin(imin1, imin2, imout)
* @(#) IMAGE *imin1, *imin2, *imout;
* @(#)
* @(#) All functions return 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, J. Cupitt
*
* Author: J. Cupitt
* Written on: 12/02/1990
* Modified on : 07/03/1991, by N. Dessipris, history removed
* 27/10/93 JC
* - adapted for partials
* - Nicos formatting removed
* - ANSIfied
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Bandjoin generate function.
*/
static int
bandjoin_gen( REGION *or, void *seq, void *a, void *b )
{
REGION **ir = (REGION **) seq;
Rect *r = &or->valid;
int le = r->left;
int ri = IM_RECT_RIGHT(r);
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int x, y, z;
int i1s = IM_IMAGE_SIZEOF_PEL( ir[0]->im );
int i2s = IM_IMAGE_SIZEOF_PEL( ir[1]->im );
/* Ask for input we need.
*/
if( im_prepare( ir[0], r ) )
return( -1 );
if( im_prepare( ir[1], r ) )
return( -1 );
/* Perform join.
*/
for( y = to; y < bo; y++ ) {
PEL *i1 = (PEL *) IM_REGION_ADDR( ir[0], le, y );
PEL *i2 = (PEL *) IM_REGION_ADDR( ir[1], le, y );
PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );
for( x = le; x < ri; x++ ) {
/* Copy bytes from first file.
*/
for( z = 0; z < i1s; z++ )
*q++ = *i1++;
/* Copy bytes from in2.
*/
for( z = 0; z < i2s; z++ )
*q++ = *i2++;
}
}
return( 0 );
}
/* Join two images. out->Bands = in1->Bands + in2->Bands. in1 goes first in
* the list.
*/
int
im_bandjoin( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
IMAGE **in;
/* Check our args.
*/
if( im_piocheck( in1, out ) )
return( -1 );
if( im_piocheck( in2, out ) )
return( -1 );
if( in1->Xsize != in2->Xsize ||
in1->Ysize != in2->Ysize ) {
im_errormsg( "im_bandjoin: images not same size" );
return( -1 );
}
if( in1->BandFmt != in2->BandFmt ) {
im_errormsg( "im_bandjoin: images not same type" );
return( -1 );
}
if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) {
im_errormsg( "im_bandjoin: input coded" );
return( -1 );
}
/* Set up the output header.
*/
if( im_cp_descv( out, in1, in2, NULL ) )
return( -1 );
out->Bands = in1->Bands + in2->Bands;
/* Set demand hints.
*/
if( im_demand_hint( out, IM_THINSTRIP, in1, in2, NULL ) )
return( -1 );
/* Make input array.
*/
if( !(in = im_allocate_input_array( out, in1, in2, NULL )) )
return( -1 );
/* Make output image.
*/
if( im_generate( out,
im_start_many, bandjoin_gen, im_stop_many, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,95 @@
/* @(#) Extract a tile from a pyramid as a jpeg
* @(#)
* @(#) int
* @(#) im_bernd( const char *tiffname,
* @(#) int x, int y, int w, int h )
* @(#)
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
*
* 7/5/99 JC
* - from im_tiff2vips and im_vips2jpeg, plus some stuff from Steve
* 11/7/01 JC
* - page number now in filename
* 12/5/09
* - fix signed/unsigned warning
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
static int
extract( IMAGE *in, int x, int y, int w, int h )
{
IMAGE *t1;
int len;
char *buf;
if( !(t1 = im_open_local( in, "im_bernd:2", "p" )) ||
im_extract_area( in, t1, x, y, w, h ) ||
im_vips2bufjpeg( t1, in, 75, &buf, &len ) )
return( -1 );
if( fwrite( buf, sizeof( char ), len, stdout ) != (size_t) len ) {
im_error( "im_bernd", "%s", _( "error writing output" ) );
return( -1 );
}
fflush( stdout );
return( 0 );
}
int
im_bernd( const char *tiffname, int x, int y, int w, int h )
{
IMAGE *in;
if( !(in = im_open( "im_bernd:1", "p" )) )
return( -1 );
if( im_tiff2vips( tiffname, in ) ||
extract( in, x, y, w, h ) ) {
im_close( in );
return( -1 );
}
im_close( in );
return( 0 );
}

View File

@ -0,0 +1,118 @@
/* @(#) Make a black uchar image of a specified size. Sometimes useful for
* @(#) building masks.
* @(#) IMAGE out should nhave been set by the calling program
* @(#)
* @(#) int
* @(#) im_black(out, x, y, bands)
* @(#) IMAGE *out;
* @(#) int x, y;
* @(#) int bands;
* @(#)
* @(#) Returns 0 on success and -1 on error.
*
* Copyright: 1990, J. Cupitt
*
* Author: J. Cupitt
* Written on: 02/08/1990
* Modified on : 16/04/1991 by N. Dessipris to work on a line by line basis
* 15/8/94 JC
* - adapted for partials
* - ANSIfied
* - memory leaks fixed!
* 2/3/98 JC
* - IM_ANY added
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <string.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Generate function --- just black out the region.
*/
static int
black_gen( REGION *or, void *seq, void *a, void *b )
{
im__black_region( or );
return( 0 );
}
/* Make a one band black uchar image of a specified size.
*/
int
im_black( IMAGE *out, int x, int y, int bands )
{
int type;
/* Check parameters.
*/
if( x < 0 || y < 0 || bands < 0 ) {
im_errormsg( "im_black: bad parameter" );
return( -1 );
}
/* Check descriptor.
*/
if( im_poutcheck( out ) )
return( -1 );
/* Set fields.
*/
if( bands == 1 )
type = IM_TYPE_B_W;
else
type = IM_TYPE_MULTIBAND;
im_initdesc( out,
x, y, bands,
IM_BBITS_BYTE, IM_BANDFMT_UCHAR, IM_CODING_NONE, type,
1.0, 1.0, 0, 0 );
/* Set hints - ANY is ok with us.
*/
if( im_demand_hint( out, IM_ANY, NULL ) )
return( -1 );
/* Generate image.
*/
if( im_generate( out, NULL, black_gen, NULL, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -0,0 +1,142 @@
/* @(#) Functions which transforms the real and the imaginary parts of
* @(#) a complex image into amplitude and phase.
* @(#) Input image is either memory mapped or in a buffer.
* @(#) Used to display an inverse complex Fourier transform
* @(#)
* @(#) int im_c2amph(in, out)
* @(#) IMAGE *in, *out;
* @(#)
* @(#) All functions return 0 on success and -1 on error
* @(#)
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 12/02/1990
* Modified on : 09/05/1990
* 15/6/93 JC
* - stupid stupid includes and externs fixed
* - I have been editing for 1 1/2 hours and I'm still drowning in
* rubbish extetrnshh
* 13/12/94 JC
* - modernised
* 9/7/02 JC
* - degree output, for consistency
* - slightly better behaviour in edge cases
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
#define loop(TYPE) \
{\
TYPE *p = (TYPE *) in;\
TYPE *q = (TYPE *) out;\
int x;\
\
for( x = 0; x < n; x++ ) {\
double re = p[0];\
double im = p[1];\
double am, ph;\
\
am = sqrt( re * re + im * im );\
\
if( re == 0 ) { \
if( im < 0.0 ) \
ph = 270; \
else if( im == 0.0 ) \
ph = 0; \
else \
ph = 90; \
} \
else { \
double t = atan( im / re ); \
\
if( re > 0.0 ) \
if( im < 0.0 ) \
ph = IM_DEG( t + IM_PI * 2.0 ); \
else \
ph = IM_DEG( t ); \
else \
ph = IM_DEG( t + IM_PI ); \
} \
\
q[0] = am; \
q[1] = ph; \
\
p += 2; \
q += 2; \
}\
}
/* c2amph buffer processor.
*/
static void
buffer_c2amph( void *in, void *out, int w, IMAGE *im )
{
int n = w * im->Bands;
switch( im->BandFmt ) {
case IM_BANDFMT_DPCOMPLEX: loop(double); break;
case IM_BANDFMT_COMPLEX: loop(float); break;
default:
error_exit( "buffer_c2amph: internal error" );
}
}
int
im_c2amph( IMAGE *in, IMAGE *out )
{
if( in->Coding != IM_CODING_NONE || !im_iscomplex( in ) ) {
im_errormsg( "im_c2amph: input should be uncoded complex" );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) buffer_c2amph, in, NULL ) )
return( -1 );
return( 0 );
}

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