merge gtkdoc branch
This commit is contained in:
parent
9fcdda8df7
commit
4e76695e19
|
@ -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
|
||||
|
|
15
Makefile.am
15
Makefile.am
|
@ -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
54
TODO
|
@ -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:
|
||||
|
||||
|
|
10
bootstrap.sh
10
bootstrap.sh
|
@ -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
|
||||
|
||||
|
|
86
configure.in
86
configure.in
|
@ -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
|
||||
|
|
|
@ -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@
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
13
doc/Makefile
13
doc/Makefile
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
SUBDIRS = reference
|
||||
|
||||
EXTRA_DIST = \
|
||||
html \
|
||||
pdf \
|
||||
src \
|
||||
makefile.tex \
|
||||
Makehtmlman \
|
||||
README
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
|
@ -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)
|
|
@ -0,0 +1,7 @@
|
|||
noinst_LTLIBRARIES = libacquire.la
|
||||
|
||||
libacquire_la_SOURCES = \
|
||||
im_clamp.c
|
||||
|
||||
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
|
||||
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 = ®->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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 = ®->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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 ) );
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
|
@ -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 ) );
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 = ®->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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
|
@ -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 = ®->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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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( ®-> 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
|
||||
}
|
||||
|
|
@ -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 ) );
|
||||
}
|
|
@ -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 ) );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 = ®->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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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@
|
|
@ -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
|
||||
};
|
|
@ -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 );
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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@
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
||||
};
|
|
@ -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@
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 ) );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 ) );
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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*/
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue