initial commit
This commit is contained in:
61
AUTHORS
Normal file
61
AUTHORS
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
===========
|
||||||
|
ALE Authors
|
||||||
|
===========
|
||||||
|
|
||||||
|
This article lists authors of documentation, code and patches in the source
|
||||||
|
repository, including (but not limited to) all files distributed in source
|
||||||
|
releases. E-mail addresses have been slightly obscured, with '_a&_'
|
||||||
|
substituted for '@'.
|
||||||
|
|
||||||
|
|
||||||
|
Image-processing code
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
David Hilvert (dhilvert_a&_auricle.dyndns.org),
|
||||||
|
(dhilvert_a&_gmail.com),
|
||||||
|
(dhilvert_a&_ugcs.caltech.edu)
|
||||||
|
|
||||||
|
HJ Hornbeck (hornbeckhj_a&_letterboxes.org)
|
||||||
|
(hjhornbeck_a&_shaw.ca)
|
||||||
|
|
||||||
|
Gregory Maxwell (gmaxwell_a&_gmail.com)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Image-processing documentation
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
David Hilvert (dhilvert_a&_auricle.dyndns.org),
|
||||||
|
(dhilvert_a&_gmail.com),
|
||||||
|
(dhilvert_a&_ugcs.caltech.edu)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Build and installation code and documentation
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
Distributions of this software may be based on the GNU project build tools
|
||||||
|
("autotools"), which may automatically import code written by authors other
|
||||||
|
than those listed below. These authors may include, but are not limited to:
|
||||||
|
|
||||||
|
X Consortium
|
||||||
|
Free Software Foundation (FSF)
|
||||||
|
|
||||||
|
More information on autotools may be available from the following sites:
|
||||||
|
|
||||||
|
http://www.gnu.org/software/automake/
|
||||||
|
http://www.gnu.org/software/autoconf/
|
||||||
|
http://www.gnu.org/software/libtool/
|
||||||
|
http://sourceware.org/autobook/
|
||||||
|
|
||||||
|
The documentation Makefile is part of the DocBook Project XSL Stylesheet
|
||||||
|
distribution, copyright (C) 1999, 2000, 2001, 2002 Norman Walsh. The DocBook
|
||||||
|
XSL stylesheets are maintained by Norman Walsh, (ndw_a&_nwalsh.com), and members
|
||||||
|
of the DocBook Project, (docbook-developers_a&_sf.net). See the COPYING file
|
||||||
|
in the documentation directory for more details. (This file may eventually be
|
||||||
|
merged with the root COPYING file.)
|
||||||
|
|
||||||
|
David Hilvert (dhilvert_a&_auricle.dyndns.org),
|
||||||
|
(dhilvert_a&_gmail.com),
|
||||||
|
(dhilvert_a&_ugcs.caltech.edu)
|
||||||
|
|
||||||
70
BUG-REPORTING
Normal file
70
BUG-REPORTING
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
BUG REPORTING
|
||||||
|
=============
|
||||||
|
|
||||||
|
ALE uses the ditz distributed issue tracking system:
|
||||||
|
|
||||||
|
http://ditz.rubyforge.org/
|
||||||
|
|
||||||
|
with issue database directory `bugs/`. Issue database patches (as well as
|
||||||
|
bugfixes) can be sent by e-mail to ale@ventricle.dyndns.org.
|
||||||
|
|
||||||
|
|
||||||
|
Relevant information
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Providing information sufficient to reproduce a bug may allow more timely resolution
|
||||||
|
of a bug report. Relevant information may include:
|
||||||
|
|
||||||
|
* the full output of ale --version
|
||||||
|
* a list of steps sufficient to reproduce the bug
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Content of the issue tracking database is licensed under the following terms:
|
||||||
|
|
||||||
|
**************************
|
||||||
|
This issue tracking database is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
The Anti-Lamenessing Engine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
**************************
|
||||||
|
|
||||||
|
|
||||||
|
Copyright
|
||||||
|
---------
|
||||||
|
|
||||||
|
Contributions to the issue database are copyright the contributor.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The following notice applies to this BUG-REPORTING document:
|
||||||
|
//
|
||||||
|
// Copyright 2006, 2009 David Hilvert <dhilvert@gmail.com>
|
||||||
|
//
|
||||||
|
// This document is part of The Anti-Lamenessing Engine.
|
||||||
|
//
|
||||||
|
// The Anti-Lamenessing Engine is free software: you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
// option) any later version.
|
||||||
|
//
|
||||||
|
// The Anti-Lamenessing Engine 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 General
|
||||||
|
// Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// The Anti-Lamenessing Engine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
674
COPYING
Normal file
674
COPYING
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
291
INSTALL
Normal file
291
INSTALL
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
|
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||||
|
2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free documentation; the Free Software Foundation gives
|
||||||
|
unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
|
Basic Installation
|
||||||
|
==================
|
||||||
|
|
||||||
|
Briefly, the shell commands `./configure; make; make install' should
|
||||||
|
configure, build, and install this package. The following
|
||||||
|
more-detailed instructions are generic; see the `README' file for
|
||||||
|
instructions specific to this package.
|
||||||
|
|
||||||
|
The `configure' shell script attempts to guess correct values for
|
||||||
|
various system-dependent variables used during compilation. It uses
|
||||||
|
those values to create a `Makefile' in each directory of the package.
|
||||||
|
It may also create one or more `.h' files containing system-dependent
|
||||||
|
definitions. Finally, it creates a shell script `config.status' that
|
||||||
|
you can run in the future to recreate the current configuration, and a
|
||||||
|
file `config.log' containing compiler output (useful mainly for
|
||||||
|
debugging `configure').
|
||||||
|
|
||||||
|
It can also use an optional file (typically called `config.cache'
|
||||||
|
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||||
|
the results of its tests to speed up reconfiguring. Caching is
|
||||||
|
disabled by default to prevent problems with accidental use of stale
|
||||||
|
cache files.
|
||||||
|
|
||||||
|
If you need to do unusual things to compile the package, please try
|
||||||
|
to figure out how `configure' could check whether to do them, and mail
|
||||||
|
diffs or instructions to the address given in the `README' so they can
|
||||||
|
be considered for the next release. If you are using the cache, and at
|
||||||
|
some point `config.cache' contains results you don't want to keep, you
|
||||||
|
may remove or edit it.
|
||||||
|
|
||||||
|
The file `configure.ac' (or `configure.in') is used to create
|
||||||
|
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||||
|
you want to change it or regenerate `configure' using a newer version
|
||||||
|
of `autoconf'.
|
||||||
|
|
||||||
|
The simplest way to compile this package is:
|
||||||
|
|
||||||
|
1. `cd' to the directory containing the package's source code and type
|
||||||
|
`./configure' to configure the package for your system.
|
||||||
|
|
||||||
|
Running `configure' might take a while. While running, it prints
|
||||||
|
some messages telling which features it is checking for.
|
||||||
|
|
||||||
|
2. Type `make' to compile the package.
|
||||||
|
|
||||||
|
3. Optionally, type `make check' to run any self-tests that come with
|
||||||
|
the package.
|
||||||
|
|
||||||
|
4. Type `make install' to install the programs and any data files and
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
5. You can remove the program binaries and object files from the
|
||||||
|
source code directory by typing `make clean'. To also remove the
|
||||||
|
files that `configure' created (so you can compile the package for
|
||||||
|
a different kind of computer), type `make distclean'. There is
|
||||||
|
also a `make maintainer-clean' target, but that is intended mainly
|
||||||
|
for the package's developers. If you use it, you may have to get
|
||||||
|
all sorts of other programs in order to regenerate files that came
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
6. Often, you can also type `make uninstall' to remove the installed
|
||||||
|
files again.
|
||||||
|
|
||||||
|
Compilers and Options
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Some systems require unusual options for compilation or linking that
|
||||||
|
the `configure' script does not know about. Run `./configure --help'
|
||||||
|
for details on some of the pertinent environment variables.
|
||||||
|
|
||||||
|
You can give `configure' initial values for configuration parameters
|
||||||
|
by setting variables in the command line or in the environment. Here
|
||||||
|
is an example:
|
||||||
|
|
||||||
|
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||||
|
|
||||||
|
*Note Defining Variables::, for more details.
|
||||||
|
|
||||||
|
Compiling For Multiple Architectures
|
||||||
|
====================================
|
||||||
|
|
||||||
|
You can compile the package for more than one kind of computer at the
|
||||||
|
same time, by placing the object files for each architecture in their
|
||||||
|
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||||
|
directory where you want the object files and executables to go and run
|
||||||
|
the `configure' script. `configure' automatically checks for the
|
||||||
|
source code in the directory that `configure' is in and in `..'.
|
||||||
|
|
||||||
|
With a non-GNU `make', it is safer to compile the package for one
|
||||||
|
architecture at a time in the source code directory. After you have
|
||||||
|
installed the package for one architecture, use `make distclean' before
|
||||||
|
reconfiguring for another architecture.
|
||||||
|
|
||||||
|
On MacOS X 10.5 and later systems, you can create libraries and
|
||||||
|
executables that work on multiple system types--known as "fat" or
|
||||||
|
"universal" binaries--by specifying multiple `-arch' options to the
|
||||||
|
compiler but only a single `-arch' option to the preprocessor. Like
|
||||||
|
this:
|
||||||
|
|
||||||
|
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CPP="gcc -E" CXXCPP="g++ -E"
|
||||||
|
|
||||||
|
This is not guaranteed to produce working output in all cases, you
|
||||||
|
may have to build one architecture at a time and combine the results
|
||||||
|
using the `lipo' tool if you have problems.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, `make install' installs the package's commands under
|
||||||
|
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||||
|
can specify an installation prefix other than `/usr/local' by giving
|
||||||
|
`configure' the option `--prefix=PREFIX'.
|
||||||
|
|
||||||
|
You can specify separate installation prefixes for
|
||||||
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||||
|
PREFIX as the prefix for installing programs and libraries.
|
||||||
|
Documentation and other data files still use the regular prefix.
|
||||||
|
|
||||||
|
In addition, if you use an unusual directory layout you can give
|
||||||
|
options like `--bindir=DIR' to specify different values for particular
|
||||||
|
kinds of files. Run `configure --help' for a list of the directories
|
||||||
|
you can set and what kinds of files go in them.
|
||||||
|
|
||||||
|
If the package supports it, you can cause programs to be installed
|
||||||
|
with an extra prefix or suffix on their names by giving `configure' the
|
||||||
|
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
|
Some packages pay attention to `--enable-FEATURE' options to
|
||||||
|
`configure', where FEATURE indicates an optional part of the package.
|
||||||
|
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||||
|
is something like `gnu-as' or `x' (for the X Window System). The
|
||||||
|
`README' should mention any `--enable-' and `--with-' options that the
|
||||||
|
package recognizes.
|
||||||
|
|
||||||
|
For packages that use the X Window System, `configure' can usually
|
||||||
|
find the X include and library files automatically, but if it doesn't,
|
||||||
|
you can use the `configure' options `--x-includes=DIR' and
|
||||||
|
`--x-libraries=DIR' to specify their locations.
|
||||||
|
|
||||||
|
Particular systems
|
||||||
|
==================
|
||||||
|
|
||||||
|
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||||
|
CC is not installed, it is recommended to use the following options in
|
||||||
|
order to use an ANSI C compiler:
|
||||||
|
|
||||||
|
./configure CC="cc -Ae"
|
||||||
|
|
||||||
|
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||||
|
|
||||||
|
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||||
|
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||||
|
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||||
|
to try
|
||||||
|
|
||||||
|
./configure CC="cc"
|
||||||
|
|
||||||
|
and if that doesn't work, try
|
||||||
|
|
||||||
|
./configure CC="cc -nodtk"
|
||||||
|
|
||||||
|
Specifying the System Type
|
||||||
|
==========================
|
||||||
|
|
||||||
|
There may be some features `configure' cannot figure out
|
||||||
|
automatically, but needs to determine by the type of machine the package
|
||||||
|
will run on. Usually, assuming the package is built to be run on the
|
||||||
|
_same_ architectures, `configure' can figure that out, but if it prints
|
||||||
|
a message saying it cannot guess the machine type, give it the
|
||||||
|
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||||
|
type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
CPU-COMPANY-SYSTEM
|
||||||
|
|
||||||
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
|
OS KERNEL-OS
|
||||||
|
|
||||||
|
See the file `config.sub' for the possible values of each field. If
|
||||||
|
`config.sub' isn't included in this package, then this package doesn't
|
||||||
|
need to know the machine type.
|
||||||
|
|
||||||
|
If you are _building_ compiler tools for cross-compiling, you should
|
||||||
|
use the option `--target=TYPE' to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with `--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for `configure' scripts to share,
|
||||||
|
you can create a site shell script called `config.site' that gives
|
||||||
|
default values for variables like `CC', `cache_file', and `prefix'.
|
||||||
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all `configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to `configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the `configure' command line, using `VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||||
|
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||||
|
|
||||||
|
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||||
|
|
||||||
|
`configure' Invocation
|
||||||
|
======================
|
||||||
|
|
||||||
|
`configure' recognizes the following options to control how it
|
||||||
|
operates.
|
||||||
|
|
||||||
|
`--help'
|
||||||
|
`-h'
|
||||||
|
Print a summary of all of the options to `configure', and exit.
|
||||||
|
|
||||||
|
`--help=short'
|
||||||
|
`--help=recursive'
|
||||||
|
Print a summary of the options unique to this package's
|
||||||
|
`configure', and exit. The `short' variant lists options used
|
||||||
|
only in the top level, while the `recursive' variant lists options
|
||||||
|
also present in any nested packages.
|
||||||
|
|
||||||
|
`--version'
|
||||||
|
`-V'
|
||||||
|
Print the version of Autoconf used to generate the `configure'
|
||||||
|
script, and exit.
|
||||||
|
|
||||||
|
`--cache-file=FILE'
|
||||||
|
Enable the cache: use and save the results of the tests in FILE,
|
||||||
|
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||||
|
disable caching.
|
||||||
|
|
||||||
|
`--config-cache'
|
||||||
|
`-C'
|
||||||
|
Alias for `--cache-file=config.cache'.
|
||||||
|
|
||||||
|
`--quiet'
|
||||||
|
`--silent'
|
||||||
|
`-q'
|
||||||
|
Do not print messages saying which checks are being made. To
|
||||||
|
suppress all normal output, redirect it to `/dev/null' (any error
|
||||||
|
messages will still be shown).
|
||||||
|
|
||||||
|
`--srcdir=DIR'
|
||||||
|
Look for the package's source code in directory DIR. Usually
|
||||||
|
`configure' can determine that directory automatically.
|
||||||
|
|
||||||
|
`--prefix=DIR'
|
||||||
|
Use DIR as the installation prefix. *Note Installation Names::
|
||||||
|
for more details, including other options available for fine-tuning
|
||||||
|
the installation locations.
|
||||||
|
|
||||||
|
`--no-create'
|
||||||
|
`-n'
|
||||||
|
Run the configure checks, but stop before creating any output
|
||||||
|
files.
|
||||||
|
|
||||||
|
`configure' also accepts some other, not widely useful, options. Run
|
||||||
|
`configure --help' for more details.
|
||||||
|
|
||||||
79
Makefile.am
Normal file
79
Makefile.am
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Copyright 2006 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
# <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
# This file is part of the Anti-Lamenessing Engine.
|
||||||
|
#
|
||||||
|
# The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Makefile.am: This file is used by automake to generate Makefile.in.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Include files from the 'm4' directory.
|
||||||
|
#
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
|
#
|
||||||
|
# Local targets.
|
||||||
|
#
|
||||||
|
|
||||||
|
clean-local: dejagnu-clean
|
||||||
|
|
||||||
|
#
|
||||||
|
# DejaGNU configuration
|
||||||
|
#
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS=dejagnu
|
||||||
|
RUNTESTFLAGS=--tool ale ALE=./ale --srcdir=./testsuite
|
||||||
|
|
||||||
|
dejagnu-clean:
|
||||||
|
rm -f ale.sum ale.log
|
||||||
|
find testsuite -name "*temp.*" -print0 | xargs -0 rm -rf
|
||||||
|
find testsuite -name "*.output.*" -print0 | xargs -0 rm -rf
|
||||||
|
|
||||||
|
#
|
||||||
|
# Gnulib support functions (generating lib/libgnu.la).
|
||||||
|
#
|
||||||
|
|
||||||
|
SUBDIRS = lib
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flags
|
||||||
|
#
|
||||||
|
# NOTE: OPTION_CFLAGS may include flags (e.g., generated by acx_pthread.m4)
|
||||||
|
# that are required for both compile and link operations; hence, it has been
|
||||||
|
# added to both AM_CPPFLAGS and AM_LDFLAGS.
|
||||||
|
#
|
||||||
|
|
||||||
|
AM_CPPFLAGS = @OPTION_CFLAGS@ @OPTION_CPPFLAGS@ -I$(top_srcdir)/lib
|
||||||
|
AM_LDFLAGS = @OPTION_CFLAGS@ @OPTION_LDFLAGS@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Executable target.
|
||||||
|
#
|
||||||
|
|
||||||
|
bin_SCRIPTS = ale
|
||||||
|
bin_PROGRAMS = ale-bin
|
||||||
|
ale_bin_SOURCES = ale.cc thread.cc rand.cc ui/ui.cc ui/input.cc ui/ui_log.cc d2.cc d3.cc
|
||||||
|
ale_bin_LDADD = lib/libgnu.la @OPTION_LIBS@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Manuals
|
||||||
|
#
|
||||||
|
|
||||||
|
man_MANS = doc/man/ale.1
|
||||||
1150
Makefile.in
Normal file
1150
Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
439
NEWS
Normal file
439
NEWS
Normal file
@@ -0,0 +1,439 @@
|
|||||||
|
ALE 0.9.0.3 News
|
||||||
|
|
||||||
|
David Hilvert
|
||||||
|
|
||||||
|
Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Hilvert
|
||||||
|
|
||||||
|
This article is free documentation; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
This article 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 General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this article; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Abstract
|
||||||
|
|
||||||
|
This article includes change summaries for each release.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
50. Version 0.9.0.3, 2009-Mar-31
|
||||||
|
|
||||||
|
This testing release fixes a serious memory leak, fixes an output bit
|
||||||
|
depth bug, and refines bit depth checks.
|
||||||
|
|
||||||
|
49. Version 0.9.0.2, 2008-Nov-05
|
||||||
|
|
||||||
|
This testing release has been updated to fix a bashism in the wrapper
|
||||||
|
script, and includes other minor fixes to the documentation tree.
|
||||||
|
|
||||||
|
48. Version 0.9.0.1, 2008-Jun-13
|
||||||
|
|
||||||
|
This testing release adds support for regional adjustment of tone (e.g.,
|
||||||
|
for varying lighting conditions), includes various multi-alignment fixes
|
||||||
|
and updates, and adds a man page.
|
||||||
|
|
||||||
|
47. Version 0.9.0, 2008-Apr-14
|
||||||
|
|
||||||
|
This testing release allows multiple alignments per input frame, and adds
|
||||||
|
an option for specifying resident sizes for loaded images, allowing more
|
||||||
|
efficient management of backing stores. The current stable branch may
|
||||||
|
offer more reliable performance and results.
|
||||||
|
|
||||||
|
46. Version 0.8.11, 2007-Nov-03
|
||||||
|
|
||||||
|
This release includes new fixed-point configuration options, improves
|
||||||
|
floating-point performance in certain cases, and resolves a possible
|
||||||
|
alignment bug.
|
||||||
|
|
||||||
|
45. Version 0.8.10.1, 2007-Oct-04
|
||||||
|
|
||||||
|
This release fixes an assertion failure occurring at large scale values.
|
||||||
|
|
||||||
|
44. Version 0.8.10, 2007-Oct-02
|
||||||
|
|
||||||
|
This release updates alignment level-of-detail, Monte Carlo alignment, and
|
||||||
|
the re-filtering renderer.
|
||||||
|
|
||||||
|
43. Version 0.8.9.1, 2007-Aug-31
|
||||||
|
|
||||||
|
This release resolves certain build failures occurring under unthreaded
|
||||||
|
configurations, removes certain debugging output, and adds support for
|
||||||
|
platforms missing certain floating point macros.
|
||||||
|
|
||||||
|
42. Version 0.8.9, 2007-Aug-25
|
||||||
|
|
||||||
|
This release adds a re-filtering renderer, fixes certain rendering bugs,
|
||||||
|
and provides a wrapper script for extracting exposure information and
|
||||||
|
decoding raw files.
|
||||||
|
|
||||||
|
41. Version 0.8.8.1, 2007-May-18
|
||||||
|
|
||||||
|
This release removes a violation of the C++ standard that may cause some
|
||||||
|
builds to fail.
|
||||||
|
|
||||||
|
40. Version 0.8.8, 2007-May-15
|
||||||
|
|
||||||
|
This release revises robustness checking for dynamic Monte Carlo
|
||||||
|
alignment, adds quiet and logging UI options, and includes a Gaussian PSF.
|
||||||
|
|
||||||
|
39. Version 0.8.7, 2007-Mar-04
|
||||||
|
|
||||||
|
This release adds new weight limiting options to Irani-Peleg and
|
||||||
|
incremental renderers, and fixes bugs that may cause alignment failure.
|
||||||
|
|
||||||
|
38. Version 0.8.6, 2007-Feb-17
|
||||||
|
|
||||||
|
This release updates certainty calculation, adds a Nikon D50 device
|
||||||
|
option, and resolves certain assertion failures.
|
||||||
|
|
||||||
|
37. Version 0.8.5, 2007-Jan-19
|
||||||
|
|
||||||
|
This release includes an autoconf build system, multi-threading, and
|
||||||
|
dynamic Monte Carlo alignment. Changes since the latest prerelease include
|
||||||
|
revised Euclidean alignment, added help text for the experimental argument
|
||||||
|
scope syntax, and reversion of 3D options to experimental status.
|
||||||
|
|
||||||
|
36. Version 0.8.5-pre3, 2006-Nov-03
|
||||||
|
|
||||||
|
This prerelease adds dynamic adjustment of the Monte Carlo alignment
|
||||||
|
parameter, fixes a potential nondeterminism bug in the random number
|
||||||
|
generator, and modifies default settings to improve the speed of
|
||||||
|
high-quality runs. Other changes include the addition of file-scoping for
|
||||||
|
the perturb-upper option and a bugfix for exp-mult parameter processing.
|
||||||
|
Documentation is incomplete.
|
||||||
|
|
||||||
|
35. Version 0.8.5-pre2, 2006-Oct-25
|
||||||
|
|
||||||
|
This prerelease adds POSIX thread support for 2D alignment and rendering
|
||||||
|
operations, and adds a profiling option to measure elapsed time for
|
||||||
|
different tasks. Documentation is incomplete.
|
||||||
|
|
||||||
|
34. Version 0.8.5-pre1, 2006-Oct-16
|
||||||
|
|
||||||
|
This prerelease includes an autotools build system, documentation licensed
|
||||||
|
under GPL, and an updated user interface accepting scope operators. In
|
||||||
|
particular, the --mc option has been changed to allow file scoping.
|
||||||
|
Documentation is currently incomplete.
|
||||||
|
|
||||||
|
A release plan is included in the TODO file, with entries for 0.8.5,
|
||||||
|
0.9.0, and 1.0.0 releases.
|
||||||
|
|
||||||
|
33. Version 0.8.4, 2006-May-14
|
||||||
|
|
||||||
|
This release refines the 3D engine to support focus effects, filtering,
|
||||||
|
and editing of scene geometry. (Freshmeat announcement)
|
||||||
|
|
||||||
|
33.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Support for filtered 3D rendering.
|
||||||
|
o Support for removal of foreground objects in 3D scenes.
|
||||||
|
o Support for synthetic focus effects.
|
||||||
|
|
||||||
|
32. Version 0.8.3, 2005-Dec-23
|
||||||
|
|
||||||
|
This version adds enhancements in the handling of 3D scenes. (Freshmeat
|
||||||
|
announcement)
|
||||||
|
|
||||||
|
32.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Various enhancements to handling of 3D scenes.
|
||||||
|
|
||||||
|
31. Version 0.8.2, 2005-Nov-22
|
||||||
|
|
||||||
|
This release revises the 3D scene reconstruction algorithm, allowing more
|
||||||
|
robust handling of certain scenes. New 3D model and output options have
|
||||||
|
also been added, including support for clipping planes and arbitrary
|
||||||
|
camera positioning. This release also fixes certain bugs in 2D
|
||||||
|
control-point alignment. (Freshmeat announcement)
|
||||||
|
|
||||||
|
31.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Fix 2D control point alignment bugs
|
||||||
|
o Revise 3D modeling code to use spatial subdivision and occupancy
|
||||||
|
o Add support for clipping planes and arbitrary camera positioning
|
||||||
|
|
||||||
|
30. Version 0.8.1, 2005-May-6
|
||||||
|
|
||||||
|
This release adds control points, median-value rendering, and a unified 3D
|
||||||
|
scene model. It resolves certain syntax errors, allowing successful
|
||||||
|
compilation under GCC 3.4. (Freshmeat announcement)
|
||||||
|
|
||||||
|
30.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Add control points, median-value rendering, and a unified 3D scene
|
||||||
|
model.
|
||||||
|
o Resolve syntax errors causing compilation failure under GCC 3.4.
|
||||||
|
|
||||||
|
29. Version 0.8.0-patch, 2005-Apr-13
|
||||||
|
|
||||||
|
Patch to fix build failures under GCC 3.4 noted by Gregory Maxwell and Tom
|
||||||
|
Holroyd
|
||||||
|
|
||||||
|
28. Version 0.8.0, 2005-Jan-12
|
||||||
|
|
||||||
|
This release adds a more informative TTY user interface, increases
|
||||||
|
Euclidean alignment precision for large images, and reduces
|
||||||
|
certainty-related noise amplification in the Irani-Peleg renderer.
|
||||||
|
(Freshmeat announcement)
|
||||||
|
|
||||||
|
28.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Add a more informative TTY user interface
|
||||||
|
o Increase Euclidean alignment precision for large images
|
||||||
|
o Reduce certainty-related noise amplification in the Irani-Peleg
|
||||||
|
renderer
|
||||||
|
|
||||||
|
27. Version 0.7.3, 2004-Dec-1
|
||||||
|
|
||||||
|
This release includes revised 3D algorithms, reduced memory usage for
|
||||||
|
certain rendering steps, and new point-spread function and device options.
|
||||||
|
(Freshmeat announcement)
|
||||||
|
|
||||||
|
27.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Reduce memory usage in Irani-Peleg and 3D renderers
|
||||||
|
o Add new PSF options for convolution and scalar multiplication
|
||||||
|
o Revise the 3D scene reconstruction algorithm
|
||||||
|
|
||||||
|
27.2. Program summary
|
||||||
|
|
||||||
|
This release includes a revised summary:
|
||||||
|
|
||||||
|
ALE is an image-processing program used for tasks such as
|
||||||
|
super-resolution, deblurring, noise reduction, and anti-aliasing. Its
|
||||||
|
principle of operation is synthetic capture, combining multiple inputs
|
||||||
|
representing the same scene.
|
||||||
|
|
||||||
|
26. Version 0.7.2, 2004-Oct-26
|
||||||
|
|
||||||
|
This release fixes exclusion region and alignment bugs, adds device
|
||||||
|
support for the Canon 300D SLR, and incorporates an experimental framework
|
||||||
|
for reconstruction of 3D scenes. (Freshmeat announcement)
|
||||||
|
|
||||||
|
26.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Incorporate changes from 0.7.1 patches
|
||||||
|
o Add a device configuration for the Canon EOS 300D (Digital Rebel)
|
||||||
|
o Incorporate an approach to 3D reconstruction. (Does not work yet.)
|
||||||
|
|
||||||
|
25. Version 0.7.1-patch2, 2004-Sep-15
|
||||||
|
|
||||||
|
25.1. Changelog summary
|
||||||
|
|
||||||
|
o Adds an option for establishing a minimum overlap area for global
|
||||||
|
searches
|
||||||
|
o Adds a rudimentary test suite.
|
||||||
|
|
||||||
|
24. Version 0.7.1-patch1, 2004-Sep-07
|
||||||
|
|
||||||
|
24.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Allows each perturbation bound to be specified as a percentage of the
|
||||||
|
smallest image dimension (useful for large images?).
|
||||||
|
o Fixes bugs in exclusion region handlers.
|
||||||
|
o Fixes bugs in alignment failure handlers.
|
||||||
|
o Avoids superfluously large undefined regions.
|
||||||
|
o Adds experimental options for refining perturbation.
|
||||||
|
|
||||||
|
23. Version 0.7.1, 2004-Aug-27
|
||||||
|
|
||||||
|
This release fixes alignment bugs, adds a global search option, and adds
|
||||||
|
support for the OmniView OV7620 sensor. (Freshmeat announcement)
|
||||||
|
|
||||||
|
23.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Add linear PSF for OV7620
|
||||||
|
o Add option to concatenate help pages
|
||||||
|
o Fix VISP segfault
|
||||||
|
o Incorporate changes from 0.7.0-patch1
|
||||||
|
|
||||||
|
23.2. Notes
|
||||||
|
|
||||||
|
The default PSF for the OV7620 can be a bit noisy. As an alternative,
|
||||||
|
box=1.3+box=1.8 also works well in some cases, and is less noisy.
|
||||||
|
|
||||||
|
22. Version 0.7.0-patch1, 2004-Aug-22
|
||||||
|
|
||||||
|
22.1. Mailing list announcement
|
||||||
|
|
||||||
|
o Fixes alignment bugs.
|
||||||
|
o Adds a global search option.
|
||||||
|
o Adds support for ov7620 in raw, linear mode.
|
||||||
|
|
||||||
|
22.2. Notes
|
||||||
|
|
||||||
|
The ov7620 device option expects that the 7620 be in raw, linear mode, and
|
||||||
|
that clamping be turned on. These features may not be accessible using
|
||||||
|
standard drivers.
|
||||||
|
|
||||||
|
21. Version 0.7.0, 2004-Aug-06
|
||||||
|
|
||||||
|
This release updates the renderer to support a variety of filters,
|
||||||
|
including sinc and Lanczos, and adds new options for excluding image
|
||||||
|
regions and processing video frames. (Freshmeat announcement)
|
||||||
|
|
||||||
|
20. Version 0.6.0, 2004-Feb-10
|
||||||
|
|
||||||
|
Merging and drizzling renderers now operate in linear colorspace, and the
|
||||||
|
Irani-Peleg renderer has been extended to handle convolutions in both
|
||||||
|
linear colorspace (e.g. lens blur) and non-linear colorspace (e.g. some
|
||||||
|
types of in-camera sharpening). New options in this release include
|
||||||
|
certainty weighting and exposure registration. (Freshmeat announcement)
|
||||||
|
|
||||||
|
19. Version 0.5.1, 2003-Nov-19
|
||||||
|
|
||||||
|
Changes in this release include optional support for 16-bit color channels
|
||||||
|
and built-in support for all PPM file types. Also, a user manual and an
|
||||||
|
updated technical description are now available. (Freshmeat announcement)
|
||||||
|
|
||||||
|
[This release was, and remains (as of Sep 2006), the most advanced version
|
||||||
|
storing pixels as integer values (rather than as floating-point values).
|
||||||
|
As integer values may be more suitable for certain applications,
|
||||||
|
integer-valued functions may be re-introduced, possibly as library code,
|
||||||
|
in the future. 19-Sep-2006]
|
||||||
|
|
||||||
|
19.1. Program summary
|
||||||
|
|
||||||
|
This release includes a revised summary:
|
||||||
|
|
||||||
|
ALE is a program that can render high-fidelity images of real scenes by
|
||||||
|
aligning and combining many similar images from a camera or scanner. The
|
||||||
|
correct similarity between images is roughly that achieved by a somewhat
|
||||||
|
unsteady hand holding a camera.
|
||||||
|
|
||||||
|
18. Version 0.5.0, 2003-Nov-02
|
||||||
|
|
||||||
|
Alignment following has been modified to support multiple-pass alignment
|
||||||
|
of panoramic image mosaics. Other changes in this release include code
|
||||||
|
cleanup and documentation updates. (Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
17. Version 0.4.8, 2003-Aug-01
|
||||||
|
|
||||||
|
The Monte Carlo alignment algorithm has been modified, and may now offer
|
||||||
|
better alignment for small sample sizes. Also, the Irani-Peleg renderer
|
||||||
|
now writes output after each iteration when incremental output is enabled.
|
||||||
|
Other changes include a bugfix in Euclidean alignment, a new option for
|
||||||
|
configuring the level of detail, and a new independent constraint for
|
||||||
|
rotational perturbation. (Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
16. Version 0.4.7, 2003-Jul-27
|
||||||
|
|
||||||
|
Support for device-specific projection functions and various bugfixes have
|
||||||
|
been added to the Irani-Peleg renderer. Also, a new option has been added
|
||||||
|
that may be useful for video stabilization applications. (Freshmeat
|
||||||
|
announcement via Neohapsis)
|
||||||
|
|
||||||
|
15. Version 0.4.6, 2003-Jul-01
|
||||||
|
|
||||||
|
This release fixes bugs in drizzling and post-processing. The following
|
||||||
|
combinations should now work as expected: drizzling in combination with
|
||||||
|
scaling and Irani-Peleg image reconstruction in combination with
|
||||||
|
high-frequency enhancement. (Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
14. Version 0.4.5, 2003-Jun-23
|
||||||
|
|
||||||
|
This release resolves a number of minor alignment bugs. (Freshmeat
|
||||||
|
announcement via Neohapsis)
|
||||||
|
|
||||||
|
13. Version 0.4.4, 2003-Jun-06
|
||||||
|
|
||||||
|
The PPM file handler has been updated to open files in binary mode,
|
||||||
|
resolving a serious bug under Windows. Also, the percentage of pixels used
|
||||||
|
in Monte Carlo alignment now more closely matches user specifications in
|
||||||
|
typical cases. (Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
12. Version 0.4.3, 2003-May-30
|
||||||
|
|
||||||
|
A Monte Carlo alignment option has been added, which may reduce alignment
|
||||||
|
time. An option to disable incremental file output has also been added.
|
||||||
|
(Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
11. Version 0.4.2, 2003-May-23
|
||||||
|
|
||||||
|
An iterative image reconstruction renderer has been added, and the PPM
|
||||||
|
file handler has been updated to correctly handle PPM header comments.
|
||||||
|
(Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
10. Version 0.4.1, 2003-Apr-28
|
||||||
|
|
||||||
|
Increased spatial extents, drizzling, and new alignment options have been
|
||||||
|
added in this release. (Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
9. Version 0.4.0p1, 2003-Apr-04
|
||||||
|
|
||||||
|
A bugfix from the Debian ALE package version 0.4.0-1 has been merged.
|
||||||
|
Without this fix, an assertion failure can occur when ImageMagick support
|
||||||
|
is enabled. (Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
o The original Debian fix was implemented by Debian package maintainer
|
||||||
|
Nick Rusnov.
|
||||||
|
|
||||||
|
8. Version 0.4.0, 2003-Mar-30
|
||||||
|
|
||||||
|
A general scaling option has been added, and the high-frequency
|
||||||
|
enhancement filter now works near image boundaries. (Freshmeat
|
||||||
|
announcement via Neohapsis)
|
||||||
|
|
||||||
|
7. Version 0.3.2, 2003-Mar-26
|
||||||
|
|
||||||
|
A match summary was added to the program's output, comments in
|
||||||
|
transformation file output were made more helpful, and an experimental
|
||||||
|
high-frequency enhancement option was added. (Freshmeat announcement via
|
||||||
|
Neohapsis)
|
||||||
|
|
||||||
|
6. Version 0.3.1, 2003-Mar-25
|
||||||
|
|
||||||
|
(This release appears to have been superseded by 0.3.2.)
|
||||||
|
|
||||||
|
5. Version 0.3.0, 2003-Jan-17
|
||||||
|
|
||||||
|
New options in this release facilitate writing final alignment
|
||||||
|
transformations to a file, reading initial alignment transformations from
|
||||||
|
a file, and setting an upper boundary on the correction step size used in
|
||||||
|
alignment. (Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
4. Version 0.2.0, 2003-Jan-01
|
||||||
|
|
||||||
|
General projective transformations can now be used in image alignment.
|
||||||
|
(Freshmeat announcement via Neohapsis)
|
||||||
|
|
||||||
|
3. Version 0.1.2, 2002-Dec-13
|
||||||
|
|
||||||
|
A new file handler has been added to read and write JPEG, PNG, and other
|
||||||
|
image formats using the ImageMagick C API. The default PPM-only file
|
||||||
|
handler now deals with certain file errors more gracefully. (Freshmeat
|
||||||
|
announcement via Neohapsis)
|
||||||
|
|
||||||
|
o Translation of file formats using ImageMagick was suggested by Nick
|
||||||
|
Rusnov.
|
||||||
|
|
||||||
|
2. Version 0.1.1, 2002-Dec-09
|
||||||
|
|
||||||
|
In this version, a scaling bug that caused corruption of boundary pixels
|
||||||
|
has been fixed. Also, the alignment algorithm has been modified to use
|
||||||
|
reduced detail for coarse alignment steps. (Freshmeat announcement via
|
||||||
|
Neohapsis)
|
||||||
|
|
||||||
|
1. Version 0.1.0, 2002-Nov-26
|
||||||
|
|
||||||
|
The image alignment algorithm has been updated. (Freshmeat announcement
|
||||||
|
via Neohapsis)
|
||||||
|
|
||||||
|
0. Version 0.0.0, 2002-Oct-11
|
||||||
|
|
||||||
|
Initial release
|
||||||
|
|
||||||
|
0.1. Program summary
|
||||||
|
|
||||||
|
ALE aligns and merges several similar images from a digitizing device
|
||||||
|
(such as a digital camera or scanner) into a single image. This may have
|
||||||
|
the effect of producing a relatively alias-free image (sometimes called
|
||||||
|
"anti-aliasing").
|
||||||
223
README
Normal file
223
README
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
ALE 0.9.0.3 Installation Guide
|
||||||
|
|
||||||
|
David Hilvert
|
||||||
|
|
||||||
|
Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Hilvert
|
||||||
|
|
||||||
|
This article is free documentation; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
This article 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 General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this article; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Abstract
|
||||||
|
|
||||||
|
This article includes download, build, and installation instructions.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
1. Compiling from source
|
||||||
|
|
||||||
|
1.1. URLs
|
||||||
|
|
||||||
|
1.2. Build prerequisites
|
||||||
|
|
||||||
|
1.3. Extraction
|
||||||
|
|
||||||
|
1.4. Running configure
|
||||||
|
|
||||||
|
1.5. Configuration options
|
||||||
|
|
||||||
|
1.6. Cross-compilation
|
||||||
|
|
||||||
|
1.7. Further details
|
||||||
|
|
||||||
|
2. On-line resources
|
||||||
|
|
||||||
|
2.1. Mailing list
|
||||||
|
|
||||||
|
1. Compiling from source
|
||||||
|
|
||||||
|
1.1. URLs
|
||||||
|
|
||||||
|
o http://auricle.dyndns.org/ALE/download/ale-0.9.0.3.tar.gz
|
||||||
|
|
||||||
|
1.2. Build prerequisites
|
||||||
|
|
||||||
|
1.2.1. GCC C++ compiler
|
||||||
|
|
||||||
|
GCC version 3.2.3 with C++ support is known to build ALE successfully.
|
||||||
|
Older versions of GCC may fail to compile some versions of ALE.
|
||||||
|
|
||||||
|
1.2.2. Prerequisites for building on Windows
|
||||||
|
|
||||||
|
Successfully running the configuration script on Windows (e.g., for native
|
||||||
|
builds) may require installation of Cygwin. For more information on
|
||||||
|
Cygwin, see:
|
||||||
|
|
||||||
|
o http://www.cygwin.com/
|
||||||
|
|
||||||
|
Alternatively, this package can be cross-compiled for Windows on a
|
||||||
|
non-Windows architecture, provided that the appropriate cross-compilers
|
||||||
|
and libraries are available.
|
||||||
|
|
||||||
|
1.3. Extraction
|
||||||
|
|
||||||
|
Download the source archive file from the URL indicated in the section
|
||||||
|
'URLs', and invoke:
|
||||||
|
|
||||||
|
tar xzf ale-0.9.0.3.tar.gz
|
||||||
|
cd ale-0.9.0.3
|
||||||
|
|
||||||
|
Invoking 'ls configure' afterward should reveal an executable script
|
||||||
|
'configure'. This script is used to determine the capabilities of the
|
||||||
|
system that will run the software.
|
||||||
|
|
||||||
|
1.4. Running configure
|
||||||
|
|
||||||
|
This package uses a configuration script, 'configure', generated by the
|
||||||
|
GNU project build tools ("autotools"). For most cases, it should be
|
||||||
|
sufficient to invoke:
|
||||||
|
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
In cases where the defaults are not adequate, configuration options can be
|
||||||
|
passed to the configuration script.
|
||||||
|
|
||||||
|
1.5. Configuration options
|
||||||
|
|
||||||
|
Configuration options can be passed to the 'configure' script prior to
|
||||||
|
build and installation, as:
|
||||||
|
|
||||||
|
./configure --config-option1 --config-option2 ...
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
Options specific to this package are described in the following
|
||||||
|
subsections. General configuration options are described in the file
|
||||||
|
'INSTALL' included in the source package.
|
||||||
|
|
||||||
|
1.5.1. ImageMagick Support
|
||||||
|
|
||||||
|
Enabling ImageMagick support allows ALE to make use of the file-handling
|
||||||
|
capabilities of ImageMagick ( http://imagemagick.org/ ). This includes
|
||||||
|
reading and writing a variety of file formats, including, among many
|
||||||
|
others, PNG and JPEG (two formats commonly used in web publishing) as well
|
||||||
|
as common interchange formats such as PPM and TIFF. ImageMagick 6.0.6 is
|
||||||
|
known to work with this version of ALE; certain older versions of
|
||||||
|
ImageMagick may cause compile, link, or runtime errors. By default,
|
||||||
|
support is automatically detected.
|
||||||
|
|
||||||
|
--with-imagemagick=auto Auto-detect ImageMagick support [default]
|
||||||
|
--with-imagemagick=yes Enable ImageMagick support
|
||||||
|
--with-imagemagick=no Disable ImageMagick support
|
||||||
|
|
||||||
|
1.5.2. Color Data Precision
|
||||||
|
|
||||||
|
ALE's internal data structures store each color channel within a pixel as
|
||||||
|
floating-point data; similarly, arithmetic operations on color channels
|
||||||
|
are performed in floating point. The available data-type configurations
|
||||||
|
are listed below, with typical data sizes indicated in parentheses.
|
||||||
|
|
||||||
|
--with-colors=single Use C++ 'float' data type (32-bit) [default]
|
||||||
|
--with-colors=double Use C++ 'double' data type (64-bit)
|
||||||
|
|
||||||
|
1.5.3. Coordinate Data Precision
|
||||||
|
|
||||||
|
In general, coordinate transformations used by ALE produce results outside
|
||||||
|
of the set of integers; hence, coordinates are treated as floating-point
|
||||||
|
data. The two available data-type configurations are listed below, with
|
||||||
|
typical data sizes indicated in parentheses.
|
||||||
|
|
||||||
|
--with-coords=single Use C++ 'float' data type (32-bit) [default]
|
||||||
|
--with-coords=double Use C++ 'double' data type (64-bit)
|
||||||
|
|
||||||
|
1.5.4. Thread support
|
||||||
|
|
||||||
|
Threads can improve performance on multiprocessor machines. POSIX threads
|
||||||
|
are currently supported.
|
||||||
|
|
||||||
|
--enable-threads=auto Auto-detect thread support. [default]
|
||||||
|
--enable-threads=yes Enable thread support.
|
||||||
|
--enable-threads=no Disable thread support.
|
||||||
|
|
||||||
|
1.5.5. FFTW Support
|
||||||
|
|
||||||
|
This feature is required in order to use the --fl option; it also
|
||||||
|
determines the approach to calculation of discrete Fourier transforms used
|
||||||
|
by the Irani-Peleg renderer. For more information on FFTW, see
|
||||||
|
http://fftw.org/.
|
||||||
|
|
||||||
|
--with-fftw3=auto Auto-detect FFTW3. [default]
|
||||||
|
--with-fftw3=yes Use FFTW3 discrete Fourier transform.
|
||||||
|
--with-fftw3=no Use built-in discrete Fourier transform.
|
||||||
|
|
||||||
|
1.5.6. Enable --wmx
|
||||||
|
|
||||||
|
This build option is required in order to use the --wmx option. If
|
||||||
|
--enable-wmx is specified, it is expected that fork() and execlp() calls
|
||||||
|
are available.
|
||||||
|
|
||||||
|
--enable-wmx=auto Automatically detect whether to enable --wmx
|
||||||
|
--enable-wmx=yes Enable --wmx
|
||||||
|
--enable-wmx=no Do not enable --wmx
|
||||||
|
|
||||||
|
1.5.7. Getsize
|
||||||
|
|
||||||
|
This build option is required to obtain additional output from --ui=tty.
|
||||||
|
If TIOCGWINSZ is not defined in <sys/ioctl.h>, however, additional output
|
||||||
|
will not be provided even if --enable-getsize is specified at build time.
|
||||||
|
|
||||||
|
--enable-getsize=auto Check for TIOCGWINSZ at build time. [default]
|
||||||
|
--enable-getsize=yes Configure to attempt to use TIOCGWINSZ
|
||||||
|
--enable-getsize=no Do not attempt to use TIOCGWINSZ
|
||||||
|
|
||||||
|
1.5.8. Assertions
|
||||||
|
|
||||||
|
Finding bugs within ALE, or within custom modifications to ALE, can be
|
||||||
|
simplified by enabling run-time assertions. These checks enforce
|
||||||
|
conditions believed to be necessary or desirable for correct program
|
||||||
|
operation. If a condition is not satisfied, ALE will abort and display a
|
||||||
|
message indicating the failed assertion.
|
||||||
|
|
||||||
|
--enable-assertions Enable assertions. [default]
|
||||||
|
--disable-assertions Disable assertions.
|
||||||
|
|
||||||
|
1.6. Cross-compilation
|
||||||
|
|
||||||
|
For cross-compilation, it may be necessary to specify both host and build
|
||||||
|
machine types, using the configure --host and --build options. For more
|
||||||
|
information on these options, see the file 'INSTALL' in the source
|
||||||
|
package.
|
||||||
|
|
||||||
|
1.7. Further details
|
||||||
|
|
||||||
|
General operation of the configure script is described in more detail in
|
||||||
|
the file 'INSTALL' in the source package.
|
||||||
|
|
||||||
|
2. On-line resources
|
||||||
|
|
||||||
|
Home Page http://auricle.dyndns.org/ALE/
|
||||||
|
git repository http://repo.or.cz/w/Ale.git
|
||||||
|
Mailing list archive http://ventricle.dyndns.org/pipermail/ale/
|
||||||
|
|
||||||
|
2.1. Mailing list
|
||||||
|
|
||||||
|
Bug reports, feature requests, patch and release announcements, and
|
||||||
|
related discussion can be sent to ale@ventricle.dyndns.org. Archives of
|
||||||
|
past postings and subscription information are available at the URLs
|
||||||
|
indicated below.
|
||||||
|
|
||||||
|
Posting address ale@ventricle.dyndns.org
|
||||||
|
Subscription info http://ventricle.dyndns.org/cgi-bin/mailman/listinfo/ale
|
||||||
|
Archives http://ventricle.dyndns.org/pipermail/ale/
|
||||||
266
TODO
Normal file
266
TODO
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
ALE 0.9.0.3 To-do list
|
||||||
|
|
||||||
|
David Hilvert
|
||||||
|
|
||||||
|
Copyright (c) 2006, 2007 David Hilvert
|
||||||
|
|
||||||
|
This article is free documentation; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
This article 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 General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this article; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Abstract
|
||||||
|
|
||||||
|
This article contains a tentative list of future versions and features.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
1. 0.9.0
|
||||||
|
|
||||||
|
1.1. Argument scope
|
||||||
|
|
||||||
|
1.2. Multiple-pass registration
|
||||||
|
|
||||||
|
1.3. 3D scenes and depth recovery
|
||||||
|
|
||||||
|
1.4. PSF windowing and infinite-support PSFs for Irani-Peleg
|
||||||
|
rendering
|
||||||
|
|
||||||
|
1.5. Variable lighting
|
||||||
|
|
||||||
|
1.6. Interchange formats
|
||||||
|
|
||||||
|
1.7. Raw file handling
|
||||||
|
|
||||||
|
1.8. Abstract and partial transformations
|
||||||
|
|
||||||
|
1.9. File scoping
|
||||||
|
|
||||||
|
1.10. Irani-Peleg for 3D models
|
||||||
|
|
||||||
|
1.11. Focus bracketing for depth-of-field expansion
|
||||||
|
|
||||||
|
1.12. Output image characteristics
|
||||||
|
|
||||||
|
1.13. Output devices
|
||||||
|
|
||||||
|
1.14. Weight and certainty upper bounds
|
||||||
|
|
||||||
|
1.15. Time locality
|
||||||
|
|
||||||
|
2. 1.0.0 (Stable)
|
||||||
|
|
||||||
|
2.1. Performance
|
||||||
|
|
||||||
|
2.2. Synchronized frame set syntax
|
||||||
|
|
||||||
|
2.3. Internationalization
|
||||||
|
|
||||||
|
2.4. Technical Manual Updates
|
||||||
|
|
||||||
|
3. Unsorted
|
||||||
|
|
||||||
|
3.1. Documentation
|
||||||
|
|
||||||
|
3.2. Integer-value routines
|
||||||
|
|
||||||
|
3.3. Library
|
||||||
|
|
||||||
|
3.4. Language Bindings
|
||||||
|
|
||||||
|
3.5. Packaging
|
||||||
|
|
||||||
|
1. 0.9.0
|
||||||
|
|
||||||
|
1.1. Argument scope
|
||||||
|
|
||||||
|
o Fix bugs in argument scope handling.
|
||||||
|
|
||||||
|
1.2. Multiple-pass registration
|
||||||
|
|
||||||
|
o Revise alignment algorithm to allow multiple passes for less
|
||||||
|
sensitivity to noise and better estimation of tonal certainty.
|
||||||
|
|
||||||
|
1.3. 3D scenes and depth recovery
|
||||||
|
|
||||||
|
o Revise 3D scene reconstruction algorithm to perform acceptably on a
|
||||||
|
wider variety of scenes.
|
||||||
|
|
||||||
|
1.4. PSF windowing and infinite-support PSFs for Irani-Peleg rendering
|
||||||
|
|
||||||
|
o Add syntax for PSF windowing and new PSF types with infinite support,
|
||||||
|
including the gaussian kernel, suggested by HJ Hornbeck.
|
||||||
|
|
||||||
|
1.5. Variable lighting
|
||||||
|
|
||||||
|
o Add a facility for handling variation in lighting between input
|
||||||
|
frames.
|
||||||
|
|
||||||
|
1.6. Interchange formats
|
||||||
|
|
||||||
|
o Add support for a commonly-used interchange format, such as autopano
|
||||||
|
pto, suggested by Peter Miller.
|
||||||
|
|
||||||
|
1.7. Raw file handling
|
||||||
|
|
||||||
|
o Use Dave Coffin's dcraw program to extract information from raw files,
|
||||||
|
including pixel data, as well as black level and other meta-data, as
|
||||||
|
suggested by Gregory Maxwell.
|
||||||
|
|
||||||
|
1.8. Abstract and partial transformations
|
||||||
|
|
||||||
|
o Add a generic 2D transformation class, supporting partial
|
||||||
|
transformations.
|
||||||
|
o 'partial transformation', as used here, means that it is expected
|
||||||
|
that some points will fail to map.
|
||||||
|
o Add a partial 2D transformation class with constructor taking as
|
||||||
|
arguments a pair of 3D projective transformations and a 3D model.
|
||||||
|
|
||||||
|
1.9. File scoping
|
||||||
|
|
||||||
|
o Add new file-scoped options
|
||||||
|
o Irani-Peleg
|
||||||
|
o black level
|
||||||
|
o alignment type
|
||||||
|
o focus details
|
||||||
|
|
||||||
|
1.10. Irani-Peleg for 3D models
|
||||||
|
|
||||||
|
o Modify existing Irani-Peleg code to use generic (partial) 2D
|
||||||
|
transformations.
|
||||||
|
o in combination with the above, this should allow the algorithm to
|
||||||
|
operate on 3D models.
|
||||||
|
|
||||||
|
1.11. Focus bracketing for depth-of-field expansion
|
||||||
|
|
||||||
|
o Add facilities for handling depth-of-field and focus bracketing in
|
||||||
|
input image sets, as suggested by Viktors Rotanovs and Gregory
|
||||||
|
Maxwell. This change will likely involve:
|
||||||
|
o using the 3D model for depth data, as suggested by Gregory
|
||||||
|
Maxwell
|
||||||
|
o using user-provided (file-scoped) focus details to determine
|
||||||
|
depth of field
|
||||||
|
o using variable PSF in the Irani-Peleg algorithm, as suggested by
|
||||||
|
Gregory Maxwell
|
||||||
|
o developing an approach to handle the incremental
|
||||||
|
(non-Irani-Peleg) case.
|
||||||
|
|
||||||
|
1.12. Output image characteristics
|
||||||
|
|
||||||
|
o Allow specification of output image characteristics, including
|
||||||
|
exposure (e.g., gamma) and channel offsets within a pixel.
|
||||||
|
|
||||||
|
1.13. Output devices
|
||||||
|
|
||||||
|
o Add support for specifying output devices, such as LCD monitors, to
|
||||||
|
allow shorthand customization of exposure (e.g., gamma) and other
|
||||||
|
characteristics, such as channel offset in the case of LCD screens for
|
||||||
|
sub-pixel anti-aliasing.
|
||||||
|
|
||||||
|
1.14. Weight and certainty upper bounds
|
||||||
|
|
||||||
|
o Add support for specifying weight and certainty upper bounds for
|
||||||
|
rendering, either as an absolute constraint or relative to average
|
||||||
|
weights, so that the overall contributions to an output pixel (or
|
||||||
|
channel) are constrained by weight.
|
||||||
|
|
||||||
|
1.15. Time locality
|
||||||
|
|
||||||
|
o In combination with weight and certainty upper bounds, time locality
|
||||||
|
could be used to determine which frames are used to generate an output
|
||||||
|
pixel. As a special case of this, video stream processing could favor
|
||||||
|
frames having the smallest time difference from the target frame.
|
||||||
|
|
||||||
|
2. 1.0.0 (Stable)
|
||||||
|
|
||||||
|
2.1. Performance
|
||||||
|
|
||||||
|
o Refine rendering and alignment code for better performance.
|
||||||
|
|
||||||
|
2.2. Synchronized frame set syntax
|
||||||
|
|
||||||
|
o Add syntax to identify synchronized frame sets.
|
||||||
|
|
||||||
|
2.3. Internationalization
|
||||||
|
|
||||||
|
o Enhance the command-line interface in preparation for i18n. (?)
|
||||||
|
o e.g., syntax for identifying synchronized frame sets
|
||||||
|
o Internationalize the command-line interface and help text to
|
||||||
|
accommodate translations.
|
||||||
|
|
||||||
|
2.4. Technical Manual Updates
|
||||||
|
|
||||||
|
o Update the Technical Manual for information regarding 3D operation.
|
||||||
|
|
||||||
|
3. Unsorted
|
||||||
|
|
||||||
|
3.1. Documentation
|
||||||
|
|
||||||
|
o Generate correctly indented book-level tables of contents when
|
||||||
|
rendering the complete set of manuals.
|
||||||
|
o Add a tutorial, and credit Metin Toyran for suggesting a step-by-step
|
||||||
|
guide.
|
||||||
|
o Remedy meaningless page numbers for book title pages in the set ToC.
|
||||||
|
o Complete migration of existing documentation from the localhost
|
||||||
|
sub-directory, removing superfluous license terms in the footers.
|
||||||
|
o Centralize licensing and authorship information (e.g., there should be
|
||||||
|
only one COPYING file and only one AUTHORS file).
|
||||||
|
o Include license and copyright terms for the doc tree Makefile as
|
||||||
|
copyright notices in the AUTHORS and/or COPYING files (or equivalent).
|
||||||
|
o Complete the documentation.
|
||||||
|
o Revise the user manual for new features and syntax.
|
||||||
|
o Document new scoping operators {}, [], and [<>].
|
||||||
|
o Document other changes in UI, including regularization of syntax.
|
||||||
|
+ in particular, commas can no longer appear in
|
||||||
|
single-argument options when using assignment-delimited
|
||||||
|
syntax; use space-delimited syntax instead. This behavior is
|
||||||
|
inconsistent with 0.8.4.
|
||||||
|
|
||||||
|
3.2. Integer-value routines
|
||||||
|
|
||||||
|
o Add facilities for manipulating images storing color as integer-valued
|
||||||
|
data, possibly as library routines.
|
||||||
|
|
||||||
|
3.3. Library
|
||||||
|
|
||||||
|
o Move image-processing routines into a library that can be used by
|
||||||
|
other programs.
|
||||||
|
|
||||||
|
3.4. Language Bindings
|
||||||
|
|
||||||
|
o Add bindings for other programming languages.
|
||||||
|
|
||||||
|
3.5. Packaging
|
||||||
|
|
||||||
|
3.5.1. Complete Package
|
||||||
|
|
||||||
|
o Investigate options for distributing a 'complete' package including
|
||||||
|
full revision history, pre-built documentation (if the ordinary
|
||||||
|
distribution does not include this), and, possibly, example image
|
||||||
|
sets. Direct download, bittorrent and CD are the most prominent
|
||||||
|
candidates for distribution.
|
||||||
|
o In the case of CD distribution, information should probably be
|
||||||
|
added to the manuals regarding how to update CD-provided program
|
||||||
|
source.
|
||||||
|
|
||||||
|
3.5.2. Windows Package
|
||||||
|
|
||||||
|
o Investigate options for creating and distributing a combined source
|
||||||
|
and binary Windows package containing sufficient software to ensure
|
||||||
|
support for common image types (e.g., by statically linking with
|
||||||
|
libraries for opening JPEG and PNG files). BitTorrent and CD are the
|
||||||
|
most obvious candidates for distribution.
|
||||||
|
o This package could build on the package described above, as a
|
||||||
|
'for Windows' variant or some such.
|
||||||
|
o This package could make use of an application such as
|
||||||
|
InstallJammer or Nullsoft Scriptable Install System for
|
||||||
|
installation.
|
||||||
1348
aclocal.m4
vendored
Normal file
1348
aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
242
ale
Executable file
242
ale
Executable file
@@ -0,0 +1,242 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# ALE wrapper script
|
||||||
|
#
|
||||||
|
# Copyright (C) 2007 David Hilvert
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
chomp ($ale_exec_dir = `dirname $0`);
|
||||||
|
|
||||||
|
%defaults = (
|
||||||
|
"ALE_BIN" => "$ale_exec_dir/ale-bin",
|
||||||
|
"DCRAW" => "dcraw",
|
||||||
|
"EXIF_UTILITY" => "exiftool",
|
||||||
|
"ALE_COUNT_THREADS" => "0",
|
||||||
|
"PAGER" => "/usr/bin/less",
|
||||||
|
);
|
||||||
|
|
||||||
|
%devices = (
|
||||||
|
"Canon EOS 5D" => "canon_300d",
|
||||||
|
"Canon EOS DIGITAL REBEL" => "canon_300d",
|
||||||
|
);
|
||||||
|
|
||||||
|
for $default (keys %defaults) {
|
||||||
|
if (!defined $ENV{$default}) {
|
||||||
|
$ENV{$default} = $defaults{$default};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Wrap help page requests
|
||||||
|
#
|
||||||
|
|
||||||
|
if (!defined @ARGV || @ARGV == 0 || $ARGV[0] =~ /^--h[a-zA-Z0-9]$/) {
|
||||||
|
$ale_bin = $ENV{"ALE_BIN"};
|
||||||
|
|
||||||
|
#
|
||||||
|
# Find a pager
|
||||||
|
#
|
||||||
|
|
||||||
|
undef $pager;
|
||||||
|
if (-x "$ENV{PAGER}") {
|
||||||
|
$pager = $ENV{"PAGER"};
|
||||||
|
} elsif (`which $ENV{"PAGER"}`) {
|
||||||
|
$pager = `which $ENV{"PAGER"}`;
|
||||||
|
} elsif (`which pager`) {
|
||||||
|
$pager = `which pager`;
|
||||||
|
} elsif (`which less`) {
|
||||||
|
$pager = `which less`;
|
||||||
|
} elsif (`which more`) {
|
||||||
|
$pager = `which more`;
|
||||||
|
} elsif (-x '/usr/bin/less') {
|
||||||
|
$pager = '/usr/bin/less';
|
||||||
|
} elsif (-x '/bin/more') {
|
||||||
|
$pager = '/bin/more';
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set pager options
|
||||||
|
#
|
||||||
|
|
||||||
|
$ENV{"LESS"} = "-X -F";
|
||||||
|
|
||||||
|
#
|
||||||
|
# Fetch help page
|
||||||
|
#
|
||||||
|
|
||||||
|
if (defined $pager) {
|
||||||
|
exec "/bin/bash -c 'exec -a $0 $ale_bin @ARGV | $pager'";
|
||||||
|
} else {
|
||||||
|
exec "/bin/bash -c 'exec -a $0 $ale_bin @ARGV'";
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Perform metadata extraction and conversion
|
||||||
|
#
|
||||||
|
|
||||||
|
$started_conversion = 0;
|
||||||
|
undef $global_device;
|
||||||
|
for ($i = 0; $i < @ARGV; $i++) {
|
||||||
|
$arg = $ARGV[$i];
|
||||||
|
|
||||||
|
$i += 10 if $arg =~ /^-?-3dvp$/;
|
||||||
|
$i += 10 if $arg =~ /^-?-3dpp$/;
|
||||||
|
$i += 2 if $arg =~ /^-?-3dp$/;
|
||||||
|
$i += 2 if $arg =~ /^-?-3dv$/;
|
||||||
|
$i += 2 if $arg =~ /^-?-ochain$/;
|
||||||
|
$i += 3 if $arg =~ /^-?-wm$/;
|
||||||
|
$i += 3 if $arg =~ /^-?-wmx$/;
|
||||||
|
$i += 1 if $arg =~ /^-?-trans-load$/;
|
||||||
|
$i += 1 if $arg =~ /^-?-trans-save$/;
|
||||||
|
|
||||||
|
next if (!-e $arg);
|
||||||
|
|
||||||
|
if (defined $ENV{"EXIF_UTILITY"} && `which $ENV{"EXIF_UTILITY"}`) {
|
||||||
|
if (`$ENV{"EXIF_UTILITY"} $arg | grep '^EV'` =~ /([0-9\.]+)/) {
|
||||||
|
$ev = $1;
|
||||||
|
if (`$ENV{"EXIF_UTILITY"} $arg | grep '^ISO'` =~ /([0-9\.]+)/) {
|
||||||
|
$ev = $ev - log($1 / 100) / log(2);
|
||||||
|
}
|
||||||
|
@ARGV = (@ARGV[0..$i - 1], "--ev", "$ev", @ARGV[$i..$#ARGV]);
|
||||||
|
$i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $ENV{"DCRAW"} && `which $ENV{"DCRAW"}`) {
|
||||||
|
$device_info = `$ENV{"DCRAW"} -i $arg 2> /dev/null`;
|
||||||
|
|
||||||
|
next if ($?);
|
||||||
|
|
||||||
|
if (!$started_conversion) {
|
||||||
|
print "Extracting frame data";
|
||||||
|
$started_conversion = 1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Make a temporary directory for conversion
|
||||||
|
#
|
||||||
|
|
||||||
|
use File::Temp qw/ tempdir /;
|
||||||
|
|
||||||
|
$tempdir = tempdir("ale.XXXXXXXXX",
|
||||||
|
CLEANUP => 1,
|
||||||
|
DIR => File::Spec->tmpdir());
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get device information
|
||||||
|
#
|
||||||
|
|
||||||
|
undef $device;
|
||||||
|
foreach $device_string (keys %devices) {
|
||||||
|
if ($device_info =~ /$device_string/) {
|
||||||
|
$device = $devices{$device_string};
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!defined $device) {
|
||||||
|
$device = "canon_300d";
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Currently, devices must be global.
|
||||||
|
#
|
||||||
|
|
||||||
|
if (defined $global_device && $global_device ne $device) {
|
||||||
|
die "Multiple device types not yet supported.\n";
|
||||||
|
} else {
|
||||||
|
$global_device = $device;
|
||||||
|
}
|
||||||
|
|
||||||
|
# @ARGV = (@ARGV[0..$i - 1], "--device", "$device", @ARGV[$i..$#ARGV]);
|
||||||
|
@ARGV = ("--device", "$device", @ARGV);
|
||||||
|
|
||||||
|
$i += 2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Convert
|
||||||
|
#
|
||||||
|
|
||||||
|
$converted_frame = $arg;
|
||||||
|
$converted_frame =~ s/(?:\.[^.]*)?$/.pgm/;
|
||||||
|
$converted_frame =~ s/.*\///;
|
||||||
|
$converted_frame = $tempdir . "/" . $converted_frame;
|
||||||
|
|
||||||
|
`$ENV{"DCRAW"} -t 0 -d -4 -k 0 -r 1 1 1 1 -c $arg > $converted_frame`;
|
||||||
|
|
||||||
|
$ARGV[$i] = $converted_frame;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Try to get black level information
|
||||||
|
#
|
||||||
|
|
||||||
|
# XXX: The following approach is not obviously correct.
|
||||||
|
|
||||||
|
if (`$ENV{"DCRAW"} -d -v -c $arg 2>&1 1>/dev/null` =~ /black=(\d+)/) {
|
||||||
|
$black_unscaled = $1;
|
||||||
|
`$ENV{"DCRAW"} -D -4 -c $arg | pgmhist | tail -1` =~ /(\d+)/;
|
||||||
|
$maxval_unscaled = $1;
|
||||||
|
`pgmhist $converted_frame | tail -1` =~ /(\d+)/;
|
||||||
|
$maxval_scaled = $1;
|
||||||
|
|
||||||
|
$black_scaled = $black_unscaled
|
||||||
|
* ($maxval_scaled / $maxval_unscaled)
|
||||||
|
/ 65535;
|
||||||
|
|
||||||
|
@ARGV = (@ARGV[0..$i - 1], "--black", "$black_scaled", @ARGV[$i..$#ARGV]);
|
||||||
|
$i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
print ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($started_conversion) {
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
@ARGV = ($0, @ARGV);
|
||||||
|
|
||||||
|
if ($ENV{"ALE_COUNT_THREADS"} == 0) {
|
||||||
|
system { $ENV{"ALE_BIN"} } @ARGV;
|
||||||
|
} else {
|
||||||
|
$| = 1;
|
||||||
|
$fork1 = fork();
|
||||||
|
if ($fork1 == 0) {
|
||||||
|
exec { $ENV{"ALE_BIN"} } @ARGV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fork() == 0) {
|
||||||
|
$status_file = "/proc/$fork1/status";
|
||||||
|
while (-r $status_file && `cat $status_file 2> /dev/null | grep Threads` =~ /(\d+)/) {
|
||||||
|
if (defined $threads{$1}) {
|
||||||
|
$threads{$1}++;
|
||||||
|
} else {
|
||||||
|
$threads{$1} = 1;
|
||||||
|
}
|
||||||
|
sleep 1;
|
||||||
|
}
|
||||||
|
foreach $count (sort keys %threads) {
|
||||||
|
print("$count thread(s): $threads{$count} tick(s)\n");
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (wait() != -1) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
106
ale.cc
Normal file
106
ale.cc
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// Copyright 2002, 2003, 2004, 2005, 2006 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ale.cc: The main module of ale. This calls the input handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ale_fixed.h"
|
||||||
|
#include "ale_pos.h"
|
||||||
|
#include "ale_real.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version Information
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_MAGICK
|
||||||
|
#include <magick/api.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *package_name = PACKAGE_NAME;
|
||||||
|
|
||||||
|
const char *short_version = VERSION;
|
||||||
|
|
||||||
|
const char *version = PACKAGE_NAME " Version: " VERSION "\n"
|
||||||
|
#ifdef USE_MAGICK
|
||||||
|
"File handler: " MagickPackageName " " MagickLibVersionText " " MagickReleaseDate " " MagickQuantumDepth "\n"
|
||||||
|
#else
|
||||||
|
"File handler: PPM\n"
|
||||||
|
#endif
|
||||||
|
"Color data: " ALE_REAL_PRECISION_STRING "\n"
|
||||||
|
"Coordinate data: " ALE_POS_PRECISION_STRING "\n"
|
||||||
|
#ifdef USE_FFTW
|
||||||
|
"DFT: FFTW3\n"
|
||||||
|
#else
|
||||||
|
"DFT: Built-in\n"
|
||||||
|
#endif
|
||||||
|
#if defined USE_PTHREAD
|
||||||
|
"Threads: POSIX\n"
|
||||||
|
#else
|
||||||
|
"Threads: Disabled\n"
|
||||||
|
#endif
|
||||||
|
#if defined NDEBUG && !defined DEBUG
|
||||||
|
"Assertions: Disabled\n"
|
||||||
|
#elif defined DEBUG && !defined NDEBUG
|
||||||
|
"Assertions: Enabled\n"
|
||||||
|
#elif defined NDEBUG
|
||||||
|
"Assertions: Probably disabled\n"
|
||||||
|
#else
|
||||||
|
"Assertions: Probably enabled\n"
|
||||||
|
#endif
|
||||||
|
#if OPTIMIZATIONS == 1
|
||||||
|
"Optimizations: Enabled\n"
|
||||||
|
#else
|
||||||
|
"Optimizations: Disabled\n"
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* User interface includes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ui/ui.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* main() calls the input handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(int argc, const char *argv[]){
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call UI routine to handle options and other interface input.
|
||||||
|
* Returning from this function indicates program success.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ui::handle_input(argc, argv, package_name, short_version, version);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
59
ale_accum.h
Normal file
59
ale_accum.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2002, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ale_accum_h__
|
||||||
|
#define __ale_accum_h__
|
||||||
|
|
||||||
|
#include "ale_fixed.h"
|
||||||
|
|
||||||
|
#define FIXED16 4
|
||||||
|
#define FIXED32 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Real-valued type used when accumulating over the domain of an image.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if ALE_COLORS == FIXED16
|
||||||
|
|
||||||
|
typedef ale_fixed<ale_fixed_16_accum,12> ale_accum;
|
||||||
|
|
||||||
|
#define ale_accum_enable_casting() ale_accum::enable_casting()
|
||||||
|
#define ale_accum_disable_casting() ale_accum::disable_casting()
|
||||||
|
|
||||||
|
#elif ALE_COLORS == FIXED32
|
||||||
|
|
||||||
|
typedef ale_fixed<ale_fixed_32_accum,15> ale_accum;
|
||||||
|
|
||||||
|
#define ale_accum_enable_casting() ale_accum::enable_casting()
|
||||||
|
#define ale_accum_disable_casting() ale_accum::disable_casting()
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef double ale_accum;
|
||||||
|
|
||||||
|
#define ale_accum_disable_casting()
|
||||||
|
#define ale_accum_enable_casting()
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef FIXED32
|
||||||
|
#undef FIXED16
|
||||||
|
|
||||||
|
#endif
|
||||||
1074
ale_fixed.h
Normal file
1074
ale_fixed.h
Normal file
File diff suppressed because it is too large
Load Diff
76
ale_math.h
Normal file
76
ale_math.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2002, 2003, 2004, 2005, 2006 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ale_math_h__
|
||||||
|
#define __ale_math_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Certain versions of Mac OSX may disable math.h definitions of is*() macros
|
||||||
|
* when iostream is included, so we include the latter here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* isnan() and isinf() code logic are based on those noted in the GNU Autoconf
|
||||||
|
* manual, by the Free Software Foundation:
|
||||||
|
*
|
||||||
|
* http://www.gnu.org/software/autoconf/manual/html_node/Function-Portability.html
|
||||||
|
*
|
||||||
|
* As C++ is available here, we use C++ overloading instead of sizeof()
|
||||||
|
* switches to handle different types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FIXED16 4
|
||||||
|
#define FIXED32 5
|
||||||
|
|
||||||
|
|
||||||
|
#if ALE_COLORS == FIXED16 || ALE_COLORS == FIXED32 \
|
||||||
|
|| ALE_COORDINATES == FIXED16 || ALE_COORDINATES == FIXED32
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we need custom isnan and isinf for fixed-point values, we disable any
|
||||||
|
* such macros provided.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef isnan
|
||||||
|
#undef isinf
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef FIXED16
|
||||||
|
#undef FIXED32
|
||||||
|
|
||||||
|
#ifndef isnan
|
||||||
|
# define isnan(x) ale_isnan(x)
|
||||||
|
static inline int ale_isnan(float x) { return x != x; }
|
||||||
|
static inline int ale_isnan(double x) { return x != x; }
|
||||||
|
static inline int ale_isnan(long double x) { return x != x; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef isinf
|
||||||
|
# define isinf(x) ale_isinf(x)
|
||||||
|
static inline int ale_isinf(float x) { return isnan (x - x); }
|
||||||
|
static inline int ale_isinf(double x) { return isnan (x - x); }
|
||||||
|
static inline int ale_isinf(long double x) { return isnan (x - x); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
109
ale_pos.h
Normal file
109
ale_pos.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// Copyright 2002, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ale_pos_h__
|
||||||
|
#define __ale_pos_h__
|
||||||
|
|
||||||
|
#include "ale_fixed.h"
|
||||||
|
|
||||||
|
#define SINGLE 1
|
||||||
|
#define DOUBLE 2
|
||||||
|
#define FIXED16 3
|
||||||
|
#define FIXED32 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Real-valued type used to represent coordinates in an image domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if ALE_COORDINATES == SINGLE
|
||||||
|
|
||||||
|
typedef float ale_pos;
|
||||||
|
|
||||||
|
#define ALE_POS_PRECISION_STRING "SINGLE"
|
||||||
|
|
||||||
|
#define ale_pos_disable_casting()
|
||||||
|
#define ale_pos_enable_casting()
|
||||||
|
#define ale_pos_casting_status() 1
|
||||||
|
|
||||||
|
#elif ALE_COORDINATES == DOUBLE
|
||||||
|
|
||||||
|
typedef double ale_pos;
|
||||||
|
|
||||||
|
#define ALE_POS_PRECISION_STRING "DOUBLE"
|
||||||
|
|
||||||
|
#define ale_pos_disable_casting()
|
||||||
|
#define ale_pos_enable_casting()
|
||||||
|
#define ale_pos_casting_status() 1
|
||||||
|
|
||||||
|
#elif ALE_COORDINATES == FIXED32
|
||||||
|
|
||||||
|
typedef ale_fixed<ale_fixed_32,16> ale_pos;
|
||||||
|
|
||||||
|
#define ALE_POS_PRECISION_STRING "FIXED32"
|
||||||
|
|
||||||
|
#define ale_pos_disable_casting() ale_pos::disable_casting()
|
||||||
|
#define ale_pos_enable_casting() ale_pos::enable_casting()
|
||||||
|
#define ale_pos_casting_status() ale_pos::casting_status()
|
||||||
|
|
||||||
|
#elif ALE_COORDINATES == FIXED16
|
||||||
|
|
||||||
|
typedef ale_fixed<ale_fixed_16_calc,10> ale_pos;
|
||||||
|
|
||||||
|
#define ALE_POS_PRECISION_STRING "FIXED16"
|
||||||
|
|
||||||
|
#define ale_pos_disable_casting() ale_pos::disable_casting()
|
||||||
|
#define ale_pos_enable_casting() ale_pos::enable_casting()
|
||||||
|
#define ale_pos_casting_status() ale_pos::casting_status()
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#warning Unknown positional precision in ale_pos.h: Choosing PPRECISION=SINGLE.
|
||||||
|
|
||||||
|
typedef float ale_pos;
|
||||||
|
|
||||||
|
#define ALE_POS_PRECISION_STRING "SINGLE"
|
||||||
|
|
||||||
|
#define ale_pos_disable_casting()
|
||||||
|
#define ale_pos_enable_casting()
|
||||||
|
#define ale_pos_casting_status() 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const ale_pos ale_pos_0 = (ale_pos) 0;
|
||||||
|
|
||||||
|
#if ALE_COLORS == FIXED && ALE_COORDINATES == FIXED
|
||||||
|
|
||||||
|
#define ale_pos_to_real(x) (x)
|
||||||
|
#define ale_real_to_pos(x) (x)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define ale_pos_to_real(x) (x)
|
||||||
|
#define ale_real_to_pos(x) (x)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef SINGLE
|
||||||
|
#undef DOUBLE
|
||||||
|
#undef HALF
|
||||||
|
#undef FIXED16
|
||||||
|
#undef FIXED32
|
||||||
|
|
||||||
|
#endif
|
||||||
319
ale_real.h
Normal file
319
ale_real.h
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
// Copyright 2002, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ale_real_h__
|
||||||
|
#define __ale_real_h__
|
||||||
|
|
||||||
|
#include "ale_fixed.h"
|
||||||
|
|
||||||
|
#define SINGLE 1
|
||||||
|
#define DOUBLE 2
|
||||||
|
#define HALF 3
|
||||||
|
#define FIXED32 4
|
||||||
|
#define FIXED16 5
|
||||||
|
|
||||||
|
#define ale_real_enable_casting()
|
||||||
|
#define ale_real_disable_casting()
|
||||||
|
|
||||||
|
#define ale_real_unexceptional_negation(VALUE) -(VALUE)
|
||||||
|
|
||||||
|
#define ale_real_from_int(INT_VALUE, MAXVAL) (((float) (INT_VALUE)) / ((float) (MAXVAL)))
|
||||||
|
#define ale_real_to_int(REAL_VALUE, MAXVAL) round((float) (REAL_VALUE) * (MAXVAL))
|
||||||
|
#define ale_real_weight_floor 0.0001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Real-valued type used to represent the range of an image (colors, weights,
|
||||||
|
* etc.).
|
||||||
|
*
|
||||||
|
* ale_real is used in computation.
|
||||||
|
* ale_sreal is used for storage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if ALE_COLORS == SINGLE
|
||||||
|
|
||||||
|
typedef float ale_real;
|
||||||
|
typedef float ale_sreal;
|
||||||
|
|
||||||
|
#define ale_real_ip_weight_floor 1e-10
|
||||||
|
#define ale_real_confidence_floor 0.001
|
||||||
|
|
||||||
|
#define ALE_REAL_PRECISION_STRING "SINGLE"
|
||||||
|
|
||||||
|
#elif ALE_COLORS == DOUBLE
|
||||||
|
|
||||||
|
typedef double ale_real;
|
||||||
|
typedef double ale_sreal;
|
||||||
|
|
||||||
|
#define ale_real_ip_weight_floor 1e-10
|
||||||
|
#define ale_real_confidence_floor 0.000001
|
||||||
|
|
||||||
|
#define ALE_REAL_PRECISION_STRING "DOUBLE"
|
||||||
|
|
||||||
|
#elif ALE_COLORS == HALF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* What follows is one approach to packing a floating point
|
||||||
|
* number into 16 bits. This implementation is very slow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MANTISSA_BITS (9)
|
||||||
|
#define EXP_BITS (15 - MANTISSA_BITS)
|
||||||
|
#define EXP_SPECIAL (1 << (EXP_BITS - 1))
|
||||||
|
#define EXP_MAX (EXP_SPECIAL - 1)
|
||||||
|
#define EXP_MIN (-EXP_MAX)
|
||||||
|
|
||||||
|
typedef float ale_real;
|
||||||
|
|
||||||
|
class ale_sreal {
|
||||||
|
|
||||||
|
union {
|
||||||
|
uint16_t bits;
|
||||||
|
struct {
|
||||||
|
uint16_t sign:1;
|
||||||
|
uint16_t mant:MANTISSA_BITS;
|
||||||
|
int16_t exp :EXP_BITS;
|
||||||
|
} fpr;
|
||||||
|
} u;
|
||||||
|
public:
|
||||||
|
ale_sreal() {
|
||||||
|
u.bits = 0;
|
||||||
|
}
|
||||||
|
ale_sreal operator=(float v) {
|
||||||
|
if (v == 0) {
|
||||||
|
u.bits = 0;
|
||||||
|
} else if (isnan(v)) {
|
||||||
|
u.fpr.exp = EXP_SPECIAL;
|
||||||
|
u.fpr.mant = 1;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (v > 0)
|
||||||
|
u.fpr.sign = 0;
|
||||||
|
else if (v < 0) {
|
||||||
|
u.fpr.sign = 1;
|
||||||
|
v = -v;
|
||||||
|
} else
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the exponent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int log2 = (int) floor (log(v) / log(2));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test the exponent against the largest expressible
|
||||||
|
* exponent for ale_sreal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (log2 > EXP_MAX) {
|
||||||
|
/*
|
||||||
|
* Infinity
|
||||||
|
*/
|
||||||
|
|
||||||
|
u.fpr.exp = EXP_SPECIAL;
|
||||||
|
u.fpr.mant = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test the exponent against the smallest expressible
|
||||||
|
* exponent for ale_sreal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (log2 < EXP_MIN) {
|
||||||
|
/*
|
||||||
|
* Zero
|
||||||
|
*/
|
||||||
|
|
||||||
|
u.fpr.exp = 0x0;
|
||||||
|
u.fpr.mant = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The exponent is in range, so use it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
u.fpr.exp = log2;
|
||||||
|
|
||||||
|
u.fpr.mant = (uint16_t) floor(v / pow(2, log2) * (1 << (MANTISSA_BITS - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator float() const {
|
||||||
|
float result = 3.14159;
|
||||||
|
|
||||||
|
if (((uint16_t) u.fpr.exp == EXP_SPECIAL) && (u.fpr.mant == 1)) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NaN
|
||||||
|
*/
|
||||||
|
|
||||||
|
float a = 0;
|
||||||
|
float b = 0;
|
||||||
|
|
||||||
|
result = a / b;
|
||||||
|
|
||||||
|
} else if (((uint16_t) u.fpr.exp == EXP_SPECIAL) && (u.fpr.mant == 0)) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Infinity
|
||||||
|
*/
|
||||||
|
|
||||||
|
float a = 1;
|
||||||
|
float b = 0;
|
||||||
|
|
||||||
|
result = (a / b);
|
||||||
|
|
||||||
|
} else if ((uint16_t) u.fpr.exp != EXP_SPECIAL) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Value is finite.
|
||||||
|
*/
|
||||||
|
|
||||||
|
result = u.fpr.mant / ((double) (1 << (MANTISSA_BITS - 1)))
|
||||||
|
* pow(2, u.fpr.exp);
|
||||||
|
|
||||||
|
} else
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
if (u.fpr.sign)
|
||||||
|
result = -result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_sreal operator-=(float r) {
|
||||||
|
*this = (float) *this - (float) r;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ale_sreal operator/=(float r) {
|
||||||
|
*this = (float) *this / (float) r;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ale_sreal operator*=(float r) {
|
||||||
|
*this = (float) *this * (float) r;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ale_sreal operator+=(float r) {
|
||||||
|
*this = (float) *this + (float) r;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef MANTISSA_BITS
|
||||||
|
#undef EXP_BITS
|
||||||
|
#undef EXP_SPECIAL
|
||||||
|
#undef EXP_MAX
|
||||||
|
#undef EXP_MIN
|
||||||
|
|
||||||
|
#define ALE_REAL_PRECISION_STRING "HALF"
|
||||||
|
|
||||||
|
#elif ALE_COLORS == FIXED32
|
||||||
|
|
||||||
|
typedef ale_fixed<ale_fixed_32,16> ale_real;
|
||||||
|
typedef ale_fixed<ale_fixed_32,16> ale_sreal;
|
||||||
|
|
||||||
|
#undef ale_real_enable_casting
|
||||||
|
#undef ale_real_disable_casting
|
||||||
|
#define ale_real_enable_casting() ale_real::enable_casting()
|
||||||
|
#define ale_real_disable_casting() ale_real::disable_casting()
|
||||||
|
|
||||||
|
#undef ale_real_unexceptional_negation
|
||||||
|
#define ale_real_unexceptional_negation(VALUE) (VALUE).unexceptional_negation();
|
||||||
|
|
||||||
|
#undef ale_real_to_int
|
||||||
|
#undef ale_real_from_int
|
||||||
|
#define ale_real_to_int(REAL_VALUE, MAXVAL) ( (MAXVAL == 255) \
|
||||||
|
? (int) ale_fixed<ale_fixed_16_calc,8>::fixed_to_bits(REAL_VALUE) \
|
||||||
|
: ( (MAXVAL == 65535) \
|
||||||
|
? (int) ale_fixed<ale_fixed_16_calc,16>::fixed_to_bits(REAL_VALUE) \
|
||||||
|
: (int) round((float) (REAL_VALUE) * (MAXVAL)) ) )
|
||||||
|
|
||||||
|
#define ale_real_from_int(INT_VALUE, MAXVAL) ( (MAXVAL == 255) \
|
||||||
|
? (ale_real) ale_fixed<ale_fixed_16_calc,8>::bits_to_fixed(INT_VALUE) \
|
||||||
|
: ( (MAXVAL == 65535) \
|
||||||
|
? (ale_real) ale_fixed<ale_fixed_16_calc,16>::bits_to_fixed(INT_VALUE) \
|
||||||
|
: (ale_real) (((float) (INT_VALUE)) / ((float) (MAXVAL))) ) )
|
||||||
|
|
||||||
|
#define ale_real_ip_weight_floor (1 / (ale_real) 100)
|
||||||
|
#define ale_real_confidence_floor (1 / (ale_real) 10)
|
||||||
|
|
||||||
|
#define ALE_REAL_PRECISION_STRING "FIXED32"
|
||||||
|
|
||||||
|
#elif ALE_COLORS == FIXED16
|
||||||
|
|
||||||
|
typedef ale_fixed<ale_fixed_16_calc,14> ale_real;
|
||||||
|
typedef ale_fixed<ale_fixed_16,12> ale_sreal;
|
||||||
|
|
||||||
|
#undef ale_real_enable_casting
|
||||||
|
#undef ale_real_disable_casting
|
||||||
|
#define ale_real_enable_casting() ale_real::enable_casting()
|
||||||
|
#define ale_real_disable_casting() ale_real::disable_casting()
|
||||||
|
|
||||||
|
#undef ale_real_unexceptional_negation
|
||||||
|
#define ale_real_unexceptional_negation(VALUE) (VALUE).unexceptional_negation();
|
||||||
|
|
||||||
|
#undef ale_real_to_int
|
||||||
|
#undef ale_real_from_int
|
||||||
|
#define ale_real_to_int(REAL_VALUE, MAXVAL) ( (MAXVAL == 255) \
|
||||||
|
? (int) ale_fixed<ale_fixed_16_calc,8>::fixed_to_bits(REAL_VALUE) \
|
||||||
|
: ( (MAXVAL == 65535) \
|
||||||
|
? (int) ale_fixed<ale_fixed_16_calc,16>::fixed_to_bits(REAL_VALUE) \
|
||||||
|
: (int) round((float) (REAL_VALUE) * (MAXVAL)) ) )
|
||||||
|
|
||||||
|
#define ale_real_from_int(INT_VALUE, MAXVAL) ( (MAXVAL == 255) \
|
||||||
|
? (ale_real) ale_fixed<ale_fixed_16_calc,8>::bits_to_fixed(INT_VALUE) \
|
||||||
|
: ( (MAXVAL == 65535) \
|
||||||
|
? (ale_real) ale_fixed<ale_fixed_16_calc,16>::bits_to_fixed(INT_VALUE) \
|
||||||
|
: (ale_real) (((float) (INT_VALUE)) / ((float) (MAXVAL))) ) )
|
||||||
|
|
||||||
|
#define ale_real_ip_weight_floor (1 / (ale_real) 100)
|
||||||
|
#define ale_real_confidence_floor (1 / (ale_real) 10)
|
||||||
|
|
||||||
|
#define ALE_REAL_PRECISION_STRING "FIXED16"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#warning Unknown precision in ale_real.h: Choosing PRECISION=SINGLE.
|
||||||
|
|
||||||
|
typedef float ale_real;
|
||||||
|
typedef float ale_sreal;
|
||||||
|
|
||||||
|
#define ale_real_ip_weight_floor 1e-10
|
||||||
|
#define ale_real_confidence_floor 0.001
|
||||||
|
|
||||||
|
#define ALE_REAL_PRECISION_STRING "SINGLE"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const ale_real ale_real_0 = (ale_real) 0;
|
||||||
|
|
||||||
|
#undef SINGLE
|
||||||
|
#undef DOUBLE
|
||||||
|
#undef HALF
|
||||||
|
#undef FIXED16
|
||||||
|
#undef FIXED32
|
||||||
|
|
||||||
|
#endif
|
||||||
26288
autom4te.cache/output.0
Normal file
26288
autom4te.cache/output.0
Normal file
File diff suppressed because it is too large
Load Diff
26288
autom4te.cache/output.1
Normal file
26288
autom4te.cache/output.1
Normal file
File diff suppressed because it is too large
Load Diff
26288
autom4te.cache/output.2
Normal file
26288
autom4te.cache/output.2
Normal file
File diff suppressed because it is too large
Load Diff
647
autom4te.cache/requests
Normal file
647
autom4te.cache/requests
Normal file
@@ -0,0 +1,647 @@
|
|||||||
|
# This file was generated by Autom4te Tue Feb 10 11:42:58 UTC 2009.
|
||||||
|
# It contains the lists of macros which have been traced.
|
||||||
|
# It can be safely removed.
|
||||||
|
|
||||||
|
@request = (
|
||||||
|
bless( [
|
||||||
|
'0',
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
'/usr/share/autoconf'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'/usr/share/autoconf/autoconf/autoconf.m4f',
|
||||||
|
'/usr/share/aclocal/argz.m4',
|
||||||
|
'/usr/share/aclocal/libtool.m4',
|
||||||
|
'/usr/share/aclocal/ltdl.m4',
|
||||||
|
'/usr/share/aclocal/ltoptions.m4',
|
||||||
|
'/usr/share/aclocal/ltsugar.m4',
|
||||||
|
'/usr/share/aclocal/ltversion.m4',
|
||||||
|
'/usr/share/aclocal/lt~obsolete.m4',
|
||||||
|
'/usr/share/aclocal/nls.m4',
|
||||||
|
'/usr/share/aclocal/po.m4',
|
||||||
|
'/usr/share/aclocal/progtest.m4',
|
||||||
|
'/usr/share/aclocal-1.10/amversion.m4',
|
||||||
|
'/usr/share/aclocal-1.10/auxdir.m4',
|
||||||
|
'/usr/share/aclocal-1.10/cond.m4',
|
||||||
|
'/usr/share/aclocal-1.10/depend.m4',
|
||||||
|
'/usr/share/aclocal-1.10/depout.m4',
|
||||||
|
'/usr/share/aclocal-1.10/init.m4',
|
||||||
|
'/usr/share/aclocal-1.10/install-sh.m4',
|
||||||
|
'/usr/share/aclocal-1.10/lead-dot.m4',
|
||||||
|
'/usr/share/aclocal-1.10/make.m4',
|
||||||
|
'/usr/share/aclocal-1.10/missing.m4',
|
||||||
|
'/usr/share/aclocal-1.10/mkdirp.m4',
|
||||||
|
'/usr/share/aclocal-1.10/options.m4',
|
||||||
|
'/usr/share/aclocal-1.10/runlog.m4',
|
||||||
|
'/usr/share/aclocal-1.10/sanity.m4',
|
||||||
|
'/usr/share/aclocal-1.10/strip.m4',
|
||||||
|
'/usr/share/aclocal-1.10/substnot.m4',
|
||||||
|
'/usr/share/aclocal-1.10/tar.m4',
|
||||||
|
'm4/acx_pthread.m4',
|
||||||
|
'm4/errno_h.m4',
|
||||||
|
'm4/error.m4',
|
||||||
|
'm4/extensions.m4',
|
||||||
|
'm4/gnulib-common.m4',
|
||||||
|
'm4/gnulib-comp.m4',
|
||||||
|
'm4/gnulib-tool.m4',
|
||||||
|
'm4/include_next.m4',
|
||||||
|
'm4/stdbool.m4',
|
||||||
|
'm4/stdlib_h.m4',
|
||||||
|
'm4/strerror.m4',
|
||||||
|
'm4/string_h.m4',
|
||||||
|
'm4/strndup.m4',
|
||||||
|
'm4/strnlen.m4',
|
||||||
|
'm4/strtod.m4',
|
||||||
|
'm4/unistd_h.m4',
|
||||||
|
'configure.in'
|
||||||
|
],
|
||||||
|
{
|
||||||
|
'AM_ENABLE_STATIC' => 1,
|
||||||
|
'AM_XGETTEXT_OPTION_INIT' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
||||||
|
'_LT_AC_SHELL_INIT' => 1,
|
||||||
|
'AC_DEFUN' => 1,
|
||||||
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
|
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AM_PROG_MKDIR_P' => 1,
|
||||||
|
'gl_UNISTD_MODULE_INDICATOR' => 1,
|
||||||
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AC_FUNC_STRTOD' => 1,
|
||||||
|
'AM_MISSING_PROG' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
||||||
|
'_LT_AC_LANG_C_CONFIG' => 1,
|
||||||
|
'gl_INCLUDE_NEXT' => 1,
|
||||||
|
'AM_PROG_INSTALL_STRIP' => 1,
|
||||||
|
'_m4_warn' => 1,
|
||||||
|
'AC_LIBTOOL_OBJDIR' => 1,
|
||||||
|
'gl_FUNC_STRNDUP' => 1,
|
||||||
|
'gl_FUNC_ARGZ' => 1,
|
||||||
|
'gl_PREREQ_STRTOD' => 1,
|
||||||
|
'AM_SANITY_CHECK' => 1,
|
||||||
|
'LTOBSOLETE_VERSION' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
||||||
|
'LT_LIB_M' => 1,
|
||||||
|
'_LT_AC_CHECK_DLFCN' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
||||||
|
'LTSUGAR_VERSION' => 1,
|
||||||
|
'_LT_PROG_LTMAIN' => 1,
|
||||||
|
'_AM_PROG_TAR' => 1,
|
||||||
|
'LT_SYS_SYMBOL_USCORE' => 1,
|
||||||
|
'gl_HEADER_ERRNO_H' => 1,
|
||||||
|
'AC_LIBTOOL_GCJ' => 1,
|
||||||
|
'gl_LIBOBJ' => 1,
|
||||||
|
'gl_FUNC_STRERROR_SEPARATE' => 1,
|
||||||
|
'LT_FUNC_DLSYM_USCORE' => 1,
|
||||||
|
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'_LT_AC_LANG_F77' => 1,
|
||||||
|
'AC_LIBTOOL_CONFIG' => 1,
|
||||||
|
'gl_ERROR' => 1,
|
||||||
|
'gl_PO_BASE' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'AC_LTDL_DLLIB' => 1,
|
||||||
|
'_AM_AUTOCONF_VERSION' => 1,
|
||||||
|
'AM_DISABLE_SHARED' => 1,
|
||||||
|
'_LTDL_SETUP' => 1,
|
||||||
|
'_LT_AC_LANG_CXX' => 1,
|
||||||
|
'AM_PROG_LIBTOOL' => 1,
|
||||||
|
'AC_LIB_LTDL' => 1,
|
||||||
|
'_LT_AC_FILE_LTDLL_C' => 1,
|
||||||
|
'AM_PROG_LD' => 1,
|
||||||
|
'AC_USE_SYSTEM_EXTENSIONS' => 1,
|
||||||
|
'AU_DEFUN' => 1,
|
||||||
|
'AC_PROG_NM' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN' => 1,
|
||||||
|
'AC_PROG_LD' => 1,
|
||||||
|
'AC_PROG_LD_GNU' => 1,
|
||||||
|
'AC_ENABLE_FAST_INSTALL' => 1,
|
||||||
|
'gltests_LIBSOURCES' => 1,
|
||||||
|
'gl_FUNC_STRNLEN' => 1,
|
||||||
|
'AC_LIBTOOL_FC' => 1,
|
||||||
|
'LTDL_CONVENIENCE' => 1,
|
||||||
|
'gltests_REPLACE_FUNCS' => 1,
|
||||||
|
'_AM_SET_OPTION' => 1,
|
||||||
|
'AC_LTDL_PREOPEN' => 1,
|
||||||
|
'gl_HEADER_STRING_H_DEFAULTS' => 1,
|
||||||
|
'_LT_LINKER_BOILERPLATE' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
||||||
|
'gl_PREREQ_ARGZ' => 1,
|
||||||
|
'gl_STDLIB_MODULE_INDICATOR' => 1,
|
||||||
|
'gl_HEADER_STRING_H' => 1,
|
||||||
|
'AM_STDBOOL_H' => 1,
|
||||||
|
'gl_LIB' => 1,
|
||||||
|
'gl_STDBOOL_H' => 1,
|
||||||
|
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
|
'gl_COMMON_BODY' => 1,
|
||||||
|
'LT_SYS_MODULE_EXT' => 1,
|
||||||
|
'LT_PROG_RC' => 1,
|
||||||
|
'gl_PREREQ_ERROR' => 1,
|
||||||
|
'AC_DEFUN_ONCE' => 1,
|
||||||
|
'AC_C_RESTRICT' => 1,
|
||||||
|
'gl_EARLY' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ' => 1,
|
||||||
|
'gl_WITH_TESTS' => 1,
|
||||||
|
'gl_LIBTOOL' => 1,
|
||||||
|
'AC_LTDL_OBJDIR' => 1,
|
||||||
|
'gl_REPLACE_FUNCS' => 1,
|
||||||
|
'gl_FUNC_STRTOD' => 1,
|
||||||
|
'_LT_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'AC_LIBTOOL_RC' => 1,
|
||||||
|
'AC_DISABLE_FAST_INSTALL' => 1,
|
||||||
|
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
||||||
|
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
||||||
|
'gl_PO_DOMAIN' => 1,
|
||||||
|
'include' => 1,
|
||||||
|
'LT_AC_PROG_SED' => 1,
|
||||||
|
'AM_ENABLE_SHARED' => 1,
|
||||||
|
'LTDL_INSTALLABLE' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'AM_POSTPROCESS_PO_MAKEFILE' => 1,
|
||||||
|
'AC_ENABLE_SHARED' => 1,
|
||||||
|
'gl_DOC_BASE' => 1,
|
||||||
|
'gl_HEADER_ERRNO_H_BODY' => 1,
|
||||||
|
'AC_ENABLE_STATIC' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
||||||
|
'_LT_AC_TAGVAR' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
||||||
|
'AM_CONDITIONAL' => 1,
|
||||||
|
'LT_LIB_DLLOAD' => 1,
|
||||||
|
'gl_INIT' => 1,
|
||||||
|
'LTDL_INIT' => 1,
|
||||||
|
'LTVERSION_VERSION' => 1,
|
||||||
|
'gl_VC_FILES' => 1,
|
||||||
|
'AM_PROG_INSTALL_SH' => 1,
|
||||||
|
'gl_PREREQ_STRNDUP' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'AC_PROG_EGREP' => 1,
|
||||||
|
'gl_LGPL' => 1,
|
||||||
|
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
||||||
|
'AC_PATH_MAGIC' => 1,
|
||||||
|
'AC_LTDL_SYSSEARCHPATH' => 1,
|
||||||
|
'AM_MAKE_INCLUDE' => 1,
|
||||||
|
'LT_CMD_MAX_LEN' => 1,
|
||||||
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
|
'AM_PO_SUBDIRS' => 1,
|
||||||
|
'm4_pattern_forbid' => 1,
|
||||||
|
'_LT_LINKER_OPTION' => 1,
|
||||||
|
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
||||||
|
'AC_DISABLE_SHARED' => 1,
|
||||||
|
'gl_AVOID' => 1,
|
||||||
|
'_LT_COMPILER_BOILERPLATE' => 1,
|
||||||
|
'AC_LIBTOOL_WIN32_DLL' => 1,
|
||||||
|
'AC_LIBTOOL_SETUP' => 1,
|
||||||
|
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
||||||
|
'AC_LTDL_DLSYM_USCORE' => 1,
|
||||||
|
'gl_MODULES' => 1,
|
||||||
|
'LT_LANG' => 1,
|
||||||
|
'AM_MISSING_HAS_RUN' => 1,
|
||||||
|
'LT_SYS_DLSEARCH_PATH' => 1,
|
||||||
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
|
'gl_MACRO_PREFIX' => 1,
|
||||||
|
'LT_OUTPUT' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
||||||
|
'gl_CHECK_NEXT_HEADERS' => 1,
|
||||||
|
'AM_NLS' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
||||||
|
'gl_FUNC_STRERROR' => 1,
|
||||||
|
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
||||||
|
'AC_WITH_LTDL' => 1,
|
||||||
|
'gl_FILE_LIST' => 1,
|
||||||
|
'AC_LIBTOOL_CXX' => 1,
|
||||||
|
'LT_AC_PROG_RC' => 1,
|
||||||
|
'LT_INIT' => 1,
|
||||||
|
'gl_USE_SYSTEM_EXTENSIONS' => 1,
|
||||||
|
'LT_SYS_DLOPEN_SELF' => 1,
|
||||||
|
'LT_AC_PROG_GCJ' => 1,
|
||||||
|
'AM_DISABLE_STATIC' => 1,
|
||||||
|
'AM_DEP_TRACK' => 1,
|
||||||
|
'_AC_PROG_LIBTOOL' => 1,
|
||||||
|
'AC_COMPUTE_INT' => 1,
|
||||||
|
'_AM_IF_OPTION' => 1,
|
||||||
|
'AC_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'AC_LIBTOOL_F77' => 1,
|
||||||
|
'm4_pattern_allow' => 1,
|
||||||
|
'AM_PATH_PROG_WITH_TEST' => 1,
|
||||||
|
'gl_HEADER_STRING_H_BODY' => 1,
|
||||||
|
'AM_SET_LEADING_DOT' => 1,
|
||||||
|
'gl_UNISTD_H_DEFAULTS' => 1,
|
||||||
|
'LT_AC_PROG_EGREP' => 1,
|
||||||
|
'_AM_DEPENDENCIES' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
||||||
|
'LTOPTIONS_VERSION' => 1,
|
||||||
|
'_LT_AC_SYS_COMPILER' => 1,
|
||||||
|
'AM_PROG_NM' => 1,
|
||||||
|
'gl_PREREQ_STRNLEN' => 1,
|
||||||
|
'gl_STDLIB_H' => 1,
|
||||||
|
'AC_LIBLTDL_CONVENIENCE' => 1,
|
||||||
|
'gl_M4_BASE' => 1,
|
||||||
|
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
||||||
|
'AC_LIBLTDL_INSTALLABLE' => 1,
|
||||||
|
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AC_LTDL_ENABLE_INSTALL' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
||||||
|
'LT_PROG_GCJ' => 1,
|
||||||
|
'gl_STRING_MODULE_INDICATOR' => 1,
|
||||||
|
'gl_PREREQ_STRERROR' => 1,
|
||||||
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
|
'AC_PROG_MKDIR_P' => 1,
|
||||||
|
'AC_DISABLE_STATIC' => 1,
|
||||||
|
'gl_REPLACE_ERRNO_VALUE' => 1,
|
||||||
|
'gl_LOCAL_DIR' => 1,
|
||||||
|
'LT_PATH_NM' => 1,
|
||||||
|
'AC_LTDL_SHLIBEXT' => 1,
|
||||||
|
'_LT_AC_LOCK' => 1,
|
||||||
|
'_LT_AC_LANG_RC_CONFIG' => 1,
|
||||||
|
'gl_COMMON' => 1,
|
||||||
|
'gl_MODULE_INDICATOR' => 1,
|
||||||
|
'gl_TESTS_BASE' => 1,
|
||||||
|
'AC_HEADER_STDBOOL' => 1,
|
||||||
|
'LT_SYS_MODULE_PATH' => 1,
|
||||||
|
'gl_UNISTD_H' => 1,
|
||||||
|
'LT_WITH_LTDL' => 1,
|
||||||
|
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
||||||
|
'AC_LTDL_SHLIBPATH' => 1,
|
||||||
|
'gl_LIBSOURCES' => 1,
|
||||||
|
'gl_STDLIB_H_DEFAULTS' => 1,
|
||||||
|
'gltests_LIBOBJ' => 1,
|
||||||
|
'AM_AUX_DIR_EXPAND' => 1,
|
||||||
|
'gl_SOURCE_BASE' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
||||||
|
'_LT_AC_LANG_F77_CONFIG' => 1,
|
||||||
|
'_AM_SET_OPTIONS' => 1,
|
||||||
|
'_LT_COMPILER_OPTION' => 1,
|
||||||
|
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'AM_RUN_LOG' => 1,
|
||||||
|
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
||||||
|
'AC_LIBTOOL_PICMODE' => 1,
|
||||||
|
'gl_MAKEFILE_NAME' => 1,
|
||||||
|
'LT_PATH_LD' => 1,
|
||||||
|
'AC_CHECK_LIBM' => 1,
|
||||||
|
'ACX_PTHREAD' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
||||||
|
'_AM_MANGLE_OPTION' => 1,
|
||||||
|
'AM_XGETTEXT_OPTION' => 1,
|
||||||
|
'AC_LTDL_SYMBOL_USCORE' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
||||||
|
'AM_SET_DEPDIR' => 1,
|
||||||
|
'_LT_CC_BASENAME' => 1,
|
||||||
|
'_LT_LIBOBJ' => 1
|
||||||
|
}
|
||||||
|
], 'Autom4te::Request' ),
|
||||||
|
bless( [
|
||||||
|
'1',
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
'/usr/share/autoconf'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'/usr/share/autoconf/autoconf/autoconf.m4f',
|
||||||
|
'aclocal.m4',
|
||||||
|
'configure.in'
|
||||||
|
],
|
||||||
|
{
|
||||||
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
|
'AM_PROG_F77_C_O' => 1,
|
||||||
|
'm4_pattern_forbid' => 1,
|
||||||
|
'AC_INIT' => 1,
|
||||||
|
'_AM_COND_IF' => 1,
|
||||||
|
'AC_CANONICAL_TARGET' => 1,
|
||||||
|
'AC_SUBST' => 1,
|
||||||
|
'AC_CONFIG_LIBOBJ_DIR' => 1,
|
||||||
|
'AC_FC_SRCEXT' => 1,
|
||||||
|
'AC_CANONICAL_HOST' => 1,
|
||||||
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
|
'AC_CONFIG_SUBDIRS' => 1,
|
||||||
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
|
'AC_REQUIRE_AUX_FILE' => 1,
|
||||||
|
'AC_CONFIG_LINKS' => 1,
|
||||||
|
'm4_sinclude' => 1,
|
||||||
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
|
'AM_MAINTAINER_MODE' => 1,
|
||||||
|
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
|
||||||
|
'_m4_warn' => 1,
|
||||||
|
'AM_PROG_CXX_C_O' => 1,
|
||||||
|
'_AM_COND_ENDIF' => 1,
|
||||||
|
'AM_ENABLE_MULTILIB' => 1,
|
||||||
|
'AC_CONFIG_FILES' => 1,
|
||||||
|
'LT_INIT' => 1,
|
||||||
|
'include' => 1,
|
||||||
|
'AM_GNU_GETTEXT' => 1,
|
||||||
|
'AC_LIBSOURCE' => 1,
|
||||||
|
'AM_PROG_FC_C_O' => 1,
|
||||||
|
'AC_CANONICAL_BUILD' => 1,
|
||||||
|
'AC_FC_FREEFORM' => 1,
|
||||||
|
'AH_OUTPUT' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'AC_CONFIG_AUX_DIR' => 1,
|
||||||
|
'sinclude' => 1,
|
||||||
|
'm4_pattern_allow' => 1,
|
||||||
|
'AM_PROG_CC_C_O' => 1,
|
||||||
|
'AC_CANONICAL_SYSTEM' => 1,
|
||||||
|
'AM_CONDITIONAL' => 1,
|
||||||
|
'AC_CONFIG_HEADERS' => 1,
|
||||||
|
'AC_DEFINE_TRACE_LITERAL' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'_AM_COND_ELSE' => 1,
|
||||||
|
'AC_SUBST_TRACE' => 1
|
||||||
|
}
|
||||||
|
], 'Autom4te::Request' ),
|
||||||
|
bless( [
|
||||||
|
'2',
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
'/usr/share/autoconf'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'/usr/share/autoconf/autoconf/autoconf.m4f',
|
||||||
|
'/usr/share/aclocal/argz.m4',
|
||||||
|
'/usr/share/aclocal/ltdl.m4',
|
||||||
|
'/usr/share/aclocal/nls.m4',
|
||||||
|
'/usr/share/aclocal/po.m4',
|
||||||
|
'/usr/share/aclocal/progtest.m4',
|
||||||
|
'/usr/share/aclocal-1.10/amversion.m4',
|
||||||
|
'/usr/share/aclocal-1.10/auxdir.m4',
|
||||||
|
'/usr/share/aclocal-1.10/cond.m4',
|
||||||
|
'/usr/share/aclocal-1.10/depend.m4',
|
||||||
|
'/usr/share/aclocal-1.10/depout.m4',
|
||||||
|
'/usr/share/aclocal-1.10/init.m4',
|
||||||
|
'/usr/share/aclocal-1.10/install-sh.m4',
|
||||||
|
'/usr/share/aclocal-1.10/lead-dot.m4',
|
||||||
|
'/usr/share/aclocal-1.10/make.m4',
|
||||||
|
'/usr/share/aclocal-1.10/missing.m4',
|
||||||
|
'/usr/share/aclocal-1.10/mkdirp.m4',
|
||||||
|
'/usr/share/aclocal-1.10/options.m4',
|
||||||
|
'/usr/share/aclocal-1.10/runlog.m4',
|
||||||
|
'/usr/share/aclocal-1.10/sanity.m4',
|
||||||
|
'/usr/share/aclocal-1.10/strip.m4',
|
||||||
|
'/usr/share/aclocal-1.10/substnot.m4',
|
||||||
|
'/usr/share/aclocal-1.10/tar.m4',
|
||||||
|
'm4/acx_pthread.m4',
|
||||||
|
'm4/errno_h.m4',
|
||||||
|
'm4/error.m4',
|
||||||
|
'm4/extensions.m4',
|
||||||
|
'm4/gnulib-common.m4',
|
||||||
|
'm4/gnulib-comp.m4',
|
||||||
|
'm4/gnulib-tool.m4',
|
||||||
|
'm4/include_next.m4',
|
||||||
|
'm4/libtool.m4',
|
||||||
|
'm4/ltoptions.m4',
|
||||||
|
'm4/ltsugar.m4',
|
||||||
|
'm4/ltversion.m4',
|
||||||
|
'm4/lt~obsolete.m4',
|
||||||
|
'm4/stdbool.m4',
|
||||||
|
'm4/stdlib_h.m4',
|
||||||
|
'm4/strerror.m4',
|
||||||
|
'm4/string_h.m4',
|
||||||
|
'm4/strndup.m4',
|
||||||
|
'm4/strnlen.m4',
|
||||||
|
'm4/strtod.m4',
|
||||||
|
'm4/unistd_h.m4',
|
||||||
|
'configure.in'
|
||||||
|
],
|
||||||
|
{
|
||||||
|
'AM_ENABLE_STATIC' => 1,
|
||||||
|
'AM_XGETTEXT_OPTION_INIT' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
||||||
|
'_LT_AC_SHELL_INIT' => 1,
|
||||||
|
'AC_DEFUN' => 1,
|
||||||
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
|
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AM_PROG_MKDIR_P' => 1,
|
||||||
|
'gl_UNISTD_MODULE_INDICATOR' => 1,
|
||||||
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AC_FUNC_STRTOD' => 1,
|
||||||
|
'AM_MISSING_PROG' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
||||||
|
'_LT_AC_LANG_C_CONFIG' => 1,
|
||||||
|
'gl_INCLUDE_NEXT' => 1,
|
||||||
|
'AM_PROG_INSTALL_STRIP' => 1,
|
||||||
|
'_m4_warn' => 1,
|
||||||
|
'AC_LIBTOOL_OBJDIR' => 1,
|
||||||
|
'gl_FUNC_STRNDUP' => 1,
|
||||||
|
'gl_FUNC_ARGZ' => 1,
|
||||||
|
'gl_PREREQ_STRTOD' => 1,
|
||||||
|
'AM_SANITY_CHECK' => 1,
|
||||||
|
'LTOBSOLETE_VERSION' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
||||||
|
'LT_LIB_M' => 1,
|
||||||
|
'_LT_AC_CHECK_DLFCN' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
||||||
|
'LTSUGAR_VERSION' => 1,
|
||||||
|
'_LT_PROG_LTMAIN' => 1,
|
||||||
|
'_AM_PROG_TAR' => 1,
|
||||||
|
'LT_SYS_SYMBOL_USCORE' => 1,
|
||||||
|
'gl_HEADER_ERRNO_H' => 1,
|
||||||
|
'AC_LIBTOOL_GCJ' => 1,
|
||||||
|
'gl_LIBOBJ' => 1,
|
||||||
|
'gl_FUNC_STRERROR_SEPARATE' => 1,
|
||||||
|
'LT_FUNC_DLSYM_USCORE' => 1,
|
||||||
|
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'_LT_AC_LANG_F77' => 1,
|
||||||
|
'AC_LIBTOOL_CONFIG' => 1,
|
||||||
|
'gl_ERROR' => 1,
|
||||||
|
'gl_PO_BASE' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'AC_LTDL_DLLIB' => 1,
|
||||||
|
'_AM_AUTOCONF_VERSION' => 1,
|
||||||
|
'AM_DISABLE_SHARED' => 1,
|
||||||
|
'_LTDL_SETUP' => 1,
|
||||||
|
'_LT_AC_LANG_CXX' => 1,
|
||||||
|
'AM_PROG_LIBTOOL' => 1,
|
||||||
|
'AC_LIB_LTDL' => 1,
|
||||||
|
'_LT_AC_FILE_LTDLL_C' => 1,
|
||||||
|
'AM_PROG_LD' => 1,
|
||||||
|
'AC_USE_SYSTEM_EXTENSIONS' => 1,
|
||||||
|
'AU_DEFUN' => 1,
|
||||||
|
'AC_PROG_NM' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN' => 1,
|
||||||
|
'AC_PROG_LD' => 1,
|
||||||
|
'AC_PROG_LD_GNU' => 1,
|
||||||
|
'AC_ENABLE_FAST_INSTALL' => 1,
|
||||||
|
'gltests_LIBSOURCES' => 1,
|
||||||
|
'gl_FUNC_STRNLEN' => 1,
|
||||||
|
'AC_LIBTOOL_FC' => 1,
|
||||||
|
'LTDL_CONVENIENCE' => 1,
|
||||||
|
'gltests_REPLACE_FUNCS' => 1,
|
||||||
|
'_AM_SET_OPTION' => 1,
|
||||||
|
'AC_LTDL_PREOPEN' => 1,
|
||||||
|
'gl_HEADER_STRING_H_DEFAULTS' => 1,
|
||||||
|
'_LT_LINKER_BOILERPLATE' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
||||||
|
'gl_PREREQ_ARGZ' => 1,
|
||||||
|
'gl_STDLIB_MODULE_INDICATOR' => 1,
|
||||||
|
'gl_HEADER_STRING_H' => 1,
|
||||||
|
'AM_STDBOOL_H' => 1,
|
||||||
|
'gl_LIB' => 1,
|
||||||
|
'gl_STDBOOL_H' => 1,
|
||||||
|
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
|
'gl_COMMON_BODY' => 1,
|
||||||
|
'LT_SYS_MODULE_EXT' => 1,
|
||||||
|
'LT_PROG_RC' => 1,
|
||||||
|
'gl_PREREQ_ERROR' => 1,
|
||||||
|
'AC_DEFUN_ONCE' => 1,
|
||||||
|
'AC_C_RESTRICT' => 1,
|
||||||
|
'gl_EARLY' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ' => 1,
|
||||||
|
'gl_WITH_TESTS' => 1,
|
||||||
|
'gl_LIBTOOL' => 1,
|
||||||
|
'AC_LTDL_OBJDIR' => 1,
|
||||||
|
'gl_REPLACE_FUNCS' => 1,
|
||||||
|
'gl_FUNC_STRTOD' => 1,
|
||||||
|
'_LT_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'AC_LIBTOOL_RC' => 1,
|
||||||
|
'AC_DISABLE_FAST_INSTALL' => 1,
|
||||||
|
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
||||||
|
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
||||||
|
'gl_PO_DOMAIN' => 1,
|
||||||
|
'include' => 1,
|
||||||
|
'LT_AC_PROG_SED' => 1,
|
||||||
|
'AM_ENABLE_SHARED' => 1,
|
||||||
|
'LTDL_INSTALLABLE' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'AM_POSTPROCESS_PO_MAKEFILE' => 1,
|
||||||
|
'AC_ENABLE_SHARED' => 1,
|
||||||
|
'gl_DOC_BASE' => 1,
|
||||||
|
'gl_HEADER_ERRNO_H_BODY' => 1,
|
||||||
|
'AC_ENABLE_STATIC' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
||||||
|
'_LT_AC_TAGVAR' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
||||||
|
'AM_CONDITIONAL' => 1,
|
||||||
|
'LT_LIB_DLLOAD' => 1,
|
||||||
|
'gl_INIT' => 1,
|
||||||
|
'LTDL_INIT' => 1,
|
||||||
|
'LTVERSION_VERSION' => 1,
|
||||||
|
'gl_VC_FILES' => 1,
|
||||||
|
'AM_PROG_INSTALL_SH' => 1,
|
||||||
|
'gl_PREREQ_STRNDUP' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'AC_PROG_EGREP' => 1,
|
||||||
|
'gl_LGPL' => 1,
|
||||||
|
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
||||||
|
'AC_PATH_MAGIC' => 1,
|
||||||
|
'AC_LTDL_SYSSEARCHPATH' => 1,
|
||||||
|
'AM_MAKE_INCLUDE' => 1,
|
||||||
|
'LT_CMD_MAX_LEN' => 1,
|
||||||
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
|
'AM_PO_SUBDIRS' => 1,
|
||||||
|
'm4_pattern_forbid' => 1,
|
||||||
|
'_LT_LINKER_OPTION' => 1,
|
||||||
|
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
||||||
|
'AC_DISABLE_SHARED' => 1,
|
||||||
|
'gl_AVOID' => 1,
|
||||||
|
'_LT_COMPILER_BOILERPLATE' => 1,
|
||||||
|
'AC_LIBTOOL_WIN32_DLL' => 1,
|
||||||
|
'AC_LIBTOOL_SETUP' => 1,
|
||||||
|
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
||||||
|
'AC_LTDL_DLSYM_USCORE' => 1,
|
||||||
|
'gl_MODULES' => 1,
|
||||||
|
'LT_LANG' => 1,
|
||||||
|
'AM_MISSING_HAS_RUN' => 1,
|
||||||
|
'LT_SYS_DLSEARCH_PATH' => 1,
|
||||||
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
|
'gl_MACRO_PREFIX' => 1,
|
||||||
|
'LT_OUTPUT' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
||||||
|
'gl_CHECK_NEXT_HEADERS' => 1,
|
||||||
|
'AM_NLS' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
||||||
|
'gl_FUNC_STRERROR' => 1,
|
||||||
|
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
||||||
|
'AC_WITH_LTDL' => 1,
|
||||||
|
'gl_FILE_LIST' => 1,
|
||||||
|
'AC_LIBTOOL_CXX' => 1,
|
||||||
|
'LT_AC_PROG_RC' => 1,
|
||||||
|
'LT_INIT' => 1,
|
||||||
|
'gl_USE_SYSTEM_EXTENSIONS' => 1,
|
||||||
|
'LT_SYS_DLOPEN_SELF' => 1,
|
||||||
|
'LT_AC_PROG_GCJ' => 1,
|
||||||
|
'AM_DISABLE_STATIC' => 1,
|
||||||
|
'AM_DEP_TRACK' => 1,
|
||||||
|
'_AC_PROG_LIBTOOL' => 1,
|
||||||
|
'AC_COMPUTE_INT' => 1,
|
||||||
|
'_AM_IF_OPTION' => 1,
|
||||||
|
'AC_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'AC_LIBTOOL_F77' => 1,
|
||||||
|
'm4_pattern_allow' => 1,
|
||||||
|
'AM_PATH_PROG_WITH_TEST' => 1,
|
||||||
|
'gl_HEADER_STRING_H_BODY' => 1,
|
||||||
|
'AM_SET_LEADING_DOT' => 1,
|
||||||
|
'gl_UNISTD_H_DEFAULTS' => 1,
|
||||||
|
'LT_AC_PROG_EGREP' => 1,
|
||||||
|
'_AM_DEPENDENCIES' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
||||||
|
'LTOPTIONS_VERSION' => 1,
|
||||||
|
'_LT_AC_SYS_COMPILER' => 1,
|
||||||
|
'AM_PROG_NM' => 1,
|
||||||
|
'gl_PREREQ_STRNLEN' => 1,
|
||||||
|
'gl_STDLIB_H' => 1,
|
||||||
|
'AC_LIBLTDL_CONVENIENCE' => 1,
|
||||||
|
'gl_M4_BASE' => 1,
|
||||||
|
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
||||||
|
'AC_LIBLTDL_INSTALLABLE' => 1,
|
||||||
|
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AC_LTDL_ENABLE_INSTALL' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
||||||
|
'LT_PROG_GCJ' => 1,
|
||||||
|
'gl_STRING_MODULE_INDICATOR' => 1,
|
||||||
|
'gl_PREREQ_STRERROR' => 1,
|
||||||
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
|
'AC_PROG_MKDIR_P' => 1,
|
||||||
|
'AC_DISABLE_STATIC' => 1,
|
||||||
|
'gl_REPLACE_ERRNO_VALUE' => 1,
|
||||||
|
'gl_LOCAL_DIR' => 1,
|
||||||
|
'LT_PATH_NM' => 1,
|
||||||
|
'AC_LTDL_SHLIBEXT' => 1,
|
||||||
|
'_LT_AC_LOCK' => 1,
|
||||||
|
'_LT_AC_LANG_RC_CONFIG' => 1,
|
||||||
|
'gl_COMMON' => 1,
|
||||||
|
'gl_MODULE_INDICATOR' => 1,
|
||||||
|
'gl_TESTS_BASE' => 1,
|
||||||
|
'AC_HEADER_STDBOOL' => 1,
|
||||||
|
'LT_SYS_MODULE_PATH' => 1,
|
||||||
|
'gl_UNISTD_H' => 1,
|
||||||
|
'LT_WITH_LTDL' => 1,
|
||||||
|
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
||||||
|
'AC_LTDL_SHLIBPATH' => 1,
|
||||||
|
'gl_LIBSOURCES' => 1,
|
||||||
|
'gl_STDLIB_H_DEFAULTS' => 1,
|
||||||
|
'gltests_LIBOBJ' => 1,
|
||||||
|
'AM_AUX_DIR_EXPAND' => 1,
|
||||||
|
'gl_SOURCE_BASE' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
||||||
|
'_LT_AC_LANG_F77_CONFIG' => 1,
|
||||||
|
'_AM_SET_OPTIONS' => 1,
|
||||||
|
'_LT_COMPILER_OPTION' => 1,
|
||||||
|
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'AM_RUN_LOG' => 1,
|
||||||
|
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
||||||
|
'AC_LIBTOOL_PICMODE' => 1,
|
||||||
|
'gl_MAKEFILE_NAME' => 1,
|
||||||
|
'LT_PATH_LD' => 1,
|
||||||
|
'AC_CHECK_LIBM' => 1,
|
||||||
|
'ACX_PTHREAD' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
||||||
|
'_AM_MANGLE_OPTION' => 1,
|
||||||
|
'AM_XGETTEXT_OPTION' => 1,
|
||||||
|
'AC_LTDL_SYMBOL_USCORE' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
||||||
|
'AM_SET_DEPDIR' => 1,
|
||||||
|
'_LT_CC_BASENAME' => 1,
|
||||||
|
'_LT_LIBOBJ' => 1
|
||||||
|
}
|
||||||
|
], 'Autom4te::Request' )
|
||||||
|
);
|
||||||
|
|
||||||
4393
autom4te.cache/traces.0
Normal file
4393
autom4te.cache/traces.0
Normal file
File diff suppressed because it is too large
Load Diff
1473
autom4te.cache/traces.1
Normal file
1473
autom4te.cache/traces.1
Normal file
File diff suppressed because it is too large
Load Diff
4393
autom4te.cache/traces.2
Normal file
4393
autom4te.cache/traces.2
Normal file
File diff suppressed because it is too large
Load Diff
139
bootstrap
Executable file
139
bootstrap
Executable file
@@ -0,0 +1,139 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2006 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
# <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
# This file is part of the Anti-Lamenessing Engine.
|
||||||
|
#
|
||||||
|
# The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
###
|
||||||
|
### 'bootstrap' generates build files for distribution.
|
||||||
|
###
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check for the existence of a configure script.
|
||||||
|
#
|
||||||
|
|
||||||
|
if test -e configure && test "x$1" != "x-r"; then
|
||||||
|
echo
|
||||||
|
echo "To install:"
|
||||||
|
echo "1) Run './configure'."
|
||||||
|
echo "2) Run 'make'."
|
||||||
|
echo "3) Run 'make install'."
|
||||||
|
echo ""
|
||||||
|
echo "* To regenerate configure, run '$0 -r'"
|
||||||
|
echo
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! which gnulib-tool &> /dev/null; then
|
||||||
|
echo "*** Cannot find 'gnulib-tool'. ***"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! which ln &> /dev/null; then
|
||||||
|
echo "*** Cannot find 'ln'. ***"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! which automake &> /dev/null; then
|
||||||
|
echo "*** Cannot find 'automake'. ***"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! which autoreconf &> /dev/null; then
|
||||||
|
echo "*** Cannot find 'autoreconf'. ***"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! test -e /usr/share/aclocal/acx_pthread.m4; then
|
||||||
|
echo "*** Cannot find file '/usr/share/aclocal/acx_pthread.m4'. ***"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add autoconf archive files.
|
||||||
|
#
|
||||||
|
|
||||||
|
mkdir -p m4
|
||||||
|
cp /usr/share/aclocal/acx_pthread.m4 m4/.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Make documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
chmod a+x doc/make-changelog
|
||||||
|
chmod a+x doc/make-infos
|
||||||
|
make -C doc ../TODO ../README ../ChangeLog ../NEWS
|
||||||
|
a2x -f manpage doc/man/ale.1.txt
|
||||||
|
|
||||||
|
#
|
||||||
|
# Import GNU extension strndup
|
||||||
|
#
|
||||||
|
|
||||||
|
gnulib-tool --libtool --import strndup error strtod
|
||||||
|
|
||||||
|
#
|
||||||
|
# Placeholders for automake-mandated files.
|
||||||
|
#
|
||||||
|
|
||||||
|
# touch NEWS
|
||||||
|
# touch AUTHORS
|
||||||
|
|
||||||
|
#
|
||||||
|
# Use the automake-mandated spelling for the changelog.
|
||||||
|
#
|
||||||
|
|
||||||
|
# ln -s Changelog ChangeLog
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run autotools' bootstrap script, adding things that automake thinks are
|
||||||
|
# missing, among other things (--install).
|
||||||
|
#
|
||||||
|
|
||||||
|
autoreconf --install
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run automake again, with the --foreign option.
|
||||||
|
#
|
||||||
|
|
||||||
|
# echo ""
|
||||||
|
# echo "Rerunning automake with --foreign flag."
|
||||||
|
# automake --foreign
|
||||||
|
|
||||||
|
#
|
||||||
|
# Make wrapper script executable
|
||||||
|
#
|
||||||
|
|
||||||
|
chmod a+x ./ale
|
||||||
|
|
||||||
|
#
|
||||||
|
# Indicate that we're done.
|
||||||
|
#
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Done."
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tell the user what to do next.
|
||||||
|
#
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "To install:"
|
||||||
|
echo "1) Run './configure'."
|
||||||
|
echo "2) Run 'make'."
|
||||||
|
echo "3) Run 'make install'."
|
||||||
|
|
||||||
53
bugs/issue-8f36cd6c86489cdaa7349beb2277e947a5d0558a.yaml
Normal file
53
bugs/issue-8f36cd6c86489cdaa7349beb2277e947a5d0558a.yaml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
--- !ditz.rubyforge.org,2008-03-06/issue
|
||||||
|
title: Reduce memory expense of multi-alignment (e.g., by discarding maps between passes, by reducing typical kept size, or by reducing map element size)
|
||||||
|
desc: ""
|
||||||
|
type: :task
|
||||||
|
component: ale
|
||||||
|
release:
|
||||||
|
reporter: David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
status: :unstarted
|
||||||
|
disposition:
|
||||||
|
creation_time: 2009-03-28 22:53:12.231388 Z
|
||||||
|
references: []
|
||||||
|
|
||||||
|
id: 8f36cd6c86489cdaa7349beb2277e947a5d0558a
|
||||||
|
log_events:
|
||||||
|
- - 2009-03-28 22:53:12.832156 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- created
|
||||||
|
- ""
|
||||||
|
- - 2009-03-28 22:53:46.644669 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- commented
|
||||||
|
- One approach that may be worth investigating is compression (e.g., by PNG).
|
||||||
|
- - 2009-03-28 22:56:07.802488 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- commented
|
||||||
|
- |-
|
||||||
|
Related to assertion failiure bug reported by Jari Juslin in message
|
||||||
|
[ale] Processing color negative scans with ALE (was: Help with aligning images)
|
||||||
|
- - 2009-03-29 08:22:52.909320 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- commented
|
||||||
|
- |-
|
||||||
|
Patch sent to list, adapted for the current branch:
|
||||||
|
|
||||||
|
--- a/d2/trans_multi.h
|
||||||
|
+++ b/d2/trans_multi.h
|
||||||
|
@@ -55,7 +55,7 @@ private:
|
||||||
|
static ale_pos _multi_decomp;
|
||||||
|
static ale_real _multi_improvement;
|
||||||
|
|
||||||
|
- typedef unsigned int index_t;
|
||||||
|
+ typedef unsigned short index_t;
|
||||||
|
|
||||||
|
std::vector<trans_single> trans_stack;
|
||||||
|
std::vector<multi_coordinate> coord_stack;
|
||||||
|
- - 2009-03-29 08:34:03.662057 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- commented
|
||||||
|
- |-
|
||||||
|
One approach to solving this would be restricting the candidate set size
|
||||||
|
for each pixel in the map, so that, e.g., only regions neighboring a local
|
||||||
|
region (allowing any level of decomposition) can be mapped.
|
||||||
|
git_branch:
|
||||||
24
bugs/issue-d279fa0d83212136ed7fd67e1ea69ef663707282.yaml
Normal file
24
bugs/issue-d279fa0d83212136ed7fd67e1ea69ef663707282.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
--- !ditz.rubyforge.org,2008-03-06/issue
|
||||||
|
title: Remove superfluous header 'Overview' from introductory sections of asciidoc documentation.
|
||||||
|
desc: ""
|
||||||
|
type: :task
|
||||||
|
component: ale
|
||||||
|
release:
|
||||||
|
reporter: David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
status: :closed
|
||||||
|
disposition: :fixed
|
||||||
|
creation_time: 2009-03-28 08:37:16.047379 Z
|
||||||
|
references: []
|
||||||
|
|
||||||
|
id: d279fa0d83212136ed7fd67e1ea69ef663707282
|
||||||
|
log_events:
|
||||||
|
- - 2009-03-28 08:37:16.512711 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- created
|
||||||
|
- ""
|
||||||
|
- - 2009-03-28 09:02:48.959063 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- closed with disposition fixed
|
||||||
|
- |-
|
||||||
|
'Overview' section should probably also be removed from the user guide, but this isn't asciidoc,
|
||||||
|
so closing.
|
||||||
38
bugs/issue-ec7a9aea4ad735dc6d5e00fe93335cc4b93f7801.yaml
Normal file
38
bugs/issue-ec7a9aea4ad735dc6d5e00fe93335cc4b93f7801.yaml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
--- !ditz.rubyforge.org,2008-03-06/issue
|
||||||
|
title: Serious memory leak affecting all current versions.
|
||||||
|
desc: |-
|
||||||
|
Jari Juslin reports in message '[ale] Processing color negative scans with ALE'
|
||||||
|
an apparent out-of-memory condition affecting 0.9 branch with --ips 0. Testing
|
||||||
|
with 0.8.11.1 indicates that the 0.8 branch is affected also. In particular,
|
||||||
|
the following commands result in memory increase without bounds (e.g., visible
|
||||||
|
in top or atop) throughout execution, which is unexpected for this
|
||||||
|
configuration:
|
||||||
|
|
||||||
|
$ convert -size 1000x1000 xc:gray gray.png
|
||||||
|
$ ale-bin --cache 0 --no-inc --dchain zero --achain zero --perturb-upper=0 --ips 0 `for i in \`seq 1 1000\`; do echo -n "gray.png "; done` null:
|
||||||
|
|
||||||
|
(Ignore the segfault following execution; this is a consequence of the 'zero'
|
||||||
|
filter.)
|
||||||
|
|
||||||
|
Running 'valgrind' on an input set of smaller dimensions and frame count reveals
|
||||||
|
a number of memory leaks (reachable and unreachable) which have now been fixed.
|
||||||
|
type: :bugfix
|
||||||
|
component: ale
|
||||||
|
release:
|
||||||
|
reporter: David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
status: :closed
|
||||||
|
disposition: :fixed
|
||||||
|
creation_time: 2009-03-30 18:46:16.735784 Z
|
||||||
|
references: []
|
||||||
|
|
||||||
|
id: ec7a9aea4ad735dc6d5e00fe93335cc4b93f7801
|
||||||
|
log_events:
|
||||||
|
- - 2009-03-30 18:46:22.694825 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- created
|
||||||
|
- ""
|
||||||
|
- - 2009-03-30 18:47:15.401088 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- closed with disposition fixed
|
||||||
|
- ""
|
||||||
|
git_branch:
|
||||||
23
bugs/issue-fe69b6ceefef3805e29190e1040f9278be84b1f8.yaml
Normal file
23
bugs/issue-fe69b6ceefef3805e29190e1040f9278be84b1f8.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
--- !ditz.rubyforge.org,2008-03-06/issue
|
||||||
|
title: Investigate recent ImageMagick build procedures, and consider updating build accordingly.
|
||||||
|
desc: ""
|
||||||
|
type: :task
|
||||||
|
component: ale
|
||||||
|
release:
|
||||||
|
reporter: David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
status: :closed
|
||||||
|
disposition: :fixed
|
||||||
|
creation_time: 2009-03-30 19:52:00.861315 Z
|
||||||
|
references: []
|
||||||
|
|
||||||
|
id: fe69b6ceefef3805e29190e1040f9278be84b1f8
|
||||||
|
log_events:
|
||||||
|
- - 2009-03-30 19:52:02.141451 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- created
|
||||||
|
- ""
|
||||||
|
- - 2009-03-31 12:23:33.521227 Z
|
||||||
|
- David Hilvert <dhilvert@auricle.dyndns.org>
|
||||||
|
- closed with disposition fixed
|
||||||
|
- Current configure seems to be OK for ImageMagick 6.4.5 2009-01-22 Q16 (shipped with Ubuntu).
|
||||||
|
git_branch:
|
||||||
8
bugs/project.yaml
Normal file
8
bugs/project.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
--- !ditz.rubyforge.org,2008-03-06/project
|
||||||
|
name: ale
|
||||||
|
version: "0.5"
|
||||||
|
components:
|
||||||
|
- !ditz.rubyforge.org,2008-03-06/component
|
||||||
|
name: ale
|
||||||
|
releases: []
|
||||||
|
|
||||||
1526
config.guess
vendored
Executable file
1526
config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
308
config.h.in
Normal file
308
config.h.in
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
/* config.h.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `strerror', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#undef HAVE_DECL_STRERROR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#undef HAVE_DECL_STRERROR_R
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `strndup', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#undef HAVE_DECL_STRNDUP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#undef HAVE_DECL_STRNLEN
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
#undef HAVE_DLFCN_H
|
||||||
|
|
||||||
|
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
||||||
|
#undef HAVE_DOPRNT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <errno.h> header file. */
|
||||||
|
#undef HAVE_ERRNO_H
|
||||||
|
|
||||||
|
/* execlp() function is available. */
|
||||||
|
#undef HAVE_EXECLP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `floor' function. */
|
||||||
|
#undef HAVE_FLOOR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fork' function. */
|
||||||
|
#undef HAVE_FORK
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
|
#undef HAVE_GETTIMEOFDAY
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* ioctl() function is available. */
|
||||||
|
#undef HAVE_IOCTL
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `m' library (-lm). */
|
||||||
|
#undef HAVE_LIBM
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <limits.h> header file. */
|
||||||
|
#undef HAVE_LIMITS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memset' function. */
|
||||||
|
#undef HAVE_MEMSET
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `nanosleep' function. */
|
||||||
|
#undef HAVE_NANOSLEEP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `nrand48' function. */
|
||||||
|
#undef HAVE_NRAND48
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pow' function. */
|
||||||
|
#undef HAVE_POW
|
||||||
|
|
||||||
|
/* Define if you have POSIX threads libraries and header files. */
|
||||||
|
#undef HAVE_PTHREAD
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `rand_r' function. */
|
||||||
|
#undef HAVE_RAND_R
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `select' function. */
|
||||||
|
#undef HAVE_SELECT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `sqrt' function. */
|
||||||
|
#undef HAVE_SQRT
|
||||||
|
|
||||||
|
/* Define to 1 if stdbool.h conforms to C99. */
|
||||||
|
#undef HAVE_STDBOOL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strchr' function. */
|
||||||
|
#undef HAVE_STRCHR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strcspn' function. */
|
||||||
|
#undef HAVE_STRCSPN
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strdup' function. */
|
||||||
|
#undef HAVE_STRDUP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strerror_r' function. */
|
||||||
|
#undef HAVE_STRERROR_R
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strndup' function. */
|
||||||
|
#undef HAVE_STRNDUP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strspn' function. */
|
||||||
|
#undef HAVE_STRSPN
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtol' function. */
|
||||||
|
#undef HAVE_STRTOL
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `struct random_data'. */
|
||||||
|
#undef HAVE_STRUCT_RANDOM_DATA
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||||
|
#undef HAVE_SYS_IOCTL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||||
|
#undef HAVE_SYS_SELECT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||||
|
#undef HAVE_SYS_SOCKET_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#undef HAVE_SYS_TIME_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||||
|
#undef HAVE_SYS_WAIT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <time.h> header file. */
|
||||||
|
#undef HAVE_TIME_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `vfork' function. */
|
||||||
|
#undef HAVE_VFORK
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <vfork.h> header file. */
|
||||||
|
#undef HAVE_VFORK_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `vprintf' function. */
|
||||||
|
#undef HAVE_VPRINTF
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <winsock2.h> header file. */
|
||||||
|
#undef HAVE_WINSOCK2_H
|
||||||
|
|
||||||
|
/* Define to 1 if `fork' works. */
|
||||||
|
#undef HAVE_WORKING_FORK
|
||||||
|
|
||||||
|
/* Define to 1 if `vfork' works. */
|
||||||
|
#undef HAVE_WORKING_VFORK
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `_Bool'. */
|
||||||
|
#undef HAVE__BOOL
|
||||||
|
|
||||||
|
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||||
|
*/
|
||||||
|
#undef LT_OBJDIR
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||||
|
your system. */
|
||||||
|
#undef PTHREAD_CREATE_JOINABLE
|
||||||
|
|
||||||
|
/* Define this to 1 if strerror is broken. */
|
||||||
|
#undef REPLACE_STRERROR
|
||||||
|
|
||||||
|
/* Define to the type of arg 1 for `select'. */
|
||||||
|
#undef SELECT_TYPE_ARG1
|
||||||
|
|
||||||
|
/* Define to the type of args 2, 3 and 4 for `select'. */
|
||||||
|
#undef SELECT_TYPE_ARG234
|
||||||
|
|
||||||
|
/* Define to the type of arg 5 for `select'. */
|
||||||
|
#undef SELECT_TYPE_ARG5
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
|
/* Define to 1 if strerror_r returns char *. */
|
||||||
|
#undef STRERROR_R_CHAR_P
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#undef VERSION
|
||||||
|
|
||||||
|
/* Define to 1 if on MINIX. */
|
||||||
|
#undef _MINIX
|
||||||
|
|
||||||
|
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||||
|
this defined. */
|
||||||
|
#undef _POSIX_1_SOURCE
|
||||||
|
|
||||||
|
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
|
||||||
|
/* Define to 500 only on HP-UX. */
|
||||||
|
#undef _XOPEN_SOURCE
|
||||||
|
|
||||||
|
/* Enable extensions on AIX 3, Interix. */
|
||||||
|
#ifndef _ALL_SOURCE
|
||||||
|
# undef _ALL_SOURCE
|
||||||
|
#endif
|
||||||
|
/* Enable GNU extensions on systems that have them. */
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
# undef _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
/* Enable threading extensions on Solaris. */
|
||||||
|
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||||
|
# undef _POSIX_PTHREAD_SEMANTICS
|
||||||
|
#endif
|
||||||
|
/* Enable extensions on HP NonStop. */
|
||||||
|
#ifndef _TANDEM_SOURCE
|
||||||
|
# undef _TANDEM_SOURCE
|
||||||
|
#endif
|
||||||
|
/* Enable general extensions on Solaris. */
|
||||||
|
#ifndef __EXTENSIONS__
|
||||||
|
# undef __EXTENSIONS__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define to empty if `const' does not conform to ANSI C. */
|
||||||
|
#undef const
|
||||||
|
|
||||||
|
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||||
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#undef inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to the type of a signed integer type of width exactly 16 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
#undef int16_t
|
||||||
|
|
||||||
|
/* Work around a bug in Apple GCC 4.0.1 build 5465: In C99 mode, it supports
|
||||||
|
the ISO C 99 semantics of 'extern inline' (unlike the GNU C semantics of
|
||||||
|
earlier versions), but does not display it by setting __GNUC_STDC_INLINE__.
|
||||||
|
__APPLE__ && __MACH__ test for MacOS X.
|
||||||
|
__APPLE_CC__ tests for the Apple compiler and its version.
|
||||||
|
__STDC_VERSION__ tests for the C99 mode. */
|
||||||
|
#if defined __APPLE__ && defined __MACH__ && __APPLE_CC__ >= 5465 && !defined __cplusplus && __STDC_VERSION__ >= 199901L && !defined __GNUC_STDC_INLINE__
|
||||||
|
# define __GNUC_STDC_INLINE__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
|
#undef pid_t
|
||||||
|
|
||||||
|
/* Define to the equivalent of the C99 'restrict' keyword, or to
|
||||||
|
nothing if this is not supported. Do not define if restrict is
|
||||||
|
supported directly. */
|
||||||
|
#undef restrict
|
||||||
|
/* Work around a bug in Sun C++: it does not support _Restrict, even
|
||||||
|
though the corresponding Sun C compiler does, which causes
|
||||||
|
"#define restrict _Restrict" in the previous line. Perhaps some future
|
||||||
|
version of Sun C++ will work with _Restrict; if so, it'll probably
|
||||||
|
define __RESTRICT, just as Sun C does. */
|
||||||
|
#if defined __SUNPRO_CC && !defined __RESTRICT
|
||||||
|
# define _Restrict
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||||
|
#undef size_t
|
||||||
|
|
||||||
|
/* Define to rpl_strnlen if the replacement function should be used. */
|
||||||
|
#undef strnlen
|
||||||
|
|
||||||
|
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
#undef uint16_t
|
||||||
|
|
||||||
|
/* Define as a marker that can be attached to function parameter declarations
|
||||||
|
for parameters that are not used. This helps to reduce warnings, such as
|
||||||
|
from GCC -Wunused-parameter. */
|
||||||
|
#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
|
||||||
|
# define _UNUSED_PARAMETER_ __attribute__ ((__unused__))
|
||||||
|
#else
|
||||||
|
# define _UNUSED_PARAMETER_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define as `fork' if `vfork' does not work. */
|
||||||
|
#undef vfork
|
||||||
1658
config.sub
vendored
Executable file
1658
config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
375
configure.in
Normal file
375
configure.in
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
# -*- Autoconf -*-
|
||||||
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
|
# Copyright 2006 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
# <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
# This file is part of the Anti-Lamenessing Engine.
|
||||||
|
#
|
||||||
|
# The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
# Parts of this file were automatically generated by the GNU project's
|
||||||
|
# configuration generator 'autoscan', part of the 'autoconf' package from the
|
||||||
|
# 'autotools' family of build and installation tools.
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Preliminaries
|
||||||
|
#
|
||||||
|
|
||||||
|
AC_PREREQ(2.60)
|
||||||
|
AC_INIT(ALE, translit(m4_include(VERSION),'
|
||||||
|
'), ale@ventricle.dyndns.org)
|
||||||
|
AC_CONFIG_SRCDIR([ale_accum.h])
|
||||||
|
AC_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE
|
||||||
|
|
||||||
|
# Checks for programs.
|
||||||
|
AC_PROG_CXX
|
||||||
|
AC_PROG_CC
|
||||||
|
|
||||||
|
# The strtod check breaks cross-compilation, so disable it.
|
||||||
|
AC_DEFUN([AC_FUNC_STRTOD],[])
|
||||||
|
|
||||||
|
#GNULib startup
|
||||||
|
gl_EARLY
|
||||||
|
|
||||||
|
# Libtool
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
|
# For gnulib.
|
||||||
|
#gl_SOURCE_BASE(gl)
|
||||||
|
#gl_M4_BASE(m4)
|
||||||
|
#gl_LIB(lib)
|
||||||
|
gl_MODULES(strndup)
|
||||||
|
gl_INIT
|
||||||
|
|
||||||
|
# Checks for libraries.
|
||||||
|
# FIXME: Replace `main' with a function in `-lm':
|
||||||
|
AC_CHECK_LIB([m], [main])
|
||||||
|
|
||||||
|
# Checks for header files.
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_HEADER_SYS_WAIT
|
||||||
|
AC_CHECK_HEADERS([limits.h stdint.h stdlib.h string.h sys/ioctl.h unistd.h time.h sys/time.h])
|
||||||
|
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_C_CONST
|
||||||
|
AC_C_INLINE
|
||||||
|
AC_TYPE_INT16_T
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_TYPE_UINT16_T
|
||||||
|
|
||||||
|
# Checks for library functions. (Commented calls cause problems for cross-compilation.)
|
||||||
|
AC_FUNC_ERROR_AT_LINE
|
||||||
|
AC_FUNC_FORK
|
||||||
|
AC_PROG_GCC_TRADITIONAL
|
||||||
|
# AC_FUNC_MALLOC
|
||||||
|
# AC_FUNC_REALLOC
|
||||||
|
AC_FUNC_SELECT_ARGTYPES
|
||||||
|
AC_FUNC_STRTOD
|
||||||
|
AC_FUNC_VPRINTF
|
||||||
|
AC_CHECK_FUNCS([floor memset pow select sqrt strchr strcspn strdup strndup strspn strtol nrand48 rand_r gettimeofday nanosleep])
|
||||||
|
|
||||||
|
if test x$enable_threads != xno; then
|
||||||
|
|
||||||
|
# Check for POSIX threads.
|
||||||
|
ACX_PTHREAD()
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine whether multithreading should be used.
|
||||||
|
AC_ARG_ENABLE(threads, [ --enable-threads enable multithreading: auto, no, yes (default=auto)])
|
||||||
|
if test x$enable_threads != xno \
|
||||||
|
&& test x$acx_pthread_ok = xyes; then
|
||||||
|
PTHREAD_CFLAGS="$PTHREAD_CFLAGS -DUSE_PTHREAD=1"
|
||||||
|
|
||||||
|
#
|
||||||
|
# XXX: This is probably wrong.
|
||||||
|
#
|
||||||
|
|
||||||
|
if test x$PTHREAD_CXX = x; then
|
||||||
|
PTHREAD_CXX="$CXX"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# CC replacement logic from ImageMagick's configuration process
|
||||||
|
#
|
||||||
|
|
||||||
|
if test "$CC" != "$PTHREAD_CC"; then
|
||||||
|
AC_MSG_WARN([Replacing compiler $CC with compiler $PTHREAD_CC to support pthreads.])
|
||||||
|
CC="$PTHREAD_CC"
|
||||||
|
fi
|
||||||
|
if test "$CXX" != "$PTHREAD_CXX"; then
|
||||||
|
AC_MSG_WARN([Replacing compiler $CXX with compiler $PTHREAD_CXX to support pthreads.])
|
||||||
|
CXX="$PTHREAD_CXX"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$enable_threads = xyes \
|
||||||
|
&& test x$acx_pthread_ok = xno; then
|
||||||
|
AC_MSG_ERROR([Multithreaded build requested (--enable-threads=yes), but no usable library was found.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Determine whether assertions should be enabled.
|
||||||
|
AC_ARG_ENABLE(assertions, [ --enable-assertions check runtime assertions (default=yes)])
|
||||||
|
if test x$enable_assertions = xno; then
|
||||||
|
ASSERT_FLAGS="-DNDEBUG"
|
||||||
|
else
|
||||||
|
ASSERT_FLAGS="-DDEBUG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine whether ImageMagick should be linked
|
||||||
|
AC_ARG_WITH(imagemagick, [ --with-imagemagick ImageMagick file handling: auto,no,yes (default=auto)])
|
||||||
|
if test x$with_imagemagick != xno; then
|
||||||
|
|
||||||
|
# AC_CHECK_TOOL is somewhat broken for cross-compilation in
|
||||||
|
# some versions of autoconf, so use a conditional instead.
|
||||||
|
|
||||||
|
if test x$host = x$build \
|
||||||
|
|| test x$host = x; then
|
||||||
|
AC_CHECK_TOOL(MAGICK_CONFIG, Magick-config, no)
|
||||||
|
else
|
||||||
|
AC_CHECK_PROG(MAGICK_CONFIG, ${ac_tool_prefix}Magick-config, ${ac_tool_prefix}Magick-config, no)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$MAGICK_CONFIG != xno; then
|
||||||
|
|
||||||
|
# Bugs have been encountered in certain versions of ImageMagick
|
||||||
|
# older than 6.0.6. Until a test is written to check for these
|
||||||
|
# bugs, check the version number instead.
|
||||||
|
#
|
||||||
|
# Since GraphicsMagick uses different version numbering, accept
|
||||||
|
# any version number from a GraphicsMagick installation.
|
||||||
|
|
||||||
|
IMAGEMAGICK_VERSION=`Magick-config --version`
|
||||||
|
IMAGEMAGICK_VERSION_A=`echo $IMAGEMAGICK_VERSION | cut -f 1 -d '.'`
|
||||||
|
IMAGEMAGICK_VERSION_B=`echo $IMAGEMAGICK_VERSION | cut -f 2 -d '.'`
|
||||||
|
IMAGEMAGICK_VERSION_C=`echo $IMAGEMAGICK_VERSION | cut -f 3 -d '.'`
|
||||||
|
|
||||||
|
if test -x `which GraphicsMagick-config` \
|
||||||
|
|| test $IMAGEMAGICK_VERSION_A -gt 6 \
|
||||||
|
|| ( test $IMAGEMAGICK_VERSION_A -eq 6 \
|
||||||
|
&& test $IMAGEMAGICK_VERSION_B -gt 0 ) \
|
||||||
|
|| ( test $IMAGEMAGICK_VERSION_A -eq 6 \
|
||||||
|
&& test $IMAGEMAGICK_VERSION_B -eq 0 \
|
||||||
|
&& test $IMAGEMAGICK_VERSION_C -ge 6 ); then
|
||||||
|
IMAGEMAGICK_CFLAGS=`$MAGICK_CONFIG --cflags`
|
||||||
|
IMAGEMAGICK_CPPFLAGS="`$MAGICK_CONFIG --cppflags` -DUSE_MAGICK"
|
||||||
|
IMAGEMAGICK_LDFLAGS=`$MAGICK_CONFIG --ldflags`
|
||||||
|
IMAGEMAGICK_LIBS=`$MAGICK_CONFIG --libs`
|
||||||
|
else
|
||||||
|
AC_MSG_WARN([not using ImageMagick older than 6.0.6 (found $IMAGEMAGICK_VERSION)])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
IMAGEMAGICK_CFLAGS=""
|
||||||
|
IMAGEMAGICK_CPPFLAGS=""
|
||||||
|
IMAGEMAGICK_LDFLAGS=""
|
||||||
|
IMAGEMAGICK_LIBS=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fatal error if user flag for ImageMagick could not be satisified
|
||||||
|
if test x$with_imagemagick = xyes \
|
||||||
|
&& test x$IMAGEMAGICK_CPPFLAGS = x; then
|
||||||
|
AC_MSG_ERROR([ImageMagick build requested (--enable-imagemagick=yes), but no suitable version was found.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine whether FFTW should be linked
|
||||||
|
AC_ARG_WITH(fftw3, [ --with-fftw3 FFTW3 fourier transforms: auto,no,yes (default=auto)])
|
||||||
|
if test x$with_fftw3 != xno; then
|
||||||
|
AC_CHECK_LIB([fftw3], [main], LIBS="-lfftw3 $LIBS" FFTW_CPPFLAGS="-DUSE_FFTW")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fatal error if user flag for FFTW could not be satisified
|
||||||
|
if test x$with_fftw3 = xyes \
|
||||||
|
&& test x$FFTW_CPPFLAGS = x; then
|
||||||
|
AC_MSG_ERROR([FFTW3 build requested (--enable-fftw3=yes), but no suitable version was found.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine the precision of colors that should be used
|
||||||
|
AC_ARG_WITH(colors, [ --with-colors=[TYPE] use TYPE colors: single,double,fixed32,fixed16 (default=single)])
|
||||||
|
if test x$with_colors = xsingle \
|
||||||
|
|| test x$with_colors = x; then
|
||||||
|
COLOR_CPPFLAGS="-DALE_COLORS=SINGLE"
|
||||||
|
elif test x$with_colors = xdouble; then
|
||||||
|
COLOR_CPPFLAGS="-DALE_COLORS=DOUBLE"
|
||||||
|
elif test x$with_colors = xfixed16; then
|
||||||
|
COLOR_CPPFLAGS="-DALE_COLORS=FIXED16"
|
||||||
|
elif test x$with_colors = xfixed32; then
|
||||||
|
COLOR_CPPFLAGS="-DALE_COLORS=FIXED32"
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR(option --with-colors=$with_colors is not currently supported)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine the precision of coordinates that should be used
|
||||||
|
AC_ARG_WITH(coords, [ --with-coords=[TYPE] use TYPE coords: single,double,fixed32,fixed16 (default=single)])
|
||||||
|
if test x$with_coords = xsingle \
|
||||||
|
|| test x$with_coords = x; then
|
||||||
|
COORD_CPPFLAGS="-DALE_COORDINATES=SINGLE"
|
||||||
|
elif test x$with_coords = xdouble; then
|
||||||
|
COORD_CPPFLAGS="-DALE_COORDINATES=DOUBLE"
|
||||||
|
elif test x$with_coords = xfixed16; then
|
||||||
|
COORD_CPPFLAGS="-DALE_COORDINATES=FIXED16"
|
||||||
|
elif test x$with_coords = xfixed32; then
|
||||||
|
COORD_CPPFLAGS="-DALE_COORDINATES=FIXED32"
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR(option --with-coords=$with_coords is not currently supported)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine whether optimizations should be used
|
||||||
|
AC_ARG_ENABLE(optimization, [ --enable-optimizations use optimization code (default=yes)])
|
||||||
|
if test x$enable_optimizations = xyes \
|
||||||
|
|| test x$enable_optimizations = x; then
|
||||||
|
OPTIMIZATION_CPPFLAGS="-DOPTIMIZATIONS=1"
|
||||||
|
elif test x$enable_optimizations = xno; then
|
||||||
|
OPTIMIZATION_CPPFLAGS="-DOPTIMIZATIONS=0"
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR(option --enable-optimizations=$enable_optimizations is not currently supported)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine whether hash maps should be used.
|
||||||
|
AC_ARG_WITH(hashmap, [ --with-hashmap=[TYPE] Use TYPE hash map: no,gnu,std (default=no)])
|
||||||
|
if test x$with_hashmap = xno \
|
||||||
|
|| test x$with_hashmap = x; then
|
||||||
|
STL_CPPFLAGS=""
|
||||||
|
elif test x$with_hashmap = xgnu; then
|
||||||
|
AC_CACHE_CHECK(whether GNU hash maps are available, ac_cv_gnu_hash,[
|
||||||
|
AC_LANG_SAVE
|
||||||
|
AC_LANG_CPLUSPLUS
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#include <ext/hash_map>
|
||||||
|
struct node_hash
|
||||||
|
{
|
||||||
|
size_t operator()(int n) const
|
||||||
|
{
|
||||||
|
return __gnu_cxx::hash<int>()(n);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
typedef __gnu_cxx::hash_map<int, int, node_hash> int_map_t;
|
||||||
|
],[
|
||||||
|
int_map_t foo;
|
||||||
|
], ac_cv_gnu_hash=yes, ac_cv_gnu_hash=no)
|
||||||
|
AC_LANG_RESTORE])
|
||||||
|
if test $ac_cv_gnu_hash = yes; then
|
||||||
|
STL_CPPFLAGS="-DHASH_MAP_GNU"
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR([option --with-hashmap=gnu specified, but this configuration fails.])
|
||||||
|
fi
|
||||||
|
elif test x$with_hashmap = xstd; then
|
||||||
|
AC_CACHE_CHECK(whether std hash maps are available, ac_cv_std_hash,[
|
||||||
|
AC_LANG_SAVE
|
||||||
|
AC_LANG_CPLUSPLUS
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#include <ext/hash_map>
|
||||||
|
typedef std::hash_map<int, int> int_map_t;
|
||||||
|
],[
|
||||||
|
int_map_t foo;
|
||||||
|
], ac_cv_std_hash=yes, ac_cv_std_hash=no)
|
||||||
|
AC_LANG_RESTORE])
|
||||||
|
if test $ac_cv_std_hash = yes; then
|
||||||
|
STL_CPPFLAGS="-DHASH_MAP_STD"
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR([option --with-hashmap=std specified, but this configuration fails.])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR(option --with-hashmap=$with_hashmap is not currently supported)
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Determine whether ioctl() should be used for determining window dimensions
|
||||||
|
AC_ARG_ENABLE(getsize, [ --enable-getsize get terminal size: auto,no,yes (default=auto)
|
||||||
|
(not doing this disables certain UI updates)])
|
||||||
|
if test x$enable_getsize != xno; then
|
||||||
|
|
||||||
|
# Check for Unix facilities.
|
||||||
|
AC_CHECK_HEADER(sys/ioctl.h, AC_DEFINE([HAVE_SYS_IOCTL_H]))
|
||||||
|
AC_CHECK_FUNC(ioctl, AC_DEFINE([HAVE_IOCTL], [], [ioctl() function is available.]))
|
||||||
|
AC_CHECK_DECL(TIOCGWINSZ, have_winsz=yes, have_winsz=no, [#include <sys/ioctl.h>])
|
||||||
|
|
||||||
|
if test x$ac_cv_header_sys_ioctl_h = xyes \
|
||||||
|
&& test x$ac_cv_func_ioctl = xyes \
|
||||||
|
&& test x$have_winsz = xyes; then
|
||||||
|
IOCTL_CPPFLAGS="-DUSE_IOCTL"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fatal error if IOCTL configuration could not be satisfied
|
||||||
|
if test x$enable_getsize = xyes \
|
||||||
|
&& test x$IOCTL_CPPFLAGS = x; then
|
||||||
|
if test x$ac_cv_header_sys_ioctl_h != xyes; then
|
||||||
|
AC_MSG_ERROR([ioctl() for window size requested (--enable-getsize=yes), but sys/ioctl.h was not found.])
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_func_ioctl != xyes; then
|
||||||
|
AC_MSG_ERROR([ioctl() for window size requested (--enable-getsize=yes), but ioctl() was not found.])
|
||||||
|
fi
|
||||||
|
if test x$have_winsz != xyes; then
|
||||||
|
AC_MSG_ERROR([ioctl() for window size requested (--enable-getsize=yes), but TIOCGWINSZ was not found.])
|
||||||
|
fi
|
||||||
|
AC_MSG_ERROR([ioctl() for window size requested (--enable-getsize=yes), but this configuration fails.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine whether the --wmx flag should be supported
|
||||||
|
AC_ARG_ENABLE(wmx, [ --enable-wmx Enable --wmx option: auto,no,yes (default=auto)
|
||||||
|
(this option requires execlp() and fork())])
|
||||||
|
if test x$enable_wmx != xno; then
|
||||||
|
|
||||||
|
# Check for Unix facilities.
|
||||||
|
AC_CHECK_HEADER(unistd.h, AC_DEFINE([HAVE_UNISTD_H]))
|
||||||
|
AC_CHECK_FUNC(execlp, AC_DEFINE([HAVE_EXECLP], [], [execlp() function is available.]))
|
||||||
|
|
||||||
|
if test x$ac_cv_func_fork_works = xyes \
|
||||||
|
&& test x$ac_cv_header_unistd_h = xyes \
|
||||||
|
&& test x$ac_cv_func_execlp = xyes; then
|
||||||
|
UNIX_CPPFLAGS="-DUSE_UNIX"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fatal error if --wmx configuration could not be satisified
|
||||||
|
if test x$enable_wmx = xyes \
|
||||||
|
&& test x$UNIX_CPPFLAGS = x; then
|
||||||
|
if test x$ac_cv_func_execlp != xyes; then
|
||||||
|
AC_MSG_ERROR([--wmx support requested (--enable-wmx=yes), but execlp() was not found.])
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_header_unistd_h != xyes; then
|
||||||
|
AC_MSG_ERROR([--wmx support requested (--enable-wmx=yes), but unistd.h header was not found.])
|
||||||
|
fi
|
||||||
|
if test x$ac_cv_func_fork_works != xyes; then
|
||||||
|
AC_MSG_ERROR([--wmx support requested (--enable-wmx=yes), but a working fork() was not found.])
|
||||||
|
fi
|
||||||
|
AC_MSG_ERROR([--wmx support requested (--enable-wmx=yes), but this configuration fails.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
OPTION_CPPFLAGS="$ASSERT_FLAGS $IMAGEMAGICK_CPPFLAGS $FFTW_CPPFLAGS $UNIX_CPPFLAGS $IOCTL_CPPFLAGS $COORD_CPPFLAGS $COLOR_CPPFLAGS $OPTIMIZATION_CPPFLAGS $STL_CPPFLAGS"
|
||||||
|
OPTION_CFLAGS="$IMAGEMAGICK_CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
OPTION_LDFLAGS="$IMAGEMAGICK_LDFLAGS"
|
||||||
|
OPTION_LIBS="$PTHREAD_LIBS $IMAGEMAGICK_LIBS"
|
||||||
|
|
||||||
|
AC_SUBST(OPTION_CPPFLAGS)
|
||||||
|
AC_SUBST(OPTION_CFLAGS)
|
||||||
|
AC_SUBST(OPTION_LDFLAGS)
|
||||||
|
AC_SUBST(OPTION_LIBS)
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile lib/Makefile])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
# Since the generated Makefile seems to sometimes miss build steps that are
|
||||||
|
# required due to reconfiguration, 'make clean' here.
|
||||||
|
|
||||||
|
AC_MSG_NOTICE(making clean)
|
||||||
|
make clean &> /dev/null
|
||||||
|
|
||||||
37
d2.cc
Normal file
37
d2.cc
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static data translation unit for classes treating scenes as
|
||||||
|
* two-dimensional data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "d2.h"
|
||||||
|
|
||||||
|
namespace d2 {
|
||||||
|
#include "d2/align.cc"
|
||||||
|
#include "d2/trans_multi.cc"
|
||||||
|
#include "d2/render.cc"
|
||||||
|
#include "d2/image_rw.cc"
|
||||||
|
#include "d2/image.cc"
|
||||||
|
#include "d2/exposure/exposure.cc"
|
||||||
|
#include "d2/vise_core.cc"
|
||||||
|
#include "d2/tfile.cc"
|
||||||
|
}
|
||||||
141
d2.h
Normal file
141
d2.h
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
// Copyright 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Top-level header file for classes treating scenes as two-dimensional data.
|
||||||
|
* autoconf 'config.h' should be included after this file, as we undefine
|
||||||
|
* various autoconf defines herein.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
// #include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <stack>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
#include "ale_math.h"
|
||||||
|
#include "ale_real.h"
|
||||||
|
#include "ale_accum.h"
|
||||||
|
#include "ale_pos.h"
|
||||||
|
#include "ui/ui.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_MAGICK
|
||||||
|
#include <magick/api.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ImageMagick defines these, for reasons unclear.
|
||||||
|
* Since they clash with autotools names, undefine
|
||||||
|
* them here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_FFTW
|
||||||
|
#include <fftw3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_UNIX
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
#include "rand.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All header files in the d2 namespace.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace d2 {
|
||||||
|
#include "d2/exclusion.h"
|
||||||
|
#include "d2/pixel.h"
|
||||||
|
#include "d2/spixel.h"
|
||||||
|
#include "d2/pixel_accum.h"
|
||||||
|
#include "d2/exposure/exposure.h"
|
||||||
|
#include "d2/exposure/exposure_default.h"
|
||||||
|
#include "d2/exposure/exposure_linear.h"
|
||||||
|
#include "d2/exposure/exposure_boolean.h"
|
||||||
|
#include "d2/align.h"
|
||||||
|
#include "d2/transformation.h"
|
||||||
|
#include "d2/image.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: The placement of this file is somewhat of a hack. What should
|
||||||
|
* be done about this?
|
||||||
|
*/
|
||||||
|
#include "optimizations.h"
|
||||||
|
|
||||||
|
namespace d2 {
|
||||||
|
#include "d2/image_ale_real.h"
|
||||||
|
#include "d2/image_weighted_avg.h"
|
||||||
|
#include "d2/image_weighted_simple.h"
|
||||||
|
#include "d2/image_weighted_median.h"
|
||||||
|
#include "d2/image_zero.h"
|
||||||
|
#include "d2/image_rw.h"
|
||||||
|
#include "d2/point.h"
|
||||||
|
#include "d2/ppm.h"
|
||||||
|
#include "d2/render.h"
|
||||||
|
#include "d2/render_parse.h"
|
||||||
|
#include "d2/tfile.h"
|
||||||
|
#include "d2/filter.h"
|
||||||
|
#include "d2/render/combine.h"
|
||||||
|
// #include "d2/render/drizzle.h"
|
||||||
|
// #include "d2/render/usm.h"
|
||||||
|
#include "d2/render/ipc.h"
|
||||||
|
// #include "d2/render/merge.h"
|
||||||
|
#include "d2/render/psf/psf.h"
|
||||||
|
#include "d2/render/psf/psf_template.h"
|
||||||
|
#include "d2/render/psf/box.h"
|
||||||
|
#include "d2/render/psf/circle.h"
|
||||||
|
#include "d2/render/psf/sum.h"
|
||||||
|
#include "d2/render/psf/stdin.h"
|
||||||
|
#include "d2/render/psf/stdin_vg.h"
|
||||||
|
#include "d2/render/psf/convolution.h"
|
||||||
|
#include "d2/render/psf/scalar_mult.h"
|
||||||
|
#include "d2/render/psf/psf_parse.h"
|
||||||
|
#include "d2/render/psf/psf_calibrate.h"
|
||||||
|
#include "d2/vise_core.h"
|
||||||
|
|
||||||
|
}
|
||||||
95
d2/align.cc
Normal file
95
d2/align.cc
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "align.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See align.h for details on these variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int align::_exp_register = 1;
|
||||||
|
|
||||||
|
ale_pos align::scale_factor;
|
||||||
|
|
||||||
|
transformation align::orig_t = transformation::eu_identity();
|
||||||
|
int align::_keep = 0;
|
||||||
|
transformation *align::kept_t = NULL;
|
||||||
|
int *align::kept_ok = NULL;
|
||||||
|
|
||||||
|
tload_t *align::tload = NULL;
|
||||||
|
tsave_t *align::tsave = NULL;
|
||||||
|
render *align::reference = NULL;
|
||||||
|
filter::scaled_filter *align::interpolant = NULL;
|
||||||
|
const image *align::reference_image = NULL;
|
||||||
|
const image *align::reference_defined = NULL;
|
||||||
|
const image *align::weight_map = NULL;
|
||||||
|
image *align::alignment_weights = NULL;
|
||||||
|
const char *align::wmx_file = NULL;
|
||||||
|
const char *align::wmx_exec = NULL;
|
||||||
|
const char *align::wmx_defs = NULL;
|
||||||
|
const char *align::fw_output = NULL;
|
||||||
|
double align::horiz_freq_cut = 0;
|
||||||
|
double align::vert_freq_cut = 0;
|
||||||
|
double align::avg_freq_cut = 0;
|
||||||
|
transformation align::latest_t = transformation::eu_identity();
|
||||||
|
int align::latest_ok;
|
||||||
|
int align::latest = -1;
|
||||||
|
|
||||||
|
int align::alignment_class = 1;
|
||||||
|
int align::default_initial_alignment_type = 1;
|
||||||
|
int align::perturb_type = 0;
|
||||||
|
int align::is_fail_default = 0;
|
||||||
|
int align::channel_alignment_type = 2;
|
||||||
|
ale_real align::metric_exponent = 2;
|
||||||
|
float align::match_threshold = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Upper/lower bounds
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_pos align::perturb_lower = 0.125;
|
||||||
|
int align::perturb_lower_percent = 0;
|
||||||
|
ale_pos align::perturb_upper = 14;
|
||||||
|
int align::perturb_upper_percent = 1;
|
||||||
|
|
||||||
|
int align::lod_preferred = -3;
|
||||||
|
int align::min_dimension = 10;
|
||||||
|
|
||||||
|
ale_pos align::rot_max = 32.0;
|
||||||
|
ale_pos align::bda_mult = 2;
|
||||||
|
ale_pos align::bda_rate = 8;
|
||||||
|
ale_accum align::match_sum = 0;
|
||||||
|
int align::match_count = 0;
|
||||||
|
|
||||||
|
ale_pos align::_mc = 30;
|
||||||
|
int align::certainty_weights = 0;
|
||||||
|
int align::_gs = 6;
|
||||||
|
|
||||||
|
ale_accum align::_gs_mo = 67;
|
||||||
|
int align::gs_mo_percent = 1;
|
||||||
|
|
||||||
|
ale_real align::_ma_cert = 0.01;
|
||||||
|
|
||||||
|
exclusion *align::ax_parameters = NULL;
|
||||||
|
int align::ax_count = 0;
|
||||||
|
|
||||||
|
const point **align::cp_array = NULL;
|
||||||
|
unsigned int align::cp_count = 0;
|
||||||
|
|
||||||
3781
d2/align.h
Normal file
3781
d2/align.h
Normal file
File diff suppressed because it is too large
Load Diff
43
d2/exclusion.h
Normal file
43
d2/exclusion.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2006 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __exclusion_h__
|
||||||
|
#define __exclusion_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header file for exclusion regions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exclusion data structure.
|
||||||
|
*
|
||||||
|
* XXX: For now, we're using floating point boundary values;
|
||||||
|
* this might be somewhat inefficient in cases where the values
|
||||||
|
* will always be integer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct exclusion {
|
||||||
|
enum {RENDER, FRAME};
|
||||||
|
char type;
|
||||||
|
|
||||||
|
ale_pos x[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
24
d2/exposure/exposure.cc
Normal file
24
d2/exposure/exposure.cc
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "exposure.h"
|
||||||
|
|
||||||
|
ale_real exposure::confidence_exponent = (ale_real) 1.0;
|
||||||
|
ale_real exposure::_gain_reference = 1;
|
||||||
258
d2/exposure/exposure.h
Normal file
258
d2/exposure/exposure.h
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exposure.h: A superclass for all exposure classes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __exposure_h__
|
||||||
|
#define __exposure_h__
|
||||||
|
|
||||||
|
#include "../pixel.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class models a non-linear response function. More information can be
|
||||||
|
* found here:
|
||||||
|
*
|
||||||
|
* http://wearcam.org/comparametrics.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
class exposure {
|
||||||
|
private:
|
||||||
|
static ale_real confidence_exponent;
|
||||||
|
pixel _multiplier;
|
||||||
|
ale_real _gain_multiplier;
|
||||||
|
static ale_real _gain_reference;
|
||||||
|
ale_real _black_level;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* confidence/uniform static mutators
|
||||||
|
*/
|
||||||
|
static void set_confidence(ale_real exponent) {
|
||||||
|
confidence_exponent = exponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* confidence accessor
|
||||||
|
*/
|
||||||
|
static ale_real get_confidence() {
|
||||||
|
return confidence_exponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Event listener interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
class listener {
|
||||||
|
friend class exposure;
|
||||||
|
private:
|
||||||
|
listener *next;
|
||||||
|
const char *name;
|
||||||
|
const exposure *target;
|
||||||
|
public:
|
||||||
|
virtual void trigger(pixel multiplier) = 0;
|
||||||
|
|
||||||
|
listener () {
|
||||||
|
next = NULL;
|
||||||
|
target = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~listener() {
|
||||||
|
if (target) {
|
||||||
|
target->remove_listener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable listener *listener_head;
|
||||||
|
public:
|
||||||
|
|
||||||
|
void add_listener(listener *l, const char *name) const {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a metafunction, so we consider it
|
||||||
|
* to leave the object constant.
|
||||||
|
*/
|
||||||
|
assert (l->next == NULL);
|
||||||
|
assert (l->target == NULL);
|
||||||
|
l->next = listener_head;
|
||||||
|
l->target = this;
|
||||||
|
l->name = name;
|
||||||
|
listener_head = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_listener(listener *l) const {
|
||||||
|
|
||||||
|
assert (listener_head != NULL);
|
||||||
|
|
||||||
|
if (listener_head == l) {
|
||||||
|
listener_head = listener_head->next;
|
||||||
|
} else {
|
||||||
|
assert (listener_head->next != NULL);
|
||||||
|
|
||||||
|
listener *a = listener_head;
|
||||||
|
listener *b = listener_head->next;
|
||||||
|
|
||||||
|
while (b != l) {
|
||||||
|
assert (b->next != NULL);
|
||||||
|
a = b;
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->next = b->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
l->target = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_multiplier(pixel _multiplier) {
|
||||||
|
listener *cl = listener_head;
|
||||||
|
|
||||||
|
while(cl != NULL) {
|
||||||
|
cl->trigger(_multiplier / this->_multiplier);
|
||||||
|
cl = cl->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_multiplier = _multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_gain_multiplier(ale_real g) {
|
||||||
|
_gain_multiplier = g;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real get_gain_multiplier() {
|
||||||
|
return _gain_multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_black_level(ale_real b) {
|
||||||
|
_black_level = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real get_black_level() {
|
||||||
|
return _black_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_gain_reference(ale_real r) {
|
||||||
|
_gain_reference = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ale_real get_gain_reference() {
|
||||||
|
return _gain_reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel get_multiplier() const {
|
||||||
|
return _multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ale_real confidence(unsigned int k, ale_real input,
|
||||||
|
ale_real confidence_floor = ale_real_confidence_floor) const {
|
||||||
|
|
||||||
|
ale_real _0 = (ale_real) 0;
|
||||||
|
ale_real _4 = (ale_real) 4;
|
||||||
|
ale_real _2 = (ale_real) 2;
|
||||||
|
ale_real _1 = (ale_real) 1;
|
||||||
|
|
||||||
|
if (confidence_exponent == _0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ale_real input_scaled = input / _multiplier[k];
|
||||||
|
|
||||||
|
ale_real unexponentiated = _1 - _4 * ((_1 / _2) - input_scaled)
|
||||||
|
* ((_1 / _2) - input_scaled);
|
||||||
|
|
||||||
|
// ale_real unexponentiated = _4 * ((_1 / _4) - (ale_real) ((_1 / _2) - input_scaled)
|
||||||
|
// * ((_1 / _2) - input_scaled));
|
||||||
|
|
||||||
|
// ale_real unexponentiated = 4 * input_scaled * (0.25 - pow(0.5 - input_scaled, 2));
|
||||||
|
|
||||||
|
ale_real exponentiated;
|
||||||
|
|
||||||
|
if (confidence_exponent != _1) {
|
||||||
|
|
||||||
|
if (unexponentiated < _0)
|
||||||
|
return confidence_floor;
|
||||||
|
|
||||||
|
exponentiated = pow(unexponentiated, confidence_exponent);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
exponentiated = unexponentiated;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exponentiated < confidence_floor || !finite(exponentiated))
|
||||||
|
return confidence_floor;
|
||||||
|
|
||||||
|
return exponentiated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a very hackish confidence function. It's zero at the
|
||||||
|
* extremes of camera response and maximal at the center.
|
||||||
|
*/
|
||||||
|
virtual pixel confidence(pixel input,
|
||||||
|
ale_real confidence_floor = ale_real_confidence_floor) const {
|
||||||
|
|
||||||
|
if (confidence_exponent != 0) {
|
||||||
|
return pixel(confidence(0, input[0], confidence_floor),
|
||||||
|
confidence(1, input[1], confidence_floor),
|
||||||
|
confidence(2, input[2], confidence_floor));
|
||||||
|
} else {
|
||||||
|
return pixel(1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Confidence that the real value is lower or higher than the given
|
||||||
|
* value.
|
||||||
|
*
|
||||||
|
* XXX: This function now applies the one-sided condition only to
|
||||||
|
* responses greater than 50%. Should it be called
|
||||||
|
* 'upper_one_sided_confidence' instead?
|
||||||
|
*/
|
||||||
|
virtual pixel one_sided_confidence(pixel input, pixel sign) const {
|
||||||
|
if (confidence_exponent != 0) {
|
||||||
|
pixel result = confidence(input);
|
||||||
|
for (unsigned int k = 0; k < 3; k++) {
|
||||||
|
if (sign[k] > 0 && input[k] / _multiplier[k] > 1 / (ale_real) 2)
|
||||||
|
result[k] = 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return pixel(1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual pixel linearize(pixel input) const = 0;
|
||||||
|
virtual pixel unlinearize(pixel input) const = 0;
|
||||||
|
|
||||||
|
exposure() {
|
||||||
|
listener_head = NULL;
|
||||||
|
_multiplier = pixel(1, 1, 1);
|
||||||
|
_gain_multiplier = 1;
|
||||||
|
_black_level = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~exposure() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
46
d2/exposure/exposure_boolean.h
Normal file
46
d2/exposure/exposure_boolean.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exposure_boolean.h: Boolean exposure properties.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __exposure_boolean_h__
|
||||||
|
#define __exposure_boolean_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Boolean exposure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class exposure_boolean : public exposure {
|
||||||
|
public:
|
||||||
|
pixel linearize(pixel input) const {
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
input[k] = (input[k] == 0) ? 0 : 1;
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
pixel unlinearize(pixel input) const {
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
input[k] = (input[k] == 0) ? 0 : 1;
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
160
d2/exposure/exposure_default.h
Normal file
160
d2/exposure/exposure_default.h
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exposure_default.h: Default exposure properties.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __exposure_default_h__
|
||||||
|
#define __exposure_default_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The default exposure is modeled after the simple power transfer function
|
||||||
|
* described in
|
||||||
|
*
|
||||||
|
* http://netpbm.sourceforge.net/doc/pnmgamma.html
|
||||||
|
*
|
||||||
|
* Note: optimizations in d2/image_rw.h depend on the details of this function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class exposure_default : public exposure {
|
||||||
|
public:
|
||||||
|
pixel linearize(pixel input) const {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Calling pow() may be expensive on some platforms (e.g.,
|
||||||
|
* those lacking hardware support for floating point).
|
||||||
|
*/
|
||||||
|
|
||||||
|
return ppow(input, 1/0.45) * get_multiplier();
|
||||||
|
#else
|
||||||
|
const int table_size = 1024;
|
||||||
|
const int table_bits = 10;
|
||||||
|
const int interp_bits = 6;
|
||||||
|
static int table_is_built = 0;
|
||||||
|
static ale_real table[table_size];
|
||||||
|
|
||||||
|
pixel result;
|
||||||
|
|
||||||
|
if (!table_is_built) {
|
||||||
|
for (int i = 0; i < table_size; i++) {
|
||||||
|
table[i] = pow((float) i / (float) (table_size - 1), 1/0.45);
|
||||||
|
}
|
||||||
|
table_is_built = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
/*
|
||||||
|
* Clamp.
|
||||||
|
*/
|
||||||
|
if (input[k] >= 1) {
|
||||||
|
result[k] = 1;
|
||||||
|
continue;
|
||||||
|
} else if (input[k] <= 0) {
|
||||||
|
result[k] = 0;
|
||||||
|
continue;
|
||||||
|
} else if (isnan(input[k])) {
|
||||||
|
result[k] = input[k];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index1 = ale_real_to_int(input[k], 65535);
|
||||||
|
|
||||||
|
int index2 = index1 >> (16 - table_bits);
|
||||||
|
int index3 = (index1 >> (16 - table_bits - interp_bits))
|
||||||
|
& ((1 << interp_bits) - 1);
|
||||||
|
|
||||||
|
if (index2 >= table_size - 1) {
|
||||||
|
result[k] = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real frac = ale_real_from_int((index3 << (16 - interp_bits)), 65535);
|
||||||
|
|
||||||
|
result[k] = (1 - frac) * table[index2] + frac * table[index2 + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result * get_multiplier();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
pixel unlinearize(pixel input) const {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Calling pow() may be expensive on some platforms (e.g.,
|
||||||
|
* those lacking hardware support for floating point).
|
||||||
|
*/
|
||||||
|
|
||||||
|
return ppow(input / get_multiplier(), 0.45);
|
||||||
|
#else
|
||||||
|
|
||||||
|
input /= get_multiplier();
|
||||||
|
|
||||||
|
const int table_size = 1024;
|
||||||
|
const int table_bits = 10;
|
||||||
|
const int interp_bits = 6;
|
||||||
|
static int table_is_built = 0;
|
||||||
|
static ale_real table[table_size];
|
||||||
|
|
||||||
|
pixel result;
|
||||||
|
|
||||||
|
if (!table_is_built) {
|
||||||
|
for (int i = 0; i < table_size; i++) {
|
||||||
|
table[i] = pow((float) i / (float) (table_size - 1), 0.45);
|
||||||
|
}
|
||||||
|
table_is_built = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
/*
|
||||||
|
* Clamp.
|
||||||
|
*/
|
||||||
|
if (input[k] >= 1) {
|
||||||
|
result[k] = 1;
|
||||||
|
continue;
|
||||||
|
} else if (input[k] <= 0) {
|
||||||
|
result[k] = 0;
|
||||||
|
continue;
|
||||||
|
} else if (isnan(input[k])) {
|
||||||
|
result[k] = input[k];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index1 = ale_real_to_int(input[k], 65535);
|
||||||
|
|
||||||
|
int index2 = index1 >> (16 - table_bits);
|
||||||
|
int index3 = (index1 >> (16 - table_bits - interp_bits))
|
||||||
|
& ((1 << interp_bits) - 1);
|
||||||
|
|
||||||
|
if (index2 >= table_size - 1) {
|
||||||
|
result[k] = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real frac = ale_real_from_int((index3 << (16 - interp_bits)), 65535);
|
||||||
|
|
||||||
|
result[k] = (1 - frac) * table[index2] + frac * table[index2 + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
42
d2/exposure/exposure_linear.h
Normal file
42
d2/exposure/exposure_linear.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exposure_linear.h: Linear exposure properties.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __exposure_linear_h__
|
||||||
|
#define __exposure_linear_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linear exposure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class exposure_linear : public exposure {
|
||||||
|
public:
|
||||||
|
pixel linearize(pixel input) const {
|
||||||
|
return input * get_multiplier();
|
||||||
|
}
|
||||||
|
pixel unlinearize(pixel input) const {
|
||||||
|
return input / get_multiplier();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
51
d2/filter.h
Normal file
51
d2/filter.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __filternamespace_h__
|
||||||
|
#define __filternamespace_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include files from the current namespace
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "point.h"
|
||||||
|
#include "transformation.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "image_ale_real.h"
|
||||||
|
#include "image_bayer_ale_real.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Establish a new namespace for all filtering classes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace filter {
|
||||||
|
#include "filter/filter.h"
|
||||||
|
#include "filter/sinc.h"
|
||||||
|
#include "filter/lanczos.h"
|
||||||
|
#include "filter/triangle.h"
|
||||||
|
#include "filter/box.h"
|
||||||
|
#include "filter/gauss.h"
|
||||||
|
#include "filter/zero.h"
|
||||||
|
#include "filter/mult.h"
|
||||||
|
#include "filter/scaled_filter.h"
|
||||||
|
#include "filter/ssfe.h"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
74
d2/filter/box.h
Normal file
74
d2/filter/box.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __d2_filter_box_h__
|
||||||
|
#define __d2_filter_box_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A box filter class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class box : public filter {
|
||||||
|
private:
|
||||||
|
ale_pos half_width;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Box filter.
|
||||||
|
*/
|
||||||
|
ale_real _box(ale_pos p) const {
|
||||||
|
if (fabs(p) > half_width)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real _box(point p) const {
|
||||||
|
return _box(p[0]) * _box(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of filter support, in number of half-cycles to each side of the
|
||||||
|
* filter center.
|
||||||
|
*/
|
||||||
|
ale_pos support() const {
|
||||||
|
return half_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response of filter at point p
|
||||||
|
*/
|
||||||
|
virtual ale_real response(point p) const {
|
||||||
|
return _box(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int equals(const filter *f) const {
|
||||||
|
if (typeid(*f) == typeid(*this))
|
||||||
|
return ((box *)f)->half_width == half_width;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
box(ale_pos half_width) {
|
||||||
|
this->half_width = half_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
||||||
47
d2/filter/filter.h
Normal file
47
d2/filter/filter.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __filterclass_h__
|
||||||
|
#define __filterclass_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A superclass for all filtering classes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class filter {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of filter support, in number of half-cycles to each side of the
|
||||||
|
* filter center.
|
||||||
|
*/
|
||||||
|
virtual ale_pos support() const = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response of filter at point p
|
||||||
|
*/
|
||||||
|
virtual ale_real response(point p) const = 0;
|
||||||
|
|
||||||
|
virtual int equals(const filter *f) const = 0;
|
||||||
|
|
||||||
|
virtual ~filter(){
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
92
d2/filter/gauss.h
Normal file
92
d2/filter/gauss.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
// code by HJ Hornbeck, based on code copyright David Hilvert
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __d2_filter_gauss_h__
|
||||||
|
#define __d2_filter_gauss_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A Gaussian filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class gauss : public filter {
|
||||||
|
private:
|
||||||
|
ale_pos sigma;
|
||||||
|
ale_pos diameter; /** measured in standard deviations **/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The heavy-lifting function:
|
||||||
|
*/
|
||||||
|
ale_real _calc(ale_pos p) const {
|
||||||
|
|
||||||
|
/** catch the trivial cases **/
|
||||||
|
if ( p == 0 ) return 1;
|
||||||
|
/** if ( p > (sigma*diameter) ) return 0;
|
||||||
|
^^ unnecessary, gauss is well-behaved
|
||||||
|
outside its radius **/
|
||||||
|
|
||||||
|
/** calculate the rest **/
|
||||||
|
|
||||||
|
ale_pos p2 = p * p;
|
||||||
|
ale_pos sigma2 = sigma * sigma;
|
||||||
|
|
||||||
|
return exp( -(p2/sigma2) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** extend the heavy-lifting function to handle a coordinate **/
|
||||||
|
ale_real _calc(point p) const {
|
||||||
|
|
||||||
|
return _calc( sqrt( (p[0]*p[0]) + (p[1]*p[1]) ) );
|
||||||
|
|
||||||
|
/** doesn't work as well:
|
||||||
|
return _calc( p[0] ) * _calc( p[1] ); **/
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of filter support, or how big a radius does this filter
|
||||||
|
* touch?
|
||||||
|
*/
|
||||||
|
ale_pos support() const {
|
||||||
|
return sigma*diameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response of filter at point p
|
||||||
|
*/
|
||||||
|
virtual ale_real response(point p) const {
|
||||||
|
return _calc(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** only compare standard deviations, since this version fixes
|
||||||
|
the diameter across all instances **/
|
||||||
|
virtual int equals(const filter *f) const {
|
||||||
|
if (typeid(*f) == typeid(*this))
|
||||||
|
return ((gauss *)f)->sigma == sigma;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gauss(ale_pos sigma) {
|
||||||
|
this->sigma = sigma;
|
||||||
|
this->diameter = 2; /** fixed, standard for imaging **/
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
||||||
81
d2/filter/lanczos.h
Normal file
81
d2/filter/lanczos.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __lanczos_h__
|
||||||
|
#define __lanczos_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A lanczos filter class.
|
||||||
|
*
|
||||||
|
* Notes on Lanczos and Sinc by Dave Martindale et alia are available here:
|
||||||
|
*
|
||||||
|
* http://www.binbooks.com/books/photo/i/l/57186AF8DE
|
||||||
|
* http://www.binbooks.com/books/photo/i/l/57186AE7E6&orig=1
|
||||||
|
*/
|
||||||
|
|
||||||
|
class lanczos : public filter {
|
||||||
|
private:
|
||||||
|
ale_pos half_width;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lanczos function
|
||||||
|
*
|
||||||
|
* The lanczos function is the central lobe of the sinc function.
|
||||||
|
*/
|
||||||
|
ale_real _lanczos(ale_pos p) const {
|
||||||
|
if (fabs(p) >= half_width)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return sinc::_sinc(p / half_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real _lanczos(point p) const {
|
||||||
|
return _lanczos(p[0]) * _lanczos(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of filter support, in number of half-cycles to each side of the
|
||||||
|
* filter center.
|
||||||
|
*/
|
||||||
|
ale_pos support() const {
|
||||||
|
return half_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int equals(const filter *f) const {
|
||||||
|
if (typeid(*f) == typeid(*this))
|
||||||
|
return ((lanczos *)f)->half_width == half_width;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response of filter at point p
|
||||||
|
*/
|
||||||
|
virtual ale_real response(point p) const {
|
||||||
|
return _lanczos(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
lanczos(double half_width) {
|
||||||
|
this->half_width = half_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
||||||
75
d2/filter/mult.h
Normal file
75
d2/filter/mult.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __mult_h__
|
||||||
|
#define __mult_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A class for pointwise multiplication of filters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class mult : public filter {
|
||||||
|
private:
|
||||||
|
ale_pos _support;
|
||||||
|
filter *f1, *f2;
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of filter support, in number of half-cycles to each side of the
|
||||||
|
* filter center.
|
||||||
|
*/
|
||||||
|
virtual ale_pos support() const {
|
||||||
|
return _support;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int equals(const filter *f) const {
|
||||||
|
if (typeid(*f) != typeid(*this))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const mult *m = (const mult *)f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: if we wished, we could recognize commutativity.
|
||||||
|
*/
|
||||||
|
return (m->f1->equals(f1)
|
||||||
|
&& m->f2->equals(f2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response of filter at point p
|
||||||
|
*/
|
||||||
|
virtual ale_real response(point p) const {
|
||||||
|
return f1->response(p) * f2->response(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
mult(filter *f1, filter *f2) {
|
||||||
|
this->f1 = f1;
|
||||||
|
this->f2 = f2;
|
||||||
|
assert (f1 != NULL);
|
||||||
|
assert (f2 != NULL);
|
||||||
|
|
||||||
|
_support = f1->support();
|
||||||
|
|
||||||
|
if (f2->support() < _support)
|
||||||
|
_support = f2->support();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
||||||
477
d2/filter/scaled_filter.h
Normal file
477
d2/filter/scaled_filter.h
Normal file
@@ -0,0 +1,477 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __scaled_filter_h__
|
||||||
|
#define __scaled_filter_h__
|
||||||
|
|
||||||
|
#include "filter.h"
|
||||||
|
#include "mult.h"
|
||||||
|
#include "sinc.h"
|
||||||
|
#include "triangle.h"
|
||||||
|
#include "box.h"
|
||||||
|
#include "gauss.h"
|
||||||
|
#include "lanczos.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Useful constants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// static const ale_pos sqrt2 = (ale_pos) 1.41421356237309504880;
|
||||||
|
// static const ale_pos one_over_sqrt2 = (ale_pos) 0.70710678118654752440;
|
||||||
|
|
||||||
|
static const ale_pos sqrt2 = sqrt((ale_pos) 2);
|
||||||
|
static const ale_pos one_over_sqrt2 = 1 / sqrt2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scaled filter class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class scaled_filter {
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* Frequency limit:
|
||||||
|
*
|
||||||
|
* 0: indicates the higher limit (identical to output frequency)
|
||||||
|
*
|
||||||
|
* 1: indicates the safer limit (minimum of input and output
|
||||||
|
* frequencies)
|
||||||
|
*
|
||||||
|
* 2: indicates a limit dynamically derived from subsequent chain
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
int frequency_limit;
|
||||||
|
filter *f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* filter function parameters
|
||||||
|
*
|
||||||
|
* Parameters include data regarding the current image and
|
||||||
|
* transformation. All parameters are mutable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A pointer to the current image is stored, as well as the image
|
||||||
|
* offset and bayer type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mutable const image *im;
|
||||||
|
mutable unsigned int bayer;
|
||||||
|
mutable point offset;
|
||||||
|
|
||||||
|
/* We are either using one transformation or a combination of two
|
||||||
|
* transformations. T_TWO indicates whether two transformations are
|
||||||
|
* being used. T[] stores the transformations. When only one
|
||||||
|
* transformation is used, OFFSET stores the image offset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mutable unsigned int t_two;
|
||||||
|
mutable transformation t0, t1;
|
||||||
|
mutable int _is_projective;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transform a point using the current transformation.
|
||||||
|
*/
|
||||||
|
point transform(point p, const trans_single &ts0, const trans_single &ts1) const {
|
||||||
|
if (t_two)
|
||||||
|
return ts1.unscaled_inverse_transform(ts0.transform_unscaled(p));
|
||||||
|
|
||||||
|
return ts0.transform_unscaled(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inverse of the above.
|
||||||
|
*/
|
||||||
|
point transform_inverse(point p, const trans_single &ts0, const trans_single &ts1) const {
|
||||||
|
if (t_two)
|
||||||
|
return ts0.unscaled_inverse_transform(ts1.transform_unscaled(p));
|
||||||
|
|
||||||
|
return ts0.unscaled_inverse_transform(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns non-zero if the transformation might be non-Euclidean.
|
||||||
|
*/
|
||||||
|
int is_projective() const {
|
||||||
|
return _is_projective;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are limiting to source frequencies, then scale a filter to
|
||||||
|
* accept only frequencies we know to be expressible in the source.
|
||||||
|
* (Or do this approximately.)
|
||||||
|
*/
|
||||||
|
void freq_limit(point p, point mapped_p, ale_pos *hscale_g,
|
||||||
|
ale_pos *hscale_rb, ale_pos *wscale_g, ale_pos *wscale_rb,
|
||||||
|
const trans_single &ts0, const trans_single &ts1) const {
|
||||||
|
|
||||||
|
if (frequency_limit == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ale_pos hnorm, wnorm;
|
||||||
|
|
||||||
|
point dh = transform_inverse(p + point(1, 0), ts0, ts1);
|
||||||
|
point dw = transform_inverse(p + point(0, 1), ts0, ts1);
|
||||||
|
|
||||||
|
hnorm = (mapped_p - dh).norm();
|
||||||
|
wnorm = (mapped_p - dw).norm();
|
||||||
|
|
||||||
|
if (bayer == IMAGE_BAYER_NONE) {
|
||||||
|
if (hnorm < 1) {
|
||||||
|
*hscale_g = hnorm;
|
||||||
|
*hscale_rb = hnorm;
|
||||||
|
}
|
||||||
|
if (wnorm < 1) {
|
||||||
|
*wscale_g = wnorm;
|
||||||
|
*wscale_rb = wnorm;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (hnorm < sqrt2) {
|
||||||
|
*hscale_g = hnorm / sqrt2;
|
||||||
|
*hscale_rb = hnorm / 2;
|
||||||
|
} else if (hnorm < 2) {
|
||||||
|
*hscale_rb = hnorm / 2;
|
||||||
|
}
|
||||||
|
if (wnorm < sqrt2) {
|
||||||
|
*wscale_g = wnorm / sqrt2;
|
||||||
|
*wscale_rb = wnorm / 2;
|
||||||
|
} else if (wnorm < 2) {
|
||||||
|
*wscale_rb = wnorm / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void filter_channel(point p, point mapped_p, unsigned int k, ale_pos hscale,
|
||||||
|
ale_pos wscale, pixel *result, pixel *weight, int honor_exclusion,
|
||||||
|
int frame, ale_real prev_value, ale_real prev_weight,
|
||||||
|
const trans_single &ts0, const trans_single &ts1) const {
|
||||||
|
|
||||||
|
ale_real temp_result = (*result)[k], temp_weight = (*weight)[k];
|
||||||
|
ale_real certainty;
|
||||||
|
|
||||||
|
if (prev_weight > 0)
|
||||||
|
certainty = im->exp().confidence(k, prev_value);
|
||||||
|
else
|
||||||
|
certainty = 1; /* We calculate certainty later */
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
/*
|
||||||
|
* This test matches the technical description.
|
||||||
|
*/
|
||||||
|
if (hscale < 1 && wscale < 1) {
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* This approach is ~33% faster for Euclidean transformations,
|
||||||
|
* but is likely to produce different results in some cases.
|
||||||
|
*/
|
||||||
|
if (hscale <= 1 && wscale <= 1) {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the especially coarse case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_pos fscale;
|
||||||
|
|
||||||
|
if (frequency_limit) {
|
||||||
|
fscale = (bayer == IMAGE_BAYER_NONE)
|
||||||
|
? (ale_pos) 1
|
||||||
|
: (k == 1) ? sqrt2 : (ale_pos) 2;
|
||||||
|
} else {
|
||||||
|
fscale = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int min_i, max_i, min_j, max_j;
|
||||||
|
|
||||||
|
ale_pos support = f->support() * fscale;
|
||||||
|
|
||||||
|
if (1 / support == 0) {
|
||||||
|
min_i = 0;
|
||||||
|
max_i = im->height() - 1;
|
||||||
|
min_j = 0;
|
||||||
|
max_j = im->width() - 1;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
point min = mapped_p - point(support, support);
|
||||||
|
point max = mapped_p + point(support, support);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lrintf() may be faster than ceil/floor() on some architectures.
|
||||||
|
* See render/psf/raster.h for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
min_i = (int) lrintf(min[0]);
|
||||||
|
max_i = (int) lrintf(max[0]);
|
||||||
|
min_j = (int) lrintf(min[1]);
|
||||||
|
max_j = (int) lrintf(max[1]);
|
||||||
|
|
||||||
|
if (min_i < 0)
|
||||||
|
min_i = 0;
|
||||||
|
if (max_i > (int) im->height() - 1)
|
||||||
|
max_i = (int) im->height() - 1;
|
||||||
|
if (min_j < 0)
|
||||||
|
min_j = 0;
|
||||||
|
if (max_j > (int) im->width() - 1)
|
||||||
|
max_j = (int) im->width() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over the source pixels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = min_i; i <= max_i; i++)
|
||||||
|
for (int j = min_j; j <= max_j; j++) {
|
||||||
|
|
||||||
|
if (honor_exclusion && render::is_excluded_f(i, j, frame))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bayer != IMAGE_BAYER_NONE
|
||||||
|
&& (im->get_channels(i, j) & (1 << k)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
point a = point(i, j);
|
||||||
|
|
||||||
|
ale_real v = im->get_chan(i, j, k);
|
||||||
|
|
||||||
|
ale_real response = f->response((a - mapped_p) / fscale);
|
||||||
|
|
||||||
|
ale_real w = certainty * response;
|
||||||
|
|
||||||
|
temp_weight += w;
|
||||||
|
temp_result += w * v;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Establish the boundaries of filtering in the source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
point min = mapped_p;
|
||||||
|
point max = mapped_p;
|
||||||
|
|
||||||
|
int imin[2];
|
||||||
|
int imax[2];
|
||||||
|
|
||||||
|
ale_pos sup = f->support();
|
||||||
|
|
||||||
|
if (1 / sup == 0) {
|
||||||
|
imin[0] = 0;
|
||||||
|
imax[0] = im->height() - 1;
|
||||||
|
imin[1] = 0;
|
||||||
|
imax[1] = im->width() - 1;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ale_pos hsup = sup / hscale;
|
||||||
|
ale_pos wsup = sup / wscale;
|
||||||
|
|
||||||
|
for (int ii = -1; ii <= +1; ii+=2)
|
||||||
|
for (int jj = -1; jj <= +1; jj+=2) {
|
||||||
|
|
||||||
|
point b = transform_inverse(point(hsup * ii, wsup * jj) + p, ts0, ts1);
|
||||||
|
for (int d = 0; d < 2; d++) {
|
||||||
|
if (b[d] < min[d])
|
||||||
|
min[d] = b[d];
|
||||||
|
if (b[d] > max[d])
|
||||||
|
max[d] = b[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lrintf() may be faster than ceil/floor() on some architectures.
|
||||||
|
* See render/psf/raster.h for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
imin[0] = lrintf(min[0]);
|
||||||
|
imax[0] = lrintf(max[0]);
|
||||||
|
imin[1] = lrintf(min[1]);
|
||||||
|
imax[1] = lrintf(max[1]);
|
||||||
|
|
||||||
|
if (imin[0] < 0)
|
||||||
|
imin[0] = 0;
|
||||||
|
if (imax[0] > (int) im->height() - 1)
|
||||||
|
imax[0] = (int) im->height() - 1;
|
||||||
|
if (imin[1] < 0)
|
||||||
|
imin[1] = 0;
|
||||||
|
if (imax[1] > (int) im->width() - 1)
|
||||||
|
imax[1] = (int) im->width() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over the source pixels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = imin[0]; i <= imax[0]; i++)
|
||||||
|
for (int j = imin[1]; j <= imax[1]; j++) {
|
||||||
|
|
||||||
|
if (honor_exclusion && render::is_excluded_f(i, j, frame))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bayer != IMAGE_BAYER_NONE
|
||||||
|
&& (im->get_channels(i, j) & (1 << k)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
point a = transform(point(i, j), ts0, ts1);
|
||||||
|
|
||||||
|
ale_real v = im->get_chan(i, j, k);
|
||||||
|
|
||||||
|
ale_real response = f->response((a - p) * point(hscale, wscale));
|
||||||
|
|
||||||
|
ale_real w = certainty * response;
|
||||||
|
|
||||||
|
temp_weight += w;
|
||||||
|
temp_result += w * v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(prev_weight > 0)
|
||||||
|
&& d2::exposure::get_confidence() != 0
|
||||||
|
&& temp_weight > 0) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate certainty for the first pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
certainty = im->exp().confidence(k, temp_result / temp_weight);
|
||||||
|
temp_weight *= certainty;
|
||||||
|
temp_result *= certainty;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*result)[k] = temp_result;
|
||||||
|
(*weight)[k] = temp_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
scaled_filter(filter *f, int frequency_limit) :
|
||||||
|
t0(transformation::eu_identity()),
|
||||||
|
t1(transformation::eu_identity()) {
|
||||||
|
|
||||||
|
this->frequency_limit = frequency_limit;
|
||||||
|
this->f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter *get_filter() const {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int equals(scaled_filter *s) {
|
||||||
|
return (frequency_limit == s->frequency_limit
|
||||||
|
&& f->equals(s->f));
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_coarse() const {
|
||||||
|
return frequency_limit == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_fine() const {
|
||||||
|
return frequency_limit == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_dynamic() const {
|
||||||
|
return frequency_limit == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the transformation T and image IM.
|
||||||
|
*/
|
||||||
|
void set_parameters(transformation _t, const image *_im, point _offset) const {
|
||||||
|
t_two = 0;
|
||||||
|
t0 = _t;
|
||||||
|
im = _im;
|
||||||
|
|
||||||
|
bayer = im->get_bayer();
|
||||||
|
offset = _offset;
|
||||||
|
|
||||||
|
_is_projective = _t.is_projective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the transformations T and S, and image IM.
|
||||||
|
*/
|
||||||
|
void set_parameters(transformation _t, transformation _s, const image *_im) const {
|
||||||
|
t_two = 1;
|
||||||
|
t0 = _t;
|
||||||
|
t1 = _s;
|
||||||
|
im = _im;
|
||||||
|
|
||||||
|
bayer = im->get_bayer();
|
||||||
|
offset = point(0, 0);
|
||||||
|
|
||||||
|
_is_projective = t0.is_projective() || t1.is_projective();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return filtered RESULT and WEIGHT at point P in a coordinate system
|
||||||
|
* specified by the inverse of transformation T based on data taken
|
||||||
|
* from image IM.
|
||||||
|
*/
|
||||||
|
void filtered(int i, int j, pixel *result, pixel *weight,
|
||||||
|
int honor_exclusion, int frame,
|
||||||
|
pixel prev_value = pixel(0, 0, 0),
|
||||||
|
pixel prev_weight = pixel(0, 0, 0)) const {
|
||||||
|
|
||||||
|
trans_single ts0, ts1;
|
||||||
|
pixel tm;
|
||||||
|
|
||||||
|
point p = point(i, j) + offset;
|
||||||
|
|
||||||
|
*result = pixel(0, 0, 0);
|
||||||
|
*weight = pixel(0, 0, 0);
|
||||||
|
|
||||||
|
ale_pos hscale_g = 1;
|
||||||
|
ale_pos hscale_rb = 1;
|
||||||
|
ale_pos wscale_g = 1;
|
||||||
|
ale_pos wscale_rb = 1;
|
||||||
|
|
||||||
|
if (t_two) {
|
||||||
|
ts1 = t1.t_at_point(p);
|
||||||
|
ts0 = t0.t_at_inv_point(ts1.transform_unscaled(p));
|
||||||
|
tm = ts0.get_tonal_multiplier(point(0, 0)) / ts1.get_tonal_multiplier(point(0, 0));
|
||||||
|
} else {
|
||||||
|
ts0 = t0.t_at_inv_point(p);
|
||||||
|
tm = ts0.get_tonal_multiplier(point(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_value /= tm;
|
||||||
|
|
||||||
|
point mapped_p = transform_inverse(p, ts0, ts1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allowing points such as these results in problems that are
|
||||||
|
* annoying to resolve. Solving such problems is not obviously
|
||||||
|
* worth the effort, given that they can be avoided entirely by
|
||||||
|
* disallowing the points.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (mapped_p[0] < 0 || mapped_p[0] > im->height() - 1
|
||||||
|
|| mapped_p[1] < 0 || mapped_p[1] > im->width() - 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
freq_limit(p, mapped_p, &hscale_g, &hscale_rb, &wscale_g, &wscale_rb, ts0, ts1);
|
||||||
|
|
||||||
|
filter_channel(p, mapped_p, 0, hscale_rb, wscale_rb, result, weight, honor_exclusion, frame, prev_value[0], prev_weight[0], ts0, ts1);
|
||||||
|
filter_channel(p, mapped_p, 2, hscale_rb, hscale_rb, result, weight, honor_exclusion, frame, prev_value[2], prev_weight[2], ts0, ts1);
|
||||||
|
filter_channel(p, mapped_p, 1, hscale_g , hscale_g , result, weight, honor_exclusion, frame, prev_value[1], prev_weight[1], ts0, ts1);
|
||||||
|
|
||||||
|
(*result) *= tm;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
76
d2/filter/sinc.h
Normal file
76
d2/filter/sinc.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __sinc_h__
|
||||||
|
#define __sinc_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A filtering class for the sinc function.
|
||||||
|
*
|
||||||
|
* Notes on Lanczos and Sinc by Dave Martindale et alia are available here:
|
||||||
|
*
|
||||||
|
* http://www.binbooks.com/books/photo/i/l/57186AF8DE
|
||||||
|
* http://www.binbooks.com/books/photo/i/l/57186AE7E6&orig=1
|
||||||
|
*/
|
||||||
|
|
||||||
|
class sinc : public filter {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sinc filter.
|
||||||
|
*
|
||||||
|
* Width is infinite.
|
||||||
|
*/
|
||||||
|
static double _sinc(ale_pos p) {
|
||||||
|
if (fabs(p) < 0.001)
|
||||||
|
return 1;
|
||||||
|
return sin(M_PI * p) / (M_PI * p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double _sinc(point p) {
|
||||||
|
return _sinc(p[0]) * _sinc(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int equals(const filter *f) const {
|
||||||
|
if (typeid(*f) == typeid(*this))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of filter support, in number of half-cycles to each side of the
|
||||||
|
* filter center.
|
||||||
|
*/
|
||||||
|
virtual ale_pos support() const {
|
||||||
|
double zero = 0;
|
||||||
|
double infinity = 1 / zero;
|
||||||
|
assert (!isnan(infinity));
|
||||||
|
assert (1 < infinity);
|
||||||
|
return (ale_pos) infinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response of filter at point p
|
||||||
|
*/
|
||||||
|
virtual ale_real response(point p) const {
|
||||||
|
return _sinc(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
98
d2/filter/ssfe.h
Normal file
98
d2/filter/ssfe.h
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ssfe_h__
|
||||||
|
#define __ssfe_h__
|
||||||
|
|
||||||
|
#include "scaled_filter.h"
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scaled filter class with exclusion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ssfe {
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* Honor exclusion?
|
||||||
|
*/
|
||||||
|
int honor_exclusion;
|
||||||
|
scaled_filter *f;
|
||||||
|
mutable point _offset;
|
||||||
|
mutable int have_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ssfe(scaled_filter *f, int honor_exclusion) {
|
||||||
|
this->honor_exclusion = honor_exclusion;
|
||||||
|
this->f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scaled_filter *get_scaled_filter() const {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int equals(const ssfe *s) {
|
||||||
|
return (honor_exclusion == s->honor_exclusion
|
||||||
|
&& f->equals(s->f));
|
||||||
|
}
|
||||||
|
|
||||||
|
int ex_is_honored() const {
|
||||||
|
return honor_exclusion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the parameters for filtering.
|
||||||
|
*/
|
||||||
|
void set_parameters(transformation t, const image *im, point offset) const {
|
||||||
|
have_offset = 1;
|
||||||
|
_offset = offset;
|
||||||
|
f->set_parameters(t, im, offset);
|
||||||
|
}
|
||||||
|
void set_parameters(transformation t, transformation s, const image *im) const {
|
||||||
|
have_offset = 0;
|
||||||
|
f->set_parameters(t, s, im);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return filtered RESULT and WEIGHT at point P in a coordinate system
|
||||||
|
* specified by the inverse of transformation T based on data taken
|
||||||
|
* from image IM.
|
||||||
|
*/
|
||||||
|
void filtered(int i, int j, int frame, pixel *result,
|
||||||
|
pixel *weight, pixel prev_value = pixel(0, 0, 0), pixel prev_weight = pixel(0, 0, 0)) const {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need a valid offset in order to determine exclusion
|
||||||
|
* regions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert (have_offset || !honor_exclusion);
|
||||||
|
|
||||||
|
*result = pixel(0, 0, 0);
|
||||||
|
*weight = pixel(0, 0, 0);
|
||||||
|
|
||||||
|
if (honor_exclusion && render::is_excluded_r(_offset, i, j, frame))
|
||||||
|
return;
|
||||||
|
|
||||||
|
f->filtered(i, j, result, weight, honor_exclusion, frame, prev_value, prev_weight);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
76
d2/filter/triangle.h
Normal file
76
d2/filter/triangle.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __triangle_h__
|
||||||
|
#define __triangle_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A triangle filter class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class triangle : public filter {
|
||||||
|
private:
|
||||||
|
ale_pos half_width;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Triangle filter.
|
||||||
|
*/
|
||||||
|
ale_real _triangle(ale_pos p) const {
|
||||||
|
ale_pos fabs_p = fabs(p);
|
||||||
|
|
||||||
|
if (fabs_p >= half_width)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (1 - fabs_p / half_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real _triangle(point p) const {
|
||||||
|
return _triangle(p[0]) * _triangle(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of filter support, in number of half-cycles to each side of the
|
||||||
|
* filter center.
|
||||||
|
*/
|
||||||
|
virtual ale_pos support() const {
|
||||||
|
return half_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int equals(const filter *f) const {
|
||||||
|
if (typeid(*f) == typeid(*this))
|
||||||
|
return ((triangle *)f)->half_width == half_width;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response of filter at point p
|
||||||
|
*/
|
||||||
|
virtual ale_real response(point p) const {
|
||||||
|
return _triangle(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
triangle(ale_pos half_width) {
|
||||||
|
this->half_width = half_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
||||||
52
d2/filter/zero.h
Normal file
52
d2/filter/zero.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __zero_h__
|
||||||
|
#define __zero_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A zero filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class zero : public filter {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of filter support, in number of half-cycles to each side of the
|
||||||
|
* filter center.
|
||||||
|
*/
|
||||||
|
ale_pos support() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int equals(const filter *f) const {
|
||||||
|
if (typeid(*f) == typeid(*this))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response of filter at point p
|
||||||
|
*/
|
||||||
|
virtual ale_real response(point p) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
27
d2/image.cc
Normal file
27
d2/image.cc
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2007 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See image.h for details on these variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
double image::resident = 0;
|
||||||
1120
d2/image.h
Normal file
1120
d2/image.h
Normal file
File diff suppressed because it is too large
Load Diff
420
d2/image_ale_real.h
Normal file
420
d2/image_ale_real.h
Normal file
@@ -0,0 +1,420 @@
|
|||||||
|
// Copyright 2002, 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_ale_real.h: Image represented by an array of ale_reals
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __image_ale_real_h__
|
||||||
|
#define __image_ale_real_h__
|
||||||
|
|
||||||
|
#include "exposure/exposure.h"
|
||||||
|
#include "point.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
#define RESIDENT_DIVISIONS 200
|
||||||
|
|
||||||
|
|
||||||
|
template <int disk_support>
|
||||||
|
class image_ale_real : public image {
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* Data structures without file support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
spixel *_p;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data structures for file support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE *support;
|
||||||
|
mutable spixel *_p_segments[RESIDENT_DIVISIONS];
|
||||||
|
mutable int dirty_segments[RESIDENT_DIVISIONS];
|
||||||
|
mutable int resident_list[RESIDENT_DIVISIONS];
|
||||||
|
mutable int resident_next;
|
||||||
|
int resident_max;
|
||||||
|
int rows_per_segment;
|
||||||
|
mutable thread::rwlock_t rwlock;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper encapsulating details of the separation between the
|
||||||
|
* resident-checking implementation and non-checking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static image *new_image_ale_real(unsigned int dimy,
|
||||||
|
unsigned int dimx,
|
||||||
|
unsigned int depth,
|
||||||
|
const char *name = "anonymous",
|
||||||
|
exposure *exp = NULL) {
|
||||||
|
|
||||||
|
double resident = image::get_resident();
|
||||||
|
|
||||||
|
if (resident == 0 || resident * 1000000 >= dimy * dimx)
|
||||||
|
return new image_ale_real<0>(dimy, dimx, depth, name, exp);
|
||||||
|
|
||||||
|
return new image_ale_real<1>(dimy, dimx, depth, name, exp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
image_ale_real (unsigned int dimy, unsigned int dimx, unsigned int
|
||||||
|
depth, const char *name = "anonymous", exposure *exp = NULL)
|
||||||
|
: image(dimy, dimx, depth, name, exp) {
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p = new spixel[dimx * dimy];
|
||||||
|
|
||||||
|
assert (_p);
|
||||||
|
|
||||||
|
if (!_p) {
|
||||||
|
fprintf(stderr, "Could not allocate memory for image data.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rows_per_segment = (int) ceil((double) dimy / (double) RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
assert (rows_per_segment > 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < RESIDENT_DIVISIONS; i++) {
|
||||||
|
_p_segments[i] = NULL;
|
||||||
|
dirty_segments[i] = 0;
|
||||||
|
resident_list[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
resident_max = (unsigned int) floor((image::get_resident() * 1000000)
|
||||||
|
/ (rows_per_segment * dimx));
|
||||||
|
|
||||||
|
assert (resident_max <= RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
if (resident_max == 0) {
|
||||||
|
ui::get()->error_hint(
|
||||||
|
"No segments resident in image array.",
|
||||||
|
"Try recompiling with more RESIDENT_DIVISIONS");
|
||||||
|
}
|
||||||
|
|
||||||
|
resident_next = 0;
|
||||||
|
|
||||||
|
support = tmpfile();
|
||||||
|
|
||||||
|
if (!support) {
|
||||||
|
ui::get()->error_hint(
|
||||||
|
"Unable to create temporary file to support image array.",
|
||||||
|
"Set --resident 0, or Win32/64 users might run as admin.");
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel *zero = new spixel[dimx];
|
||||||
|
|
||||||
|
assert(zero);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < dimy; i++) {
|
||||||
|
unsigned int c = fwrite(zero, sizeof(spixel), dimx, support);
|
||||||
|
if (c < dimx)
|
||||||
|
ui::get()->error_hint("Image array support file error.",
|
||||||
|
"Submit a bug report.");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~image_ale_real() {
|
||||||
|
if (disk_support == 0) {
|
||||||
|
delete[] _p;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < RESIDENT_DIVISIONS; i++) {
|
||||||
|
if (_p_segments[i])
|
||||||
|
delete[] _p_segments[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(support);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resident_begin(unsigned int segment) const {
|
||||||
|
rwlock.rdlock();
|
||||||
|
if (_p_segments[segment])
|
||||||
|
return;
|
||||||
|
rwlock.unlock();
|
||||||
|
|
||||||
|
rwlock.wrlock();
|
||||||
|
|
||||||
|
if (_p_segments[segment])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (resident_list[resident_next] >= 0) {
|
||||||
|
/*
|
||||||
|
* Eject a segment
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (dirty_segments[resident_list[resident_next]]) {
|
||||||
|
fseek(support, rows_per_segment * _dimx * sizeof(spixel)
|
||||||
|
* resident_list[resident_next],
|
||||||
|
SEEK_SET);
|
||||||
|
assert(_p_segments[resident_list[resident_next]]);
|
||||||
|
fwrite(_p_segments[resident_list[resident_next]],
|
||||||
|
sizeof(spixel), rows_per_segment * _dimx, support);
|
||||||
|
dirty_segments[resident_list[resident_next]] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] _p_segments[resident_list[resident_next]];
|
||||||
|
_p_segments[resident_list[resident_next]] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
resident_list[resident_next] = segment;
|
||||||
|
|
||||||
|
_p_segments[segment] = new spixel[_dimx * rows_per_segment];
|
||||||
|
|
||||||
|
assert (_p_segments[segment]);
|
||||||
|
|
||||||
|
fseek(support, rows_per_segment * _dimx * sizeof(spixel)
|
||||||
|
* segment,
|
||||||
|
SEEK_SET);
|
||||||
|
|
||||||
|
fread(_p_segments[segment], sizeof(spixel), rows_per_segment * _dimx, support);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the next ejection candidate.
|
||||||
|
*/
|
||||||
|
resident_next++;
|
||||||
|
if (resident_next >= resident_max)
|
||||||
|
resident_next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resident_end(unsigned int segment) const {
|
||||||
|
rwlock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel get_pixel(unsigned int y, unsigned int x) const {
|
||||||
|
assert (x < _dimx);
|
||||||
|
assert (y < _dimy);
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
return _p[y * _dimx + x];
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
spixel result = _p_segments[segment][(y % rows_per_segment) * _dimx + x];
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pixel(unsigned int y, unsigned int x, spixel p) {
|
||||||
|
assert (x < _dimx);
|
||||||
|
assert (y < _dimy);
|
||||||
|
|
||||||
|
image_updated();
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p[y * _dimx + x] = p;
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
_p_segments[segment][(y % rows_per_segment) * _dimx + x] = p;
|
||||||
|
dirty_segments[segment] = 1;
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mul_pixel(unsigned int y, unsigned int x, spixel p) {
|
||||||
|
assert (x < _dimx);
|
||||||
|
assert (y < _dimy);
|
||||||
|
|
||||||
|
image_updated();
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p[y * _dimx + x] *= p;
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
_p_segments[segment][(y % rows_per_segment) * _dimx + x] *= p;
|
||||||
|
dirty_segments[segment] = 1;
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_pixel(unsigned int y, unsigned int x, pixel p) {
|
||||||
|
assert (x < _dimx);
|
||||||
|
assert (y < _dimy);
|
||||||
|
|
||||||
|
image_updated();
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p[y * _dimx + x] += p;
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
_p_segments[segment][(y % rows_per_segment) * _dimx + x] += p;
|
||||||
|
dirty_segments[segment] = 1;
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_sreal get_chan(unsigned int y, unsigned int x, unsigned int k) const {
|
||||||
|
assert (x < _dimx);
|
||||||
|
assert (y < _dimy);
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
return _p[y * _dimx + x][k];
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
ale_sreal result = _p_segments[segment]
|
||||||
|
[(y % rows_per_segment) * _dimx + x][k];
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_chan(unsigned int y, unsigned int x, unsigned int k, ale_sreal c) {
|
||||||
|
assert (x < _dimx);
|
||||||
|
assert (y < _dimy);
|
||||||
|
|
||||||
|
image_updated();
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p[y * _dimx + x][k] = c;
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
_p_segments[segment][(y % rows_per_segment) * _dimx + x][k] = c;
|
||||||
|
dirty_segments[segment] = 1;
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void div_chan(unsigned int y, unsigned int x, unsigned int k, ale_sreal c) {
|
||||||
|
assert (x < _dimx);
|
||||||
|
assert (y < _dimy);
|
||||||
|
|
||||||
|
image_updated();
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p[y * _dimx + x][k] /= c;
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
_p_segments[segment][(y % rows_per_segment) * _dimx + x][k] /= c;
|
||||||
|
dirty_segments[segment] = 1;
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a new image suitable for receiving scaled values.
|
||||||
|
*/
|
||||||
|
virtual image *scale_generator(int height, int width, int depth, const char *name) const {
|
||||||
|
return new_image_ale_real(height, width, depth, name, _exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extend the image area to the top, bottom, left, and right,
|
||||||
|
* initializing the new image areas with black pixels. Negative values
|
||||||
|
* shrink the image.
|
||||||
|
*/
|
||||||
|
image *_extend(int top, int bottom, int left, int right) {
|
||||||
|
|
||||||
|
image *is = new_image_ale_real (
|
||||||
|
height() + top + bottom,
|
||||||
|
width() + left + right , depth(), name, _exp);
|
||||||
|
|
||||||
|
assert(is);
|
||||||
|
|
||||||
|
unsigned int min_i = (-top > 0)
|
||||||
|
? -top
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
unsigned int min_j = (-left > 0)
|
||||||
|
? -left
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
unsigned int max_i = (height() < is->height() - top)
|
||||||
|
? height()
|
||||||
|
: is->height() - top;
|
||||||
|
|
||||||
|
unsigned int max_j = (width() < is->width() - left)
|
||||||
|
? width()
|
||||||
|
: is->width() - left;
|
||||||
|
|
||||||
|
for (unsigned int i = min_i; i < max_i; i++)
|
||||||
|
for (unsigned int j = min_j; j < max_j; j++)
|
||||||
|
is->set_pixel(i + top, j + left, get_pixel(i, j));
|
||||||
|
|
||||||
|
is->set_offset(_offset[0] - top, _offset[1] - left);
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void trigger(pixel multiplier) {
|
||||||
|
for (unsigned int i = 0; i < height(); i++)
|
||||||
|
for (unsigned int j = 0; j < width(); j++) {
|
||||||
|
mul_pixel(i, j, multiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper encapsulating details of the separation between the
|
||||||
|
* resident-checking implementation and non-checking.
|
||||||
|
*/
|
||||||
|
static inline image *new_image_ale_real(unsigned int dimy,
|
||||||
|
unsigned int dimx,
|
||||||
|
unsigned int depth,
|
||||||
|
const char *name = "anonymous",
|
||||||
|
exposure *exp = NULL) {
|
||||||
|
|
||||||
|
return image_ale_real<0>::new_image_ale_real(dimy, dimx, depth, name, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
465
d2/image_bayer_ale_real.h
Normal file
465
d2/image_bayer_ale_real.h
Normal file
@@ -0,0 +1,465 @@
|
|||||||
|
// Copyright 2002, 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_bayer_ale_real.h: Bayer-patterned image represented by an array of ale_reals
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __image_bayer_ale_real_h__
|
||||||
|
#define __image_bayer_ale_real_h__
|
||||||
|
|
||||||
|
#include "exposure/exposure.h"
|
||||||
|
#include "point.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "image_ale_real.h"
|
||||||
|
|
||||||
|
template <int disk_support>
|
||||||
|
class image_bayer_ale_real : public image {
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* Data structures without file support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_sreal *_p;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data structures for file support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE *support;
|
||||||
|
mutable ale_sreal *_p_segments[RESIDENT_DIVISIONS];
|
||||||
|
mutable int dirty_segments[RESIDENT_DIVISIONS];
|
||||||
|
mutable int resident_list[RESIDENT_DIVISIONS];
|
||||||
|
mutable int resident_next;
|
||||||
|
int resident_max;
|
||||||
|
int rows_per_segment;
|
||||||
|
mutable thread::rwlock_t rwlock;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* X offset of 'R' element
|
||||||
|
*/
|
||||||
|
unsigned int r_x_offset() const {
|
||||||
|
return bayer & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Y offset of 'R' element
|
||||||
|
*/
|
||||||
|
unsigned int r_y_offset() const {
|
||||||
|
return (bayer & 0x2) >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* Return the color of a given pixel.
|
||||||
|
*/
|
||||||
|
unsigned int bayer_color(unsigned int i, unsigned int j) const {
|
||||||
|
return (i + r_y_offset()) % 2 + (j + r_x_offset()) % 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
char get_channels(int i, int j) const {
|
||||||
|
return (1 << bayer_color(i, j));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper encapsulating details of the separation between the
|
||||||
|
* resident-checking implementation and non-checking.
|
||||||
|
*/
|
||||||
|
static inline image *new_image_bayer_ale_real(unsigned int dimy,
|
||||||
|
unsigned int dimx,
|
||||||
|
unsigned int depth,
|
||||||
|
unsigned int bayer,
|
||||||
|
const char *name = "anonymous",
|
||||||
|
exposure *exp = NULL) {
|
||||||
|
|
||||||
|
unsigned int resident = image::get_resident();
|
||||||
|
|
||||||
|
if (resident == 0 || resident * 1000000 > dimy * dimx)
|
||||||
|
return new image_bayer_ale_real<0>(dimy, dimx, depth, bayer, name, exp);
|
||||||
|
|
||||||
|
return new image_bayer_ale_real<1>(dimy, dimx, depth, bayer, name, exp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
image_bayer_ale_real (unsigned int dimy, unsigned int dimx, unsigned int depth,
|
||||||
|
unsigned int bayer, const char *name = "anonymous", exposure *exp = NULL)
|
||||||
|
: image(dimy, dimx, depth, name, exp, bayer) {
|
||||||
|
|
||||||
|
assert (bayer == IMAGE_BAYER_BGRG
|
||||||
|
|| bayer == IMAGE_BAYER_GBGR
|
||||||
|
|| bayer == IMAGE_BAYER_GRGB
|
||||||
|
|| bayer == IMAGE_BAYER_RGBG);
|
||||||
|
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p = new ale_sreal[dimx * dimy];
|
||||||
|
|
||||||
|
assert (_p);
|
||||||
|
|
||||||
|
if (!_p) {
|
||||||
|
fprintf(stderr, "Could not allocate memory for image data.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < dimx * dimy; i++) {
|
||||||
|
_p[i] = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rows_per_segment = (int) ceil((double) dimy / (double) RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
assert (rows_per_segment > 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < RESIDENT_DIVISIONS; i++) {
|
||||||
|
_p_segments[i] = NULL;
|
||||||
|
dirty_segments[i] = 0;
|
||||||
|
resident_list[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
resident_max = (unsigned int) floor((image::get_resident() * 1000000)
|
||||||
|
/ (rows_per_segment * dimx));
|
||||||
|
|
||||||
|
assert (resident_max <= RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
if (resident_max == 0) {
|
||||||
|
ui::get()->error_hint(
|
||||||
|
"No segments resident in image array.",
|
||||||
|
"Try recompiling with more RESIDENT_DIVISIONS");
|
||||||
|
}
|
||||||
|
|
||||||
|
resident_next = 0;
|
||||||
|
|
||||||
|
support = tmpfile();
|
||||||
|
|
||||||
|
if (!support) {
|
||||||
|
ui::get()->error_hint(
|
||||||
|
"Unable to create temporary file to support image array.",
|
||||||
|
"Set --resident 0, or Win32/64 users might run as admin.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_sreal *zero = new ale_sreal[dimx];
|
||||||
|
|
||||||
|
assert(zero);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < dimx; i++)
|
||||||
|
zero[i] = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < dimy; i++) {
|
||||||
|
unsigned int c = fwrite(zero, sizeof(ale_sreal), dimx, support);
|
||||||
|
if (c < dimx)
|
||||||
|
ui::get()->error_hint("Image array support file error.",
|
||||||
|
"Submit a bug report.");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~image_bayer_ale_real() {
|
||||||
|
if (disk_support == 0) {
|
||||||
|
delete[] _p;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < RESIDENT_DIVISIONS; i++) {
|
||||||
|
if (_p_segments[i])
|
||||||
|
delete[] _p_segments[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(support);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resident_begin(unsigned int segment) const {
|
||||||
|
rwlock.rdlock();
|
||||||
|
if (_p_segments[segment])
|
||||||
|
return;
|
||||||
|
rwlock.unlock();
|
||||||
|
|
||||||
|
rwlock.wrlock();
|
||||||
|
|
||||||
|
if (_p_segments[segment])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (resident_list[resident_next] >= 0) {
|
||||||
|
/*
|
||||||
|
* Eject a segment
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (dirty_segments[resident_list[resident_next]]) {
|
||||||
|
fseek(support, rows_per_segment * _dimx * sizeof(ale_sreal)
|
||||||
|
* resident_list[resident_next],
|
||||||
|
SEEK_SET);
|
||||||
|
assert(_p_segments[resident_list[resident_next]]);
|
||||||
|
fwrite(_p_segments[resident_list[resident_next]],
|
||||||
|
sizeof(ale_sreal), rows_per_segment * _dimx, support);
|
||||||
|
dirty_segments[resident_list[resident_next]] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] _p_segments[resident_list[resident_next]];
|
||||||
|
_p_segments[resident_list[resident_next]] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
resident_list[resident_next] = segment;
|
||||||
|
|
||||||
|
_p_segments[segment] = new ale_sreal[_dimx * rows_per_segment];
|
||||||
|
|
||||||
|
assert (_p_segments[segment]);
|
||||||
|
|
||||||
|
fseek(support, rows_per_segment * _dimx * sizeof(ale_sreal)
|
||||||
|
* segment,
|
||||||
|
SEEK_SET);
|
||||||
|
|
||||||
|
fread(_p_segments[segment], sizeof(ale_sreal), rows_per_segment * _dimx, support);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the next ejection candidate.
|
||||||
|
*/
|
||||||
|
resident_next++;
|
||||||
|
if (resident_next >= resident_max)
|
||||||
|
resident_next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resident_end(unsigned int segment) const {
|
||||||
|
rwlock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_chan(unsigned int y, unsigned int x, unsigned int k, ale_sreal c) {
|
||||||
|
assert (k == bayer_color(y, x));
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p[y * _dimx + x] = c;
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
_p_segments[segment][(y % rows_per_segment) * _dimx + x] = c;
|
||||||
|
dirty_segments[segment] = 1;
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_chan(unsigned int y, unsigned int x, unsigned int k, ale_sreal c) {
|
||||||
|
assert (k == bayer_color(y, x));
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p[y * _dimx + x] += c;
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
_p_segments[segment][(y % rows_per_segment) * _dimx + x] += c;
|
||||||
|
dirty_segments[segment] = 1;
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void div_chan(unsigned int y, unsigned int x, unsigned int k, ale_sreal c) {
|
||||||
|
assert (k == bayer_color(y, x));
|
||||||
|
if (disk_support == 0) {
|
||||||
|
_p[y * _dimx + x] /= c;
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
_p_segments[segment][(y % rows_per_segment) * _dimx + x] /= c;
|
||||||
|
dirty_segments[segment] = 1;
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_sreal get_chan(unsigned int y, unsigned int x, unsigned int k) const {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This may be expensive.
|
||||||
|
*/
|
||||||
|
assert (k == bayer_color(y, x));
|
||||||
|
#endif
|
||||||
|
if (disk_support == 0) {
|
||||||
|
return _p[y * _dimx + x];
|
||||||
|
} else {
|
||||||
|
int segment = y / rows_per_segment;
|
||||||
|
assert (segment < RESIDENT_DIVISIONS);
|
||||||
|
|
||||||
|
resident_begin(segment);
|
||||||
|
|
||||||
|
ale_sreal result = _p_segments[segment]
|
||||||
|
[(y % rows_per_segment) * _dimx + x];
|
||||||
|
|
||||||
|
resident_end(segment);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method throws away data not stored at this pixel
|
||||||
|
* position.
|
||||||
|
*/
|
||||||
|
void set_pixel(unsigned int y, unsigned int x, spixel p) {
|
||||||
|
set_chan(y, x, bayer_color(y, x), p[bayer_color(y, x)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method uses bilinear interpolation.
|
||||||
|
*/
|
||||||
|
spixel get_pixel(unsigned int y, unsigned int x) const {
|
||||||
|
pixel result;
|
||||||
|
unsigned int k = bayer_color(y, x);
|
||||||
|
ale_real sum;
|
||||||
|
unsigned int num;
|
||||||
|
|
||||||
|
result[k] = get_chan(y, x, k);
|
||||||
|
|
||||||
|
if (k == 1) {
|
||||||
|
unsigned int k1 = bayer_color(y + 1, x);
|
||||||
|
unsigned int k2 = 2 - k1;
|
||||||
|
|
||||||
|
sum = 0; num = 0;
|
||||||
|
if (y > 0) {
|
||||||
|
sum += get_chan(y - 1, x, k1);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (y < _dimy - 1) {
|
||||||
|
sum += get_chan(y + 1, x, k1);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
assert (num > 0);
|
||||||
|
result[k1] = sum / num;
|
||||||
|
|
||||||
|
sum = 0; num = 0;
|
||||||
|
if (x > 0) {
|
||||||
|
sum += get_chan(y, x - 1, k2);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (x < _dimx - 1) {
|
||||||
|
sum += get_chan(y, x + 1, k2);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
assert (num > 0);
|
||||||
|
result[k2] = sum / num;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
sum = 0; num = 0;
|
||||||
|
if (y > 0) {
|
||||||
|
sum += get_chan(y - 1, x, 1);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (x > 0) {
|
||||||
|
sum += get_chan(y, x - 1, 1);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (y < _dimy - 1) {
|
||||||
|
sum += get_chan(y + 1, x, 1);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (x < _dimx - 1) {
|
||||||
|
sum += get_chan(y, x + 1, 1);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
assert (num > 0);
|
||||||
|
result[1] = sum / num;
|
||||||
|
|
||||||
|
sum = 0; num = 0;
|
||||||
|
if (y > 0 && x > 0) {
|
||||||
|
sum += get_chan(y - 1, x - 1, 2 - k);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (y > 0 && x < _dimx - 1) {
|
||||||
|
sum += get_chan(y - 1, x + 1, 2 - k);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (y < _dimy - 1 && x > 0) {
|
||||||
|
sum += get_chan(y + 1, x - 1, 2 - k);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (y < _dimy - 1 && x < _dimx - 1) {
|
||||||
|
sum += get_chan(y + 1, x + 1, 2 - k);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
result[2 - k] = sum/num;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel get_raw_pixel(unsigned int y, unsigned int x) const {
|
||||||
|
pixel result;
|
||||||
|
int k = bayer_color(y, x);
|
||||||
|
|
||||||
|
result[k] = get_chan(y, x, k);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a new image suitable for receiving scaled values.
|
||||||
|
*/
|
||||||
|
virtual image *scale_generator(int height, int width, int depth, const char *name) const {
|
||||||
|
return new_image_ale_real(height, width, depth, name, _exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extend the image area to the top, bottom, left, and right,
|
||||||
|
* initializing the new image areas with black pixels.
|
||||||
|
*/
|
||||||
|
image *_extend(int top, int bottom, int left, int right) {
|
||||||
|
/*
|
||||||
|
* Bayer-patterned images should always represent inputs,
|
||||||
|
* which should not ever be extended.
|
||||||
|
*/
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void trigger(pixel multiplier) {
|
||||||
|
for (unsigned int i = 0; i < _dimy; i++)
|
||||||
|
for (unsigned int j = 0; j < _dimx; j++) {
|
||||||
|
unsigned int k = bayer_color(i, j);
|
||||||
|
set_chan(i, j, k, get_chan(i, j, k) * multiplier[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper encapsulating details of the separation between the
|
||||||
|
* resident-checking implementation and non-checking.
|
||||||
|
*/
|
||||||
|
static inline image *new_image_bayer_ale_real(unsigned int dimy,
|
||||||
|
unsigned int dimx,
|
||||||
|
unsigned int depth,
|
||||||
|
unsigned int bayer,
|
||||||
|
const char *name = "anonymous",
|
||||||
|
exposure *exp = NULL) {
|
||||||
|
|
||||||
|
return image_bayer_ale_real<0>::new_image_bayer_ale_real(dimy, dimx, depth, bayer, name, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
49
d2/image_rw.cc
Normal file
49
d2/image_rw.cc
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "image_rw.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See image_rw.h for details on these variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int image_rw::ppm_type = 0;
|
||||||
|
|
||||||
|
unsigned int image_rw::mcv = 65535;
|
||||||
|
|
||||||
|
unsigned int image_rw::file_count = 0;
|
||||||
|
const char *image_rw::output_filename = NULL;
|
||||||
|
const char **image_rw::filenames = NULL;
|
||||||
|
const image **image_rw::images = NULL;
|
||||||
|
int *image_rw::files_open;
|
||||||
|
|
||||||
|
int image_rw::latest_close_num = -1;
|
||||||
|
|
||||||
|
double image_rw::cache_size = 0;
|
||||||
|
double image_rw::cache_size_max = 256;
|
||||||
|
unsigned int image_rw::cache_count = 0;
|
||||||
|
|
||||||
|
double image_rw::nn_defined_radius = 0;
|
||||||
|
|
||||||
|
exposure **image_rw::input_exposure = NULL;
|
||||||
|
exposure *image_rw::output_exposure = NULL;
|
||||||
|
unsigned int image_rw::bayer_default = 0;
|
||||||
|
unsigned int *image_rw::bayer_specific = NULL;
|
||||||
|
int image_rw::exposure_scale = 0;
|
||||||
647
d2/image_rw.h
Normal file
647
d2/image_rw.h
Normal file
@@ -0,0 +1,647 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_rw.h: Read and write images.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __image_rw_h__
|
||||||
|
#define __image_rw_h__
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
#include "image_ale_real.h"
|
||||||
|
#include "image_bayer_ale_real.h"
|
||||||
|
#include "ppm.h"
|
||||||
|
#include "exposure/exposure.h"
|
||||||
|
#include "exposure/exposure_default.h"
|
||||||
|
|
||||||
|
class image_rw {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private data members
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PPM type
|
||||||
|
*
|
||||||
|
* 0 = No type selected
|
||||||
|
* 1 = PPM Raw
|
||||||
|
* 2 = PPM Plain
|
||||||
|
*/
|
||||||
|
static int ppm_type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bit depth
|
||||||
|
*/
|
||||||
|
static unsigned int mcv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nearest-neighbor defined value radius.
|
||||||
|
*/
|
||||||
|
static double nn_defined_radius;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input and output exposure models
|
||||||
|
*/
|
||||||
|
static exposure **input_exposure;
|
||||||
|
static exposure *output_exposure;
|
||||||
|
static int exposure_scale;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default bayer pattern
|
||||||
|
*/
|
||||||
|
static unsigned int bayer_default;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Image-specific bayer patterns.
|
||||||
|
*/
|
||||||
|
static unsigned int *bayer_specific;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pointer to the output filename
|
||||||
|
*/
|
||||||
|
static const char *output_filename;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variables relating to input image files and image data structures.
|
||||||
|
*/
|
||||||
|
static const char **filenames;
|
||||||
|
static unsigned int file_count;
|
||||||
|
static const image **images;
|
||||||
|
static int *files_open;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The most recently closed image number.
|
||||||
|
*/
|
||||||
|
static int latest_close_num;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum cache size, in megabytes (2^20 * bytes), for images not most
|
||||||
|
* recently closed.
|
||||||
|
*/
|
||||||
|
static double cache_size_max;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actual cache size.
|
||||||
|
*/
|
||||||
|
static double cache_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of cached files.
|
||||||
|
*/
|
||||||
|
static unsigned int cache_count;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private methods to init and shut down the file reader.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the image file handler
|
||||||
|
*/
|
||||||
|
static void init_image() {
|
||||||
|
#ifdef USE_MAGICK
|
||||||
|
InitializeMagick("ale");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy the image file handler
|
||||||
|
*/
|
||||||
|
static void destroy_image() {
|
||||||
|
#ifdef USE_MAGICK
|
||||||
|
DestroyMagick();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methods to read and write image files
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read an image from a file
|
||||||
|
*/
|
||||||
|
static image *read_image(const char *filename, exposure *exp, const char *name = "file",
|
||||||
|
unsigned int bayer = IMAGE_BAYER_DEFAULT, int init_reference_gain = 0) {
|
||||||
|
|
||||||
|
static int warned = 0;
|
||||||
|
|
||||||
|
if (bayer == IMAGE_BAYER_DEFAULT)
|
||||||
|
bayer = bayer_default;
|
||||||
|
|
||||||
|
if (is_eppm(filename)) {
|
||||||
|
return read_ppm(filename, exp, bayer, init_reference_gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_MAGICK
|
||||||
|
|
||||||
|
if (MaxRGB < 65535 && mcv == 65535 && !warned) {
|
||||||
|
fprintf(stderr, "\n\n*** Warning: " MagickPackageName " has not been compiled with 16 bit support.\n");
|
||||||
|
fprintf(stderr, "*** Reading input using 8 bits per channel.\n");
|
||||||
|
fprintf(stderr, "*** \n");
|
||||||
|
fprintf(stderr, "*** (To silence this warning, specify option --8bpc)\n\n\n");
|
||||||
|
|
||||||
|
warned = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Patterned after http://www.imagemagick.org/www/api.html
|
||||||
|
* and http://www.imagemagick.org/www/smile.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
ExceptionInfo exception;
|
||||||
|
Image *mi;
|
||||||
|
ImageInfo *image_info;
|
||||||
|
image *im;
|
||||||
|
const PixelPacket *p;
|
||||||
|
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
ale_real black_level = exp->get_black_level();
|
||||||
|
|
||||||
|
GetExceptionInfo(&exception);
|
||||||
|
image_info = CloneImageInfo((ImageInfo *) NULL);
|
||||||
|
|
||||||
|
strncpy(image_info->filename, filename, MaxTextExtent);
|
||||||
|
mi = ReadImage(image_info, &exception);
|
||||||
|
if (exception.severity != UndefinedException) {
|
||||||
|
fprintf(stderr, "\n\n");
|
||||||
|
CatchException(&exception);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
if (mi == (Image *) NULL)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
if (bayer == IMAGE_BAYER_NONE)
|
||||||
|
im = new_image_ale_real(mi->rows, mi->columns, 3, name, exp);
|
||||||
|
else
|
||||||
|
im = new_image_bayer_ale_real(mi->rows, mi->columns, 3, bayer, name, exp);
|
||||||
|
|
||||||
|
for (i = 0; i < mi->rows; i++) {
|
||||||
|
p = AcquireImagePixels(mi, 0, i, mi->columns, 1, &exception);
|
||||||
|
|
||||||
|
if (exception.severity != UndefinedException)
|
||||||
|
CatchException(&exception);
|
||||||
|
if (p == NULL)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
for (j = 0; j < mi->columns; j++) {
|
||||||
|
|
||||||
|
pixel input ( ale_real_from_int(p->red, MaxRGB),
|
||||||
|
ale_real_from_int(p->green, MaxRGB),
|
||||||
|
ale_real_from_int(p->blue, MaxRGB) );
|
||||||
|
|
||||||
|
pixel linear_input = (exp->linearize(input) - exp->get_multiplier() * black_level)
|
||||||
|
/ (1 - black_level);
|
||||||
|
|
||||||
|
im->set_pixel(i, j, linear_input);
|
||||||
|
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyImage(mi);
|
||||||
|
DestroyImageInfo(image_info);
|
||||||
|
|
||||||
|
return im;
|
||||||
|
#else
|
||||||
|
return read_ppm(filename, exp, bayer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializer.
|
||||||
|
*
|
||||||
|
* Handle FILE_COUNT input files with names in array FILENAMES and
|
||||||
|
* output file OUTPUT_FILENAME. FILENAMES should be an array of char *
|
||||||
|
* that is never freed. OUTPUT_FILENAME should be a char * that is
|
||||||
|
* never freed.
|
||||||
|
*
|
||||||
|
* INPUT_EXPOSURE should be an array of FILE_COUNT exposure objects
|
||||||
|
* that is never freed. OUTPUT_EXPOSURE should be an exposure * that
|
||||||
|
* is never freed.
|
||||||
|
*/
|
||||||
|
static void init(unsigned int _file_count, const char **_filenames,
|
||||||
|
const char *_output_filename, exposure **_input_exposure,
|
||||||
|
exposure *_output_exposure){
|
||||||
|
assert (_file_count > 0);
|
||||||
|
|
||||||
|
init_image();
|
||||||
|
|
||||||
|
filenames = _filenames;
|
||||||
|
file_count = _file_count;
|
||||||
|
output_filename = _output_filename;
|
||||||
|
input_exposure = _input_exposure;
|
||||||
|
output_exposure = _output_exposure;
|
||||||
|
|
||||||
|
images = (const image **)malloc(file_count * sizeof(image *));
|
||||||
|
bayer_specific = (unsigned int *)malloc(file_count * sizeof(unsigned int));
|
||||||
|
files_open = (int *)calloc(file_count, sizeof(int));
|
||||||
|
|
||||||
|
assert (images);
|
||||||
|
assert (bayer_specific);
|
||||||
|
assert (files_open);
|
||||||
|
|
||||||
|
if (!images || !files_open || !bayer_specific) {
|
||||||
|
fprintf(stderr, "Unable to allocate memory for images.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < file_count; i++)
|
||||||
|
bayer_specific[i] = IMAGE_BAYER_DEFAULT;
|
||||||
|
|
||||||
|
ui::get()->identify_output(output_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppm_plain() {
|
||||||
|
ppm_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppm_raw() {
|
||||||
|
ppm_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppm_auto() {
|
||||||
|
#ifdef USE_MAGICK
|
||||||
|
ppm_type = 0;
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "\n\n*** Error: --auto flag not supported on this build. ***\n"
|
||||||
|
"*** (Hint: Rebuild with IMAGEMAGICK=1) ***\n\n");
|
||||||
|
exit(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_default_bayer(unsigned int b) {
|
||||||
|
bayer_default = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_specific_bayer(unsigned int index, unsigned int b) {
|
||||||
|
assert (bayer_specific);
|
||||||
|
bayer_specific[index] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void depth16() {
|
||||||
|
mcv = 65535;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void depth8() {
|
||||||
|
mcv = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_cache(double size) {
|
||||||
|
cache_size_max = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy() {
|
||||||
|
assert (file_count > 0);
|
||||||
|
destroy_image();
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int count() {
|
||||||
|
assert (file_count > 0);
|
||||||
|
return file_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *name(unsigned int image) {
|
||||||
|
assert (image < file_count);
|
||||||
|
|
||||||
|
return filenames[image];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void def_nn(double _nn) {
|
||||||
|
nn_defined_radius = _nn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *output_name() {
|
||||||
|
assert (file_count > 0);
|
||||||
|
return output_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write an image to a file
|
||||||
|
*/
|
||||||
|
static void write_image(const char *filename, const image *im, exposure *exp = output_exposure, int rezero = 0, int exp_scale_override = 0) {
|
||||||
|
static int warned = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle ALE-specific magical filenames.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!strcmp(filename, "dump:")) {
|
||||||
|
fprintf(stderr, "Image dump: ");
|
||||||
|
for (unsigned int i = 0; i < im->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < im->width(); j++) {
|
||||||
|
pixel p = im->get_pixel(i, j);
|
||||||
|
fprintf(stderr, "(%d, %d): [%f %f %f] ", i, j, (double) p[0], (double) p[1], (double) p[2]);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_MAGICK
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Patterned after http://www.imagemagick.org/www/api.html
|
||||||
|
* and http://www.imagemagick.org/www/smile.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
ExceptionInfo exception;
|
||||||
|
Image *mi;
|
||||||
|
ImageInfo *image_info;
|
||||||
|
PixelPacket *p;
|
||||||
|
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
GetExceptionInfo(&exception);
|
||||||
|
image_info = CloneImageInfo((ImageInfo *) NULL);
|
||||||
|
strncpy(image_info->filename, filename, MaxTextExtent);
|
||||||
|
|
||||||
|
mi = AllocateImage(image_info);
|
||||||
|
if (mi == (Image *) NULL)
|
||||||
|
MagickError(ResourceLimitError,
|
||||||
|
"Unable to display image", "MemoryAllocationFailed");
|
||||||
|
|
||||||
|
mi->columns = im->width();
|
||||||
|
mi->rows = im->height();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the output image depth
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (MaxRGB < 65535 || mcv < 65535)
|
||||||
|
mi->depth = 8;
|
||||||
|
else
|
||||||
|
mi->depth = 16;
|
||||||
|
|
||||||
|
if (MaxRGB < 65535 && mcv == 65535 && !warned) {
|
||||||
|
fprintf(stderr, "\n\n*** Warning: " MagickPackageName " has not been compiled with 16 bit support.\n");
|
||||||
|
fprintf(stderr, "*** Writing output using 8 bits per channel.\n");
|
||||||
|
fprintf(stderr, "*** \n");
|
||||||
|
fprintf(stderr, "*** (To silence this warning, specify option --8bpc)\n\n\n");
|
||||||
|
|
||||||
|
warned = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set compression type
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ppm_type == 2) {
|
||||||
|
mi->compression = NoCompression;
|
||||||
|
image_info->compression = NoCompression;
|
||||||
|
strncpy(mi->magick, "PNM", MaxTextExtent);
|
||||||
|
strncpy(image_info->magick, "PNM", MaxTextExtent);
|
||||||
|
} else if (ppm_type == 1) {
|
||||||
|
strncpy(mi->magick, "PNM", MaxTextExtent);
|
||||||
|
strncpy(image_info->magick, "PNM", MaxTextExtent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Automatic exposure adjustment (don't blow out highlights)
|
||||||
|
*/
|
||||||
|
ale_real maxval = 1;
|
||||||
|
ale_real minval = (rezero ? im->minval() : (ale_real) 0);
|
||||||
|
if (minval > 0)
|
||||||
|
minval = 0;
|
||||||
|
pixel minval_pixel(minval, minval, minval);
|
||||||
|
|
||||||
|
|
||||||
|
if (exposure_scale || exp_scale_override) {
|
||||||
|
ale_real new_maxval = im->maxval();
|
||||||
|
|
||||||
|
if (new_maxval > maxval)
|
||||||
|
maxval = new_maxval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the image
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (i = 0; i < mi->rows; i++) {
|
||||||
|
p = SetImagePixels(mi, 0, i, mi->columns, 1);
|
||||||
|
if (p == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (j = 0; j < mi->columns; j++) {
|
||||||
|
|
||||||
|
pixel value = im->get_pixel(i, j);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get nearest-neighbor defined values.
|
||||||
|
*
|
||||||
|
* XXX: While this implementation is correct, it is inefficient
|
||||||
|
* for large radii. A better implementation would search
|
||||||
|
* perimeters of squares of ever-increasing radius, tracking
|
||||||
|
* the best-so-far data until the square perimeter exceeded the
|
||||||
|
* best-so-far radius.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
if (isnan(value[k]))
|
||||||
|
for (int radius = 1; radius <= nn_defined_radius; radius++) {
|
||||||
|
double nearest_radius_squared = (radius + 1) * (radius + 1);
|
||||||
|
for (int ii = -radius; ii <= radius; ii++)
|
||||||
|
for (int jj = -radius; jj <= radius; jj++) {
|
||||||
|
if (!im->in_bounds(point(i + ii, j + jj)))
|
||||||
|
continue;
|
||||||
|
if (ii * ii + jj * jj < nearest_radius_squared
|
||||||
|
&& finite(im->get_pixel(i + ii, j + jj)[k])) {
|
||||||
|
value[k] = im->get_pixel(i + ii, j + jj)[k];
|
||||||
|
nearest_radius_squared = ii * ii + jj * jj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nearest_radius_squared < (radius + 1) * (radius + 1))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unlinearize
|
||||||
|
*/
|
||||||
|
|
||||||
|
pixel unlinearized(exp->unlinearize((value - minval_pixel)
|
||||||
|
/ (maxval - minval)));
|
||||||
|
|
||||||
|
unlinearized = unlinearized.clamp();
|
||||||
|
|
||||||
|
p->red = (Quantum) ale_real_to_int(unlinearized[0], MaxRGB);
|
||||||
|
p->green = (Quantum) ale_real_to_int(unlinearized[1], MaxRGB);
|
||||||
|
p->blue = (Quantum) ale_real_to_int(unlinearized[2], MaxRGB);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SyncImagePixels(mi))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WriteImage(image_info, mi)) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perhaps file type was unknown? Set to PNM by default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
strncpy(mi->magick, "PNM", MaxTextExtent);
|
||||||
|
strncpy(image_info->magick, "PNM", MaxTextExtent);
|
||||||
|
|
||||||
|
if (!WriteImage(image_info, mi)) {
|
||||||
|
fprintf(stderr, "\n\n");
|
||||||
|
CatchException(&mi->exception);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyImage(mi);
|
||||||
|
DestroyImageInfo(image_info);
|
||||||
|
#else
|
||||||
|
write_ppm(filename, im, exp, mcv, ppm_type == 2, rezero, exposure_scale || exp_scale_override,
|
||||||
|
nn_defined_radius);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output(const image *i) {
|
||||||
|
assert (file_count > 0);
|
||||||
|
write_image(output_name(), i, output_exposure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vise_write(const char *p, const char *s, const image *i) {
|
||||||
|
static int count = 0;
|
||||||
|
int length = strlen(p) + strlen(s) + 8;
|
||||||
|
char *output_string = (char *) malloc(length * sizeof(char));
|
||||||
|
|
||||||
|
snprintf(output_string, length, "%s%08d%s", p, count, s);
|
||||||
|
|
||||||
|
write_image(output_string, i, output_exposure);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static exposure &exp(int n) {
|
||||||
|
return *input_exposure[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const exposure &const_exp(int n) {
|
||||||
|
return *input_exposure[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
static exposure &exp() {
|
||||||
|
return *output_exposure;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exp_scale() {
|
||||||
|
exposure_scale = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exp_noscale() {
|
||||||
|
exposure_scale = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const exposure &const_exp() {
|
||||||
|
return *output_exposure;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned int bayer(unsigned int n) {
|
||||||
|
if (bayer_specific[n] == IMAGE_BAYER_DEFAULT)
|
||||||
|
return bayer_default;
|
||||||
|
else
|
||||||
|
return bayer_specific[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const image *open(unsigned int n) {
|
||||||
|
assert (n < file_count);
|
||||||
|
assert (!files_open[n]);
|
||||||
|
|
||||||
|
files_open[n] = 1;
|
||||||
|
|
||||||
|
if (latest_close_num >= 0 && n == (unsigned int) latest_close_num) {
|
||||||
|
latest_close_num = -1;
|
||||||
|
return images[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n < cache_count)
|
||||||
|
return images[n];
|
||||||
|
|
||||||
|
ui::get()->loading_file();
|
||||||
|
image *i = read_image(filenames[n], input_exposure[n], "file", bayer(n), (n == 0));
|
||||||
|
|
||||||
|
images[n] = i;
|
||||||
|
|
||||||
|
return images[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void open_all() {
|
||||||
|
for (unsigned int n = 0; n < file_count; n++)
|
||||||
|
open(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const image *get_open(unsigned int n) {
|
||||||
|
assert (files_open[n]);
|
||||||
|
return images[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
static image *copy(unsigned int n, const char *name) {
|
||||||
|
assert (n < file_count);
|
||||||
|
|
||||||
|
if (files_open[n])
|
||||||
|
return images[n]->clone(name);
|
||||||
|
else {
|
||||||
|
image *i = read_image(filenames[n], input_exposure[n], name, bayer(n), (n == 0));
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close(unsigned int image) {
|
||||||
|
assert (image < file_count);
|
||||||
|
assert (files_open[image]);
|
||||||
|
|
||||||
|
files_open[image] = 0;
|
||||||
|
|
||||||
|
if (image < cache_count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (image == cache_count) {
|
||||||
|
double image_size = ((double) images[image]->storage_size()) / pow(2, 20);
|
||||||
|
|
||||||
|
if (image_size + cache_size < cache_size_max) {
|
||||||
|
cache_size += image_size;
|
||||||
|
cache_count++;
|
||||||
|
ui::get()->cache(cache_size, cache_size_max);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ui::get()->cache_status(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (latest_close_num >= 0)
|
||||||
|
delete images[latest_close_num];
|
||||||
|
|
||||||
|
latest_close_num = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_all() {
|
||||||
|
for (unsigned int n = 0; n < file_count; n++)
|
||||||
|
close(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
97
d2/image_weighted_avg.h
Normal file
97
d2/image_weighted_avg.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2002, 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_weighted_avg.h: Image representing a weighted average of inputs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __image_weighted_avg_h__
|
||||||
|
#define __image_weighted_avg_h__
|
||||||
|
|
||||||
|
#include "image_ale_real.h"
|
||||||
|
#include "exposure/exposure.h"
|
||||||
|
#include "point.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
class image_weighted_avg : public image {
|
||||||
|
private:
|
||||||
|
void trigger(pixel multiplier) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
image_weighted_avg (unsigned int dimy, unsigned int dimx, unsigned int
|
||||||
|
depth, const char *name = "anonymous")
|
||||||
|
: image(dimy, dimx, depth, name, NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~image_weighted_avg() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pixel(unsigned int y, unsigned int x, spixel p) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel get_pixel(unsigned int y, unsigned int x) const {
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
return spixel(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_chan(unsigned int y, unsigned int x, unsigned int k, ale_sreal c) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_sreal get_chan(unsigned int y, unsigned int x, unsigned int k) const {
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a new image suitable for receiving scaled values.
|
||||||
|
*/
|
||||||
|
virtual image *scale_generator(int height, int width, int depth, const char *name) const {
|
||||||
|
return new_image_ale_real(height, width, depth, name, _exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pre-transformation check for whether an area should be skipped.
|
||||||
|
* Takes image weights as an argument.
|
||||||
|
*/
|
||||||
|
virtual int accumulate_norender(int i, int j) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Accumulate pixels
|
||||||
|
*/
|
||||||
|
virtual void accumulate(int i, int j, int f, pixel new_value, pixel new_weight) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get color map
|
||||||
|
*/
|
||||||
|
virtual image *get_colors() = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get weight map
|
||||||
|
*/
|
||||||
|
virtual image *get_weights() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
248
d2/image_weighted_median.h
Normal file
248
d2/image_weighted_median.h
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
// Copyright 2002, 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_weighted_median.h: Image representing a weighted median of inputs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __image_weighted_median_h__
|
||||||
|
#define __image_weighted_median_h__
|
||||||
|
|
||||||
|
#include "exposure/exposure.h"
|
||||||
|
#include "point.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
class image_weighted_median : public image_weighted_avg {
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Array 'colors' stores image colors, sorted by intensity for each
|
||||||
|
* channel at each pixel location.
|
||||||
|
*
|
||||||
|
* Array 'weights' stores the weights associated with each color, where
|
||||||
|
* the weights are represented cumulatively, so that for weights and
|
||||||
|
* intensities:
|
||||||
|
*
|
||||||
|
* Color: 1 2 3 6 7
|
||||||
|
* Weight: 2 2 1 1 1
|
||||||
|
*
|
||||||
|
* The (cumulative) representation would be:
|
||||||
|
*
|
||||||
|
* Color: 1 2 3 6 7
|
||||||
|
* Weight: 2 4 5 6 7
|
||||||
|
*
|
||||||
|
* XXX: This storage approach may have poor cache characteristics.
|
||||||
|
* It might be better to localize elements having identical spatial
|
||||||
|
* coordinates.
|
||||||
|
*/
|
||||||
|
image **colors;
|
||||||
|
image **weights;
|
||||||
|
unsigned int capacity;
|
||||||
|
|
||||||
|
public:
|
||||||
|
image_weighted_median (unsigned int dimy, unsigned int dimx, unsigned int
|
||||||
|
depth, int capacity = -1, const char *name = "anonymous")
|
||||||
|
: image_weighted_avg(dimy, dimx, depth, name) {
|
||||||
|
|
||||||
|
if (capacity == -1) {
|
||||||
|
this->capacity = image_rw::count();
|
||||||
|
} else if (capacity >= 0) {
|
||||||
|
this->capacity = (unsigned int) capacity;
|
||||||
|
} else
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
colors = (image **) malloc(this->capacity * sizeof(image *));
|
||||||
|
weights = (image **) malloc(this->capacity * sizeof(image *));
|
||||||
|
|
||||||
|
assert(colors);
|
||||||
|
assert(weights);
|
||||||
|
|
||||||
|
if (!colors || !weights) {
|
||||||
|
fprintf(stderr, "Could not allocate memory for image data.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int f = 0; f < this->capacity; f++) {
|
||||||
|
colors[f] = new_image_ale_real(dimy, dimx, depth);
|
||||||
|
weights[f] = new_image_ale_real(dimy, dimx, depth);
|
||||||
|
|
||||||
|
assert(colors[f]);
|
||||||
|
assert(weights[f]);
|
||||||
|
|
||||||
|
if (!colors[f] || !weights[f]) {
|
||||||
|
fprintf(stderr, "Could not allocate memory for image data.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~image_weighted_median() {
|
||||||
|
for (unsigned int f = 0; f < capacity; f++) {
|
||||||
|
delete colors[f];
|
||||||
|
delete weights[f];
|
||||||
|
}
|
||||||
|
|
||||||
|
free(colors);
|
||||||
|
free(weights);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extend the image area to the top, bottom, left, and right,
|
||||||
|
* initializing the new image areas with black pixels. Negative values
|
||||||
|
* shrink the image.
|
||||||
|
*/
|
||||||
|
image *_extend(int top, int bottom, int left, int right) {
|
||||||
|
|
||||||
|
for (unsigned int f = 0; f < capacity; f++) {
|
||||||
|
extend(&colors[f], top, bottom, left, right);
|
||||||
|
extend(&weights[f], top, bottom, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
_dimx = colors[0]->width();
|
||||||
|
_dimy = colors[0]->height();
|
||||||
|
_offset = colors[0]->offset();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int accumulate_norender(int i, int j) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform insertion sort on the arrays, where sort is by color.
|
||||||
|
*
|
||||||
|
* XXX: This does a poor job of handling multiple contributions from
|
||||||
|
* the same frame, especially when the number of frames is 1.
|
||||||
|
*/
|
||||||
|
void accumulate(int i, int j, int f, pixel new_value, pixel new_weight) {
|
||||||
|
for (unsigned int k = 0; k < 3; k++) {
|
||||||
|
|
||||||
|
if (fabs(new_weight[k]) > ale_real_weight_floor)
|
||||||
|
new_value[k] /= new_weight[k];
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: This initialization should not be necessary.
|
||||||
|
*/
|
||||||
|
if (f == 0)
|
||||||
|
for (unsigned int ff = 0; ff < capacity; ff++)
|
||||||
|
weights[ff]->set_chan(i, j, k, 0);
|
||||||
|
|
||||||
|
assert (finite(new_weight[k]));
|
||||||
|
|
||||||
|
if (new_weight[k] <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (unsigned int ff = 0; ff < capacity; ff++) {
|
||||||
|
assert (ff <= (unsigned int) f);
|
||||||
|
if (ff == capacity - 1) {
|
||||||
|
colors[ff]->set_chan(i, j, k, new_value[k]);
|
||||||
|
weights[ff]->set_chan(i, j, k,
|
||||||
|
weights[ff]->get_chan(i, j, k) + new_weight[k]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((ff == 0 && weights[ff]->get_chan(i, j, k) == 0)
|
||||||
|
|| (ff > 0 && weights[ff]->get_chan(i, j, k) == weights[ff - 1]->get_chan(i, j, k))) {
|
||||||
|
colors[ff]->set_chan(i, j, k, new_value[k]);
|
||||||
|
for (unsigned int fff = ff; fff < capacity; fff++)
|
||||||
|
weights[fff]->set_chan(i, j, k,
|
||||||
|
weights[fff]->get_chan(i, j, k) + new_weight[k]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (colors[ff]->get_chan(i, j, k) == (ale_sreal) new_value[k]) {
|
||||||
|
for (unsigned int fff = ff; fff < capacity; fff++)
|
||||||
|
weights[fff]->set_chan(i, j, k,
|
||||||
|
weights[fff]->get_chan(i, j, k) + new_weight[k]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (colors[ff]->get_chan(i, j, k) > (ale_sreal) new_value[k]) {
|
||||||
|
for (unsigned int fff = capacity - 1; fff > ff; fff--) {
|
||||||
|
weights[fff]->set_chan(i, j, k, weights[fff - 1]->get_pixel(i, j)[k] + new_weight[k]);
|
||||||
|
colors[fff]->set_chan(i, j, k, colors[fff - 1]->get_pixel(i, j)[k]);
|
||||||
|
}
|
||||||
|
colors[ff]->set_chan(i, j, k, new_value[k]);
|
||||||
|
weights[ff]->set_chan(i, j, k, new_weight[k]);
|
||||||
|
if (ff > 0)
|
||||||
|
weights[ff]->set_chan(i, j, k,
|
||||||
|
weights[ff]->get_chan(i, j, k)
|
||||||
|
+ weights[ff - 1]->get_chan(i, j, k));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: This is inefficient in cases where only one channel is desired.
|
||||||
|
*/
|
||||||
|
spixel get_pixel(unsigned int y, unsigned int x) const {
|
||||||
|
pixel result;
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
ale_real midpoint = weights[capacity - 1]->get_chan(y, x, k) / 2;
|
||||||
|
|
||||||
|
if (midpoint == 0)
|
||||||
|
return pixel::zero();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Binary search.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned int l = 0;
|
||||||
|
unsigned int h = capacity - 1;
|
||||||
|
unsigned int m = h / 2;
|
||||||
|
|
||||||
|
while (h > l + 1) {
|
||||||
|
if ((ale_real) weights[m]->get_chan(y, x, k) < midpoint)
|
||||||
|
l = m;
|
||||||
|
else
|
||||||
|
h = m;
|
||||||
|
m = (h + l) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ale_real) weights[l]->get_chan(y, x, k) < midpoint)
|
||||||
|
l = h;
|
||||||
|
if ((ale_real) weights[l]->get_chan(y, x, k) > midpoint)
|
||||||
|
result[k] = colors[l]->get_chan(y, x, k);
|
||||||
|
else if ((ale_real) weights[l]->get_chan(y, x, k) == midpoint)
|
||||||
|
result[k] = (colors[l]->get_chan(y, x, k)
|
||||||
|
+ colors[l + 1]->get_chan(y, x, k)) / 2;
|
||||||
|
else
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
image *get_weights() {
|
||||||
|
return weights[capacity - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
image *get_colors() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
205
d2/image_weighted_simple.h
Normal file
205
d2/image_weighted_simple.h
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
// Copyright 2002, 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_weighted_simple.h: Image representing a weighted average of inputs.
|
||||||
|
* Covers simple cases that require space constant with frame count.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __image_weighted_simple_h__
|
||||||
|
#define __image_weighted_simple_h__
|
||||||
|
|
||||||
|
#include "image_weighted_avg.h"
|
||||||
|
#include "render/invariant.h"
|
||||||
|
|
||||||
|
class image_weighted_simple : public image_weighted_avg {
|
||||||
|
private:
|
||||||
|
invariant *inv;
|
||||||
|
image *colors;
|
||||||
|
image *weights;
|
||||||
|
|
||||||
|
public:
|
||||||
|
image_weighted_simple (unsigned int dimy, unsigned int dimx, unsigned int
|
||||||
|
depth, invariant *inv, const char *name = "anonymous")
|
||||||
|
: image_weighted_avg(dimy, dimx, depth, name) {
|
||||||
|
colors = new_image_ale_real(dimy, dimx, depth);
|
||||||
|
weights = new_image_ale_real(dimy, dimx, depth);
|
||||||
|
this->inv = inv;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~image_weighted_simple() {
|
||||||
|
delete colors;
|
||||||
|
delete weights;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extend the image area to the top, bottom, left, and right,
|
||||||
|
* initializing the new image areas with black pixels. Negative values
|
||||||
|
* shrink the image.
|
||||||
|
*/
|
||||||
|
image *_extend(int top, int bottom, int left, int right) {
|
||||||
|
extend(&colors, top, bottom, left, right);
|
||||||
|
extend(&weights, top, bottom, left, right);
|
||||||
|
|
||||||
|
_dimx = colors->width();
|
||||||
|
_dimy = colors->height();
|
||||||
|
_offset = colors->offset();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pre-transformation check for whether an area should be skipped.
|
||||||
|
* Takes image weights as an argument.
|
||||||
|
*/
|
||||||
|
int accumulate_norender(int i, int j) {
|
||||||
|
/*
|
||||||
|
* Initial value
|
||||||
|
*/
|
||||||
|
if (inv->is_first() && weights->get_chan(i, j, 0) != 0)
|
||||||
|
return 1;
|
||||||
|
/*
|
||||||
|
* Weight limit satisfied
|
||||||
|
*/
|
||||||
|
if (inv->is_avgf()
|
||||||
|
&& weights->get_chan(i, j, 0) > inv->get_param()
|
||||||
|
&& weights->get_chan(i, j, 1) > inv->get_param()
|
||||||
|
&& weights->get_chan(i, j, 2) > inv->get_param())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Accumulate pixels
|
||||||
|
*/
|
||||||
|
void accumulate(int i, int j, int f, pixel new_value, pixel new_weight) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform operations separately for each channel
|
||||||
|
*/
|
||||||
|
for (unsigned int k = 0; k < 3; k++) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cases independent of the old pixel value and weight
|
||||||
|
* for which the update can be ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!inv->is_avgx()
|
||||||
|
&& new_weight[k] < render::get_wt())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cases independent of the old pixel value and weight for which
|
||||||
|
* previous pixel values can be ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (inv->is_last() && new_weight[k] >= render::get_wt()) {
|
||||||
|
colors->set_chan(i, j, k, new_value[k]);
|
||||||
|
weights->set_chan(i, j, k, new_weight[k]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain the old pixel weight.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_real old_weight = weights->get_chan(i, j, k);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cases independent of the old pixel value for which the
|
||||||
|
* update can be ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (old_weight >= render::get_wt()
|
||||||
|
&& inv->is_first())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (inv->is_avgf()
|
||||||
|
&& old_weight >= inv->get_param())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cases independent of the old pixel value for which previous
|
||||||
|
* pixel values can be ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (old_weight == 0
|
||||||
|
|| (old_weight < render::get_wt()
|
||||||
|
&& !inv->is_avgx())) {
|
||||||
|
weights->set_chan(i, j, k, new_weight[k]);
|
||||||
|
colors ->set_chan(i, j, k, new_value[k]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inv->is_max()) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cases in which the old pixel value can be ignored
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (new_value[k] * (ale_real) weights->get_chan(i, j, k)
|
||||||
|
> (ale_real) colors->get_chan(i, j, k) * new_weight[k]) {
|
||||||
|
weights->set_chan(i, j, k, new_weight[k]);
|
||||||
|
colors-> set_chan(i, j, k, new_value[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else if (inv->is_min()) {
|
||||||
|
/*
|
||||||
|
* Cases in which the old pixel value can be ignored
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (new_value[k] * (ale_real) weights->get_chan(i, j, k)
|
||||||
|
< (ale_real) colors->get_chan(i, j, k) * new_weight[k]) {
|
||||||
|
weights->set_chan(i, j, k, new_weight[k]);
|
||||||
|
colors-> set_chan(i, j, k, new_value[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update weight and color values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
weights->set_chan(i, j, k, weights->get_chan(i, j, k) + new_weight[k]);
|
||||||
|
colors->set_chan(i, j, k, colors->get_chan(i, j, k) + new_value[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
spixel get_pixel(unsigned int y, unsigned int x) const {
|
||||||
|
return (pixel) colors->get_pixel(y, x) / (pixel) weights->get_pixel(y, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
image *get_weights() {
|
||||||
|
return weights;
|
||||||
|
}
|
||||||
|
|
||||||
|
image *get_colors() {
|
||||||
|
assert(0);
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
246
d2/image_zero.h
Normal file
246
d2/image_zero.h
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
// Copyright 2002, 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* zero_image.h: Image that is zero everywhere.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __image_zero_h__
|
||||||
|
#define __image_zero_h__
|
||||||
|
|
||||||
|
#include "point.h"
|
||||||
|
#include "pixel.h"
|
||||||
|
#include "exposure/exposure.h"
|
||||||
|
|
||||||
|
class image_zero : public image_weighted_avg {
|
||||||
|
public:
|
||||||
|
|
||||||
|
spixel get_pixel(unsigned int y, unsigned int x) const {
|
||||||
|
return pixel::zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pixel(unsigned int y, unsigned int x, spixel p) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_chan(unsigned int y, unsigned int x, unsigned int k, ale_sreal c) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_sreal get_chan(unsigned int y, unsigned int x, unsigned int k) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real maxval() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real minval() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a color value at a given position using bilinear interpolation between the
|
||||||
|
* four nearest pixels. Result values:
|
||||||
|
*
|
||||||
|
* result[0] == pixel value
|
||||||
|
* result[1] == pixel confidence
|
||||||
|
*/
|
||||||
|
void get_bl(point x, pixel result[2]) const {
|
||||||
|
result[0] = pixel::zero();
|
||||||
|
result[1] = pixel::zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel get_bl(point x) const {
|
||||||
|
pixel result[2];
|
||||||
|
|
||||||
|
get_bl(x, result);
|
||||||
|
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel get_scaled_bl(point x, ale_pos f) const {
|
||||||
|
return pixel::zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a new image suitable for receiving scaled values.
|
||||||
|
*/
|
||||||
|
virtual image *scale_generator(int height, int width, int depth, const char *name) const {
|
||||||
|
|
||||||
|
image *is = new image_zero(height, width, depth, name);
|
||||||
|
|
||||||
|
assert(is);
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return an image scaled by some factor >= 1.0
|
||||||
|
*/
|
||||||
|
image *scale(ale_pos f, const char *name) const {
|
||||||
|
|
||||||
|
image *is = new image_zero(
|
||||||
|
(int) floor(height() * f),
|
||||||
|
(int) floor(width() * f), depth());
|
||||||
|
|
||||||
|
assert(is);
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scale by half. We use the following filter:
|
||||||
|
*
|
||||||
|
* 1/16 1/8 1/16
|
||||||
|
* 1/8 1/4 1/8
|
||||||
|
* 1/16 1/8 1/16
|
||||||
|
*
|
||||||
|
* At the edges, these values are normalized so that the sum of
|
||||||
|
* contributing pixels is 1.
|
||||||
|
*/
|
||||||
|
image *scale_by_half(const char *name) const {
|
||||||
|
ale_pos f = 0.5;
|
||||||
|
|
||||||
|
image *result = new image_zero(
|
||||||
|
(int) floor(height() * f),
|
||||||
|
(int) floor(width() * f), depth());
|
||||||
|
|
||||||
|
assert(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scale an image definition array by 1/2.
|
||||||
|
*
|
||||||
|
* ALE considers an image definition array as a special kind of image
|
||||||
|
* weight array (typedefs of which should appear below the definition
|
||||||
|
* of this class). ALE uses nonzero pixel values to mean 'defined' and
|
||||||
|
* zero values to mean 'undefined'. Through this interpretation, the
|
||||||
|
* image weight array implementation that ALE uses allows image weight
|
||||||
|
* arrays to also serve as image definition arrays.
|
||||||
|
*
|
||||||
|
* Whereas scaling of image weight arrays is not generally obvious in
|
||||||
|
* either purpose or method, ALE requires that image definition arrays
|
||||||
|
* be scalable, and the method we implement here is a fairly obvious
|
||||||
|
* one. In particular, if any source pixel contributing to the value of
|
||||||
|
* a scaled target pixel has an undefined value, then the scaled target
|
||||||
|
* pixel is undefined (zero). Otherwise, it is defined (non-zero).
|
||||||
|
*
|
||||||
|
* Since there are many possible ways of implementing this function, we
|
||||||
|
* choose an easy way and simply multiply the numerical values of the
|
||||||
|
* source pixels to obtain the value of the scaled target pixel.
|
||||||
|
*
|
||||||
|
* XXX: we consider all pixels within a 9-pixel square to contribute.
|
||||||
|
* There are other approaches. For example, edge pixels could be
|
||||||
|
* considered to have six contributing pixels and corner pixels four
|
||||||
|
* contributing pixels. To use this convention, change the ': 0' text
|
||||||
|
* in the code below to ': 1'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
image *defined_scale_by_half(const char *name) const {
|
||||||
|
ale_pos f = 0.5;
|
||||||
|
|
||||||
|
image *result = new image_zero(
|
||||||
|
(int) floor(height() * f),
|
||||||
|
(int) floor(width() * f), depth());
|
||||||
|
|
||||||
|
assert(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extend the image area to the top, bottom, left, and right,
|
||||||
|
* initializing the new image areas with black pixels.
|
||||||
|
*/
|
||||||
|
virtual image *_extend(int top, int bottom, int left, int right) {
|
||||||
|
_dimy += top + bottom;
|
||||||
|
_dimx += left + right;
|
||||||
|
_offset[0] -= top;
|
||||||
|
_offset[1] -= left;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clone
|
||||||
|
*/
|
||||||
|
image *clone(const char *name) const {
|
||||||
|
return new image_zero(_dimy, _dimx, _depth, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the average (mean) clamped magnitude of a channel across
|
||||||
|
* all pixels in an image. The magnitude is clamped to the range of
|
||||||
|
* real inputs.
|
||||||
|
*/
|
||||||
|
ale_real avg_channel_clamped_magnitude(unsigned int k) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel avg_channel_clamped_magnitude() const {
|
||||||
|
return pixel::zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the average (mean) magnitude of a channel across all
|
||||||
|
* pixels in an image.
|
||||||
|
*/
|
||||||
|
ale_real avg_channel_magnitude(unsigned int k) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel avg_channel_magnitude() const {
|
||||||
|
return pixel::zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the average (mean) magnitude of a pixel (where magnitude
|
||||||
|
* is defined as the mean of the channel values).
|
||||||
|
*/
|
||||||
|
ale_real avg_pixel_magnitude() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
image_zero(unsigned int dimy, unsigned int dimx, unsigned int depth,
|
||||||
|
const char *name = "anonymous") : image_weighted_avg(dimy, dimx, depth, name) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int accumulate_norender(int i, int j) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void accumulate(int i, int j, int f, pixel new_value, pixel new_weight) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
image *get_colors() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
image *get_weights() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
277
d2/pixel.h
Normal file
277
d2/pixel.h
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __pixel_h__
|
||||||
|
#define __pixel_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure to describe a pixel
|
||||||
|
*/
|
||||||
|
|
||||||
|
class pixel {
|
||||||
|
private:
|
||||||
|
ale_real x[3];
|
||||||
|
|
||||||
|
public:
|
||||||
|
pixel() {
|
||||||
|
x[0] = 0;
|
||||||
|
x[1] = 0;
|
||||||
|
x[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel(ale_real x0, ale_real x1, ale_real x2) {
|
||||||
|
x[0] = x0;
|
||||||
|
x[1] = x1;
|
||||||
|
x[2] = x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel(const pixel &p) {
|
||||||
|
x[0] = p[0];
|
||||||
|
x[1] = p[1];
|
||||||
|
x[2] = p[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel &operator=(const pixel &p) {
|
||||||
|
x[0] = p[0];
|
||||||
|
x[1] = p[1];
|
||||||
|
x[2] = p[2];
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Due to automatic typecasts and automatic int <==> ale_real *
|
||||||
|
// conversions, this can cause some really weird bugs.
|
||||||
|
//
|
||||||
|
// pixel(ale_real *_x) {
|
||||||
|
// x[0] = _x[0];
|
||||||
|
// x[1] = _x[1];
|
||||||
|
// x[2] = _x[2];
|
||||||
|
// }
|
||||||
|
|
||||||
|
const ale_real &operator[](unsigned int i) const {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This may be expensive.
|
||||||
|
*/
|
||||||
|
assert (i < 3);
|
||||||
|
#endif
|
||||||
|
return x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real &operator[](unsigned int i) {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This may be expensive.
|
||||||
|
*/
|
||||||
|
assert (i < 3);
|
||||||
|
#endif
|
||||||
|
return x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator+(pixel p) const {
|
||||||
|
return pixel(p[0] + x[0], p[1] + x[1], p[2] + x[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator-(pixel p) const {
|
||||||
|
return pixel(x[0] - p[0], x[1] - p[1], x[2] - p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator-() const {
|
||||||
|
return pixel(-x[0], -x[1], -x[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator/(pixel p) const {
|
||||||
|
return pixel(x[0] / p[0], x[1] / p[1], x[2] / p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator/(ale_real d) const {
|
||||||
|
return pixel(x[0] / d, x[1] / d, x[2] / d);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel mult(pixel p) const {
|
||||||
|
return pixel(x[0] * p[0], x[1] * p[1], x[2] * p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel mult(ale_real d) const {
|
||||||
|
return pixel(x[0] * d, x[1] * d, x[2] * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator+=(pixel p) {
|
||||||
|
return pixel(x[0] += p[0], x[1] += p[1], x[2] += p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator*=(pixel p) {
|
||||||
|
return pixel(x[0] *= p[0], x[1] *= p[1], x[2] *= p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator*=(ale_real d) {
|
||||||
|
return pixel(x[0] *= d, x[1] *= d, x[2] *= d);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator/=(pixel p) {
|
||||||
|
return pixel(x[0] /= p[0], x[1] /= p[1], x[2] /= p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator/=(ale_real d) {
|
||||||
|
return pixel(x[0] /= d, x[1] /= d, x[2] /= d);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel clamp() const {
|
||||||
|
pixel result;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
if (x[i] > 1.0)
|
||||||
|
result[i] = 1.0;
|
||||||
|
else if (x[i] < 0.0)
|
||||||
|
result[i] = 0.0;
|
||||||
|
else
|
||||||
|
result[i] = x[i];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pixel abs() {
|
||||||
|
return pixel(fabs(x[0]), fabs(x[1]), fabs(x[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real normsq() {
|
||||||
|
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real norm() {
|
||||||
|
return sqrt(normsq());
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real lnorm() {
|
||||||
|
return x[0] + x[1] + x[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real maxabs_norm() {
|
||||||
|
ale_real m = fabs(x[0]);
|
||||||
|
if (fabs(x[1]) > m)
|
||||||
|
m = fabs(x[1]);
|
||||||
|
if (fabs(x[2]) > m)
|
||||||
|
m = fabs(x[2]);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real minabs_norm() {
|
||||||
|
ale_real m = fabs(x[0]);
|
||||||
|
if (fabs(x[1]) < m)
|
||||||
|
m = fabs(x[1]);
|
||||||
|
if (fabs(x[2]) < m)
|
||||||
|
m = fabs(x[2]);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real min_norm() const {
|
||||||
|
ale_real m = x[0];
|
||||||
|
if (x[1] < m)
|
||||||
|
m = x[1];
|
||||||
|
if (x[2] < m)
|
||||||
|
m = x[2];
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real max_norm() {
|
||||||
|
ale_real m = x[0];
|
||||||
|
if (x[1] > m)
|
||||||
|
m = x[1];
|
||||||
|
if (x[2] > m)
|
||||||
|
m = x[2];
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static pixel zero() {
|
||||||
|
return pixel(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pixel one() {
|
||||||
|
return pixel(1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int operator==(const pixel &p) {
|
||||||
|
return x[0] == p[0]
|
||||||
|
&& x[1] == p[1]
|
||||||
|
&& x[2] == p[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
int operator!=(const pixel &p) {
|
||||||
|
return !operator==(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int finite() {
|
||||||
|
return ::finite(x[0]) && ::finite(x[1]) && ::finite(x[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pixel undefined() {
|
||||||
|
ale_real zero = 0;
|
||||||
|
return pixel(zero / zero, zero / zero, zero / zero);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline pixel operator*(const pixel &p, const pixel &q) {
|
||||||
|
return p.mult(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline pixel operator*(T d, const pixel &p) {
|
||||||
|
return p.mult(d);
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
inline pixel operator*(const pixel &p, T d) {
|
||||||
|
return p.mult(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream &operator<<(std::ostream &o, const pixel &p) {
|
||||||
|
o << "[" << (double) p[0] << " " << (double) p[1] << " " << (double) p[2] << "]";
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline pixel ppow(pixel p, T d) {
|
||||||
|
return pixel(
|
||||||
|
pow(p[0], d),
|
||||||
|
pow(p[1], d),
|
||||||
|
pow(p[2], d));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pixel pexp(pixel p) {
|
||||||
|
return pixel(
|
||||||
|
exp((double) p[0]),
|
||||||
|
exp((double) p[1]),
|
||||||
|
exp((double) p[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pixel psqrt(pixel p) {
|
||||||
|
return pixel(
|
||||||
|
sqrt(p[0]),
|
||||||
|
sqrt(p[1]),
|
||||||
|
sqrt(p[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
158
d2/pixel_accum.h
Normal file
158
d2/pixel_accum.h
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __pixel_accum_h__
|
||||||
|
#define __pixel_accum_h__
|
||||||
|
|
||||||
|
#include "pixel.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure to accumulate values over many pixels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class pixel_accum {
|
||||||
|
private:
|
||||||
|
ale_accum x[3];
|
||||||
|
|
||||||
|
public:
|
||||||
|
pixel_accum() {
|
||||||
|
x[0] = 0;
|
||||||
|
x[1] = 0;
|
||||||
|
x[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum(ale_accum x0, ale_accum x1, ale_accum x2) {
|
||||||
|
x[0] = x0;
|
||||||
|
x[1] = x1;
|
||||||
|
x[2] = x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum(pixel p) {
|
||||||
|
x[0] = p[0];
|
||||||
|
x[1] = p[1];
|
||||||
|
x[2] = p[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
operator pixel() {
|
||||||
|
pixel result;
|
||||||
|
|
||||||
|
result[0] = x[0];
|
||||||
|
result[1] = x[1];
|
||||||
|
result[2] = x[2];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Due to automatic typecasts and automatic int <==> ale_accum *
|
||||||
|
// conversions, this can cause some really weird bugs.
|
||||||
|
//
|
||||||
|
// pixel_accum(ale_accum *_x) {
|
||||||
|
// x[0] = _x[0];
|
||||||
|
// x[1] = _x[1];
|
||||||
|
// x[2] = _x[2];
|
||||||
|
// }
|
||||||
|
|
||||||
|
const ale_accum &operator[](int i) const {
|
||||||
|
assert (i >= 0);
|
||||||
|
assert (i < 3);
|
||||||
|
|
||||||
|
return x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_accum &operator[](int i) {
|
||||||
|
assert (i >= 0);
|
||||||
|
assert (i < 3);
|
||||||
|
|
||||||
|
return x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator+(pixel_accum p) const {
|
||||||
|
return pixel_accum(p[0] + x[0], p[1] + x[1], p[2] + x[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator-(pixel_accum p) const {
|
||||||
|
return pixel_accum(x[0] - p[0], x[1] - p[1], x[2] - p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator/(pixel_accum p) const {
|
||||||
|
return pixel_accum(x[0] / p[0], x[1] / p[1], x[2] / p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator/(ale_accum d) const {
|
||||||
|
return pixel_accum(x[0] / d, x[1] / d, x[2] / d);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator*(pixel_accum p) const {
|
||||||
|
return pixel_accum(x[0] * p[0], x[1] * p[1], x[2] * p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator*(ale_accum d) const {
|
||||||
|
return pixel_accum(x[0] * d, x[1] * d, x[2] * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator+=(pixel_accum p) {
|
||||||
|
return pixel_accum(x[0] += p[0], x[1] += p[1], x[2] += p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator*=(pixel_accum p) {
|
||||||
|
return pixel_accum(x[0] *= p[0], x[1] *= p[1], x[2] *= p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator*=(ale_accum d) {
|
||||||
|
return pixel_accum(x[0] *= d, x[1] *= d, x[2] *= d);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator/=(pixel_accum p) {
|
||||||
|
return pixel_accum(x[0] /= p[0], x[1] /= p[1], x[2] /= p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_accum operator/=(ale_accum d) {
|
||||||
|
return pixel_accum(x[0] /= d, x[1] /= d, x[2] /= d);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline pixel_accum operator*(float d, const pixel_accum &p) {
|
||||||
|
return p * d;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pixel_accum operator*(double d, const pixel_accum &p) {
|
||||||
|
return p * d;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream &operator<<(std::ostream &o, const pixel_accum &p) {
|
||||||
|
o << "[" << (double) p[0] << " " << (double) p[1] << " " << (double) p[2] << "]";
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pixel_accum ppow(pixel_accum p, float d) {
|
||||||
|
return pixel_accum(
|
||||||
|
pow((ale_accum) p[0], d),
|
||||||
|
pow((ale_accum) p[1], d),
|
||||||
|
pow((ale_accum) p[2], d));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pixel_accum ppow(pixel_accum p, double d) {
|
||||||
|
return pixel_accum(
|
||||||
|
pow((ale_accum) p[0], d),
|
||||||
|
pow((ale_accum) p[1], d),
|
||||||
|
pow((ale_accum) p[2], d));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
215
d2/point.h
Normal file
215
d2/point.h
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __d2point_h__
|
||||||
|
#define __d2point_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure to describe a point
|
||||||
|
*/
|
||||||
|
|
||||||
|
class point {
|
||||||
|
private:
|
||||||
|
ale_pos x[2];
|
||||||
|
|
||||||
|
public:
|
||||||
|
point() {
|
||||||
|
}
|
||||||
|
|
||||||
|
point(ale_pos x0, ale_pos x1) {
|
||||||
|
x[0] = x0;
|
||||||
|
x[1] = x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ale_pos &operator[](unsigned int i) const {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This may be expensive.
|
||||||
|
*/
|
||||||
|
assert (i < 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_pos &operator[](unsigned int i) {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This may be expensive.
|
||||||
|
*/
|
||||||
|
assert (i < 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
point operator+(point p) const {
|
||||||
|
return point(p[0] + x[0], p[1] + x[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
point operator-(point p) const {
|
||||||
|
return point(x[0] - p[0], x[1] - p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
point operator-() const {
|
||||||
|
return point(-x[0], -x[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
point operator+=(point p) {
|
||||||
|
(*this) = (*this) + p;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
point operator-=(point p) {
|
||||||
|
(*this) = (*this) - p;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
point mult(ale_pos d) const {
|
||||||
|
return point(x[0] * d, x[1] * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
point operator*(point p) const {
|
||||||
|
/*
|
||||||
|
* element-wise multiplication
|
||||||
|
*/
|
||||||
|
return point(x[0] * p[0], x[1] * p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
point operator *=(ale_pos d) {
|
||||||
|
(*this) = mult(d);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
point operator/(ale_pos d) const {
|
||||||
|
return point(x[0] / d, x[1] / d);
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_pos normsq() const {
|
||||||
|
return x[0] * x[0] + x[1] * x[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_pos norm() const {
|
||||||
|
return sqrt(normsq());
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_pos absmaxnorm() const {
|
||||||
|
ale_pos a = fabs(x[0]);
|
||||||
|
ale_pos b = fabs(x[1]);
|
||||||
|
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_pos lengthtosq(point p) const {
|
||||||
|
point diff = operator-(p);
|
||||||
|
|
||||||
|
return diff[0] * diff[0] + diff[1] * diff[1];
|
||||||
|
}
|
||||||
|
ale_pos lengthto(point p) const {
|
||||||
|
return sqrt(lengthtosq(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_pos dproduct(point p) const {
|
||||||
|
return (x[0] * p[0] + x[1] * p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_pos anglebetw(point p, point q) {
|
||||||
|
/*
|
||||||
|
* by the law of cosines, the cosine is equal to:
|
||||||
|
*
|
||||||
|
* (lengthtosq(p) + lengthtosq(q) - p.lengthtosq(q))
|
||||||
|
* / (2 * lengthto(p) * lengthto(q))
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_pos to_p = lengthtosq(p);
|
||||||
|
ale_pos to_q = lengthtosq(q);
|
||||||
|
|
||||||
|
ale_pos cos_of = (double) (to_p + to_q - p.lengthtosq(q))
|
||||||
|
/ (2 * sqrt(to_p) * sqrt(to_q));
|
||||||
|
|
||||||
|
return acos(cos_of);
|
||||||
|
}
|
||||||
|
|
||||||
|
static point posinf() {
|
||||||
|
ale_pos a = +1;
|
||||||
|
ale_pos z = +0;
|
||||||
|
|
||||||
|
a = a / z;
|
||||||
|
|
||||||
|
assert (isinf(a) && a > 0);
|
||||||
|
|
||||||
|
return point(a, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static point neginf() {
|
||||||
|
point n = -posinf();
|
||||||
|
|
||||||
|
assert (isinf(n[0]) && n[0] < 0);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void accumulate_max(point p) {
|
||||||
|
for (int d = 0; d < 2; d++)
|
||||||
|
if (p[d] > x[d])
|
||||||
|
x[d] = p[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
void accumulate_min(point p) {
|
||||||
|
for (int d = 0; d < 2; d++)
|
||||||
|
if (p[d] < x[d])
|
||||||
|
x[d] = p[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
static point undefined() {
|
||||||
|
double a = 0;
|
||||||
|
|
||||||
|
point p(0, 0);
|
||||||
|
|
||||||
|
return p / a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int defined() const {
|
||||||
|
return (!isnan(x[0])
|
||||||
|
&& !isnan(x[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int finite() const {
|
||||||
|
return (::finite(x[0])
|
||||||
|
&& ::finite(x[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int defined(const point &p) {
|
||||||
|
return p.defined();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline point operator*(const point &p, double d) {
|
||||||
|
return p.mult(d);
|
||||||
|
}
|
||||||
|
inline point operator*(double d, const point &p) {
|
||||||
|
return p.mult(d);
|
||||||
|
}
|
||||||
|
inline point operator*(float d, const point &p) {
|
||||||
|
return p.mult(d);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
430
d2/ppm.h
Normal file
430
d2/ppm.h
Normal file
@@ -0,0 +1,430 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ppm.h: Read and write PPM files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ppm_h__
|
||||||
|
#define __ppm_h__
|
||||||
|
|
||||||
|
#include "image_ale_real.h"
|
||||||
|
#include "image_bayer_ale_real.h"
|
||||||
|
#include "exposure/exposure.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extended attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct extended_t {
|
||||||
|
int is_extended;
|
||||||
|
ale_real black_level;
|
||||||
|
ale_real aperture; /* 1 == f/1.0, 1.4 == f/1.4, etc. */
|
||||||
|
ale_real shutter; /* 1 == 1 sec, 0.5 == 1/2 sec, etc. */
|
||||||
|
ale_real gain; /* 1 == ISO 100, 2 == ISO 200, etc. */
|
||||||
|
|
||||||
|
extended_t() {
|
||||||
|
is_extended = 0;
|
||||||
|
black_level = 0;
|
||||||
|
aperture = 0;
|
||||||
|
shutter = 0;
|
||||||
|
gain = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void error_ppm(const char *filename) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n\n*** '%s' doesn't look like a PPM file.\n"
|
||||||
|
"\n*** (To handle other file types, use a version of ALE with\n"
|
||||||
|
"*** ImageMagick support enabled.)\n\n",
|
||||||
|
filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int digest_comment(FILE *f, const char *filename, extended_t *extended) {
|
||||||
|
int next = '#';
|
||||||
|
int value;
|
||||||
|
double fvalue, fvalue2;
|
||||||
|
|
||||||
|
while (next != '\n' && next != '\r' && next != EOF) {
|
||||||
|
while (next == ' ' || next == '\t' || next == '#') {
|
||||||
|
next = fgetc(f);
|
||||||
|
if (feof(f))
|
||||||
|
error_ppm(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ungetc(next, f) == EOF) {
|
||||||
|
assert(0);
|
||||||
|
fprintf(stderr, "Unable to ungetc().");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fvalue2 = 1;
|
||||||
|
|
||||||
|
if (extended->is_extended && fscanf(f, "Black-level: %d", &value) == 1)
|
||||||
|
extended->black_level = value;
|
||||||
|
else if (extended->is_extended && fscanf(f, "ISO: %lf", &fvalue) == 1)
|
||||||
|
extended->gain = fvalue / 100;
|
||||||
|
else if (extended->is_extended && fscanf(f, "Gain: %lf", &fvalue) == 1)
|
||||||
|
extended->gain = fvalue;
|
||||||
|
else if (extended->is_extended && fscanf(f, "Aperture: %lf", &fvalue) == 1)
|
||||||
|
extended->aperture = fvalue;
|
||||||
|
else if (extended->is_extended && fscanf(f, "Shutter: %lf/%lf", &fvalue, &fvalue2) > 0)
|
||||||
|
extended->shutter = fvalue / fvalue2;
|
||||||
|
else if (next != '\n' && next != '\r' && next != EOF)
|
||||||
|
next = fgetc(f);
|
||||||
|
|
||||||
|
next = fgetc(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void eat_comments(FILE *f, const char *filename, extended_t *extended) {
|
||||||
|
int next = ' ';
|
||||||
|
|
||||||
|
while (next == ' ' || next == '\n' || next == '\t' || next == '#' || next == '\r') {
|
||||||
|
next = fgetc(f);
|
||||||
|
if (next == '#')
|
||||||
|
next = digest_comment(f, filename, extended);
|
||||||
|
if (feof(f))
|
||||||
|
error_ppm(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ungetc(next, f) == EOF) {
|
||||||
|
assert(0);
|
||||||
|
fprintf(stderr, "Unable to ungetc().");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int is_eppm(const char *filename) {
|
||||||
|
char m1, m2, m3, m4;
|
||||||
|
int n;
|
||||||
|
extended_t extended;
|
||||||
|
FILE *f = fopen(filename, "rb");
|
||||||
|
|
||||||
|
if (f == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Magic */
|
||||||
|
|
||||||
|
eat_comments(f, filename, &extended); /* XXX - should we eat comments here? */
|
||||||
|
n = fscanf(f, "%c%c%c%c", &m1, &m2, &m3, &m4);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (n != 4 || m1 != 'P' || (m2 != '6' && m2 != '3') || m3 != '#' || m4 != 'E')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline image *read_ppm(const char *filename, exposure *e, unsigned int bayer, int init_reference_gain = 0) {
|
||||||
|
unsigned int i, j, k;
|
||||||
|
image *im;
|
||||||
|
unsigned char m1, m2, val;
|
||||||
|
int m3, m4;
|
||||||
|
int ival;
|
||||||
|
int w, h, mcv;
|
||||||
|
int n;
|
||||||
|
struct extended_t extended;
|
||||||
|
FILE *f = fopen(filename, "rb");
|
||||||
|
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf(stderr, "\n\nUnable to open '%s'.\n\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(f);
|
||||||
|
|
||||||
|
/* Magic */
|
||||||
|
|
||||||
|
eat_comments(f, filename, &extended); /* XXX - should we eat comments here? */
|
||||||
|
n = fscanf(f, "%c%c", &m1, &m2);
|
||||||
|
|
||||||
|
if (n != 2 || m1 != 'P' || (m2 != '6' && m2 != '3'))
|
||||||
|
error_ppm(filename);
|
||||||
|
|
||||||
|
assert(n == 2 && m1 == 'P' && (m2 == '6' || m2 == '3'));
|
||||||
|
|
||||||
|
/* Extended flag */
|
||||||
|
|
||||||
|
m3 = fgetc(f);
|
||||||
|
|
||||||
|
if (m3 == '#') {
|
||||||
|
m4 = fgetc(f);
|
||||||
|
if (m4 == 'E')
|
||||||
|
extended.is_extended = 1;
|
||||||
|
else while (m4 != EOF && m4 != '\n' && m4 != '\r')
|
||||||
|
m4 = fgetc(f);
|
||||||
|
} else if (ungetc(m3, f) == EOF) {
|
||||||
|
assert(0);
|
||||||
|
fprintf(stderr, "Unable to ungetc().");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Width */
|
||||||
|
|
||||||
|
eat_comments(f, filename, &extended);
|
||||||
|
n = fscanf(f, " %d", &w);
|
||||||
|
assert(n == 1);
|
||||||
|
|
||||||
|
if (n != 1)
|
||||||
|
error_ppm(filename);
|
||||||
|
|
||||||
|
/* Height */
|
||||||
|
|
||||||
|
eat_comments(f, filename, &extended);
|
||||||
|
n = fscanf(f, "%d", &h);
|
||||||
|
assert(n == 1);
|
||||||
|
|
||||||
|
if (n != 1)
|
||||||
|
error_ppm(filename);
|
||||||
|
|
||||||
|
/* Maximum component value */
|
||||||
|
|
||||||
|
eat_comments(f, filename, &extended);
|
||||||
|
n = fscanf(f, "%d", &mcv);
|
||||||
|
assert(n == 1);
|
||||||
|
assert(mcv <= 65535 || m2 == '3');
|
||||||
|
|
||||||
|
if (extended.black_level == 0) {
|
||||||
|
extended.black_level = e->get_black_level();
|
||||||
|
} else {
|
||||||
|
extended.black_level /= mcv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n != 1 || (mcv > 65535 && m2 == '6'))
|
||||||
|
error_ppm(filename);
|
||||||
|
|
||||||
|
/* Make a new image */
|
||||||
|
|
||||||
|
if (bayer == IMAGE_BAYER_NONE)
|
||||||
|
im = new_image_ale_real(h, w, 3, "file", e);
|
||||||
|
else
|
||||||
|
im = new_image_bayer_ale_real(h, w, 3, bayer, "file", e);
|
||||||
|
|
||||||
|
assert (im);
|
||||||
|
|
||||||
|
/* Trailing whitespace */
|
||||||
|
|
||||||
|
if (fgetc(f) == EOF) {
|
||||||
|
assert(0);
|
||||||
|
error_ppm(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pixels */
|
||||||
|
|
||||||
|
for (i = 0; i < im->height(); i++)
|
||||||
|
for (j = 0; j < im->width(); j++) {
|
||||||
|
pixel p;
|
||||||
|
for (k = 0; k < im->depth(); k++) {
|
||||||
|
|
||||||
|
if (m2 == '6') {
|
||||||
|
|
||||||
|
/* Binary data */
|
||||||
|
|
||||||
|
n = fscanf(f, "%c", &val);
|
||||||
|
assert (n == 1);
|
||||||
|
|
||||||
|
if (n != 1)
|
||||||
|
error_ppm(filename);
|
||||||
|
|
||||||
|
ival = val;
|
||||||
|
|
||||||
|
if (mcv > 255) {
|
||||||
|
n = fscanf(f, "%c", &val);
|
||||||
|
assert(n == 1);
|
||||||
|
|
||||||
|
if (n != 1)
|
||||||
|
error_ppm(filename);
|
||||||
|
|
||||||
|
ival = (ival << 8) | val;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* ASCII data */
|
||||||
|
|
||||||
|
eat_comments(f, filename, &extended);
|
||||||
|
|
||||||
|
n = fscanf(f, "%d", &ival);
|
||||||
|
|
||||||
|
assert (n == 1);
|
||||||
|
if (n != 1)
|
||||||
|
error_ppm(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
p[k] = ale_real_from_int(ival, mcv);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel p_linear = (e->linearize(p) - e->get_multiplier() * extended.black_level)
|
||||||
|
/ (1 - extended.black_level);
|
||||||
|
|
||||||
|
im->set_pixel(i, j, p_linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle exposure and gain */
|
||||||
|
|
||||||
|
if (extended.is_extended) {
|
||||||
|
if (extended.aperture != 0
|
||||||
|
|| extended.shutter != 0
|
||||||
|
|| extended.gain != 0) {
|
||||||
|
|
||||||
|
if (extended.aperture == 0)
|
||||||
|
extended.aperture = 1;
|
||||||
|
if (extended.shutter == 0)
|
||||||
|
extended.shutter = 1;
|
||||||
|
if (extended.gain == 0)
|
||||||
|
extended.gain = 1;
|
||||||
|
|
||||||
|
ale_real combined_gain = (1 / pow(extended.aperture, 2))
|
||||||
|
* extended.shutter
|
||||||
|
* extended.gain;
|
||||||
|
|
||||||
|
if (init_reference_gain)
|
||||||
|
exposure::set_gain_reference(combined_gain);
|
||||||
|
else
|
||||||
|
e->set_gain_multiplier(exposure::get_gain_reference()
|
||||||
|
/ combined_gain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return im;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void write_ppm(const char *filename, const image *im, exposure *e,
|
||||||
|
unsigned int mcv, int plain, int rezero, int exposure_scale, double nn_defined_radius) {
|
||||||
|
unsigned int i, j, k;
|
||||||
|
FILE *f = fopen(filename, "wb");
|
||||||
|
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf(stderr, "\n\nUnable to open '%s'.\n\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(f);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output a plain (ASCII) or raw (binary) PPM file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Magic */
|
||||||
|
|
||||||
|
if (plain)
|
||||||
|
fprintf(f, "P3 ");
|
||||||
|
else
|
||||||
|
fprintf(f, "P6 ");
|
||||||
|
|
||||||
|
/* Width */
|
||||||
|
|
||||||
|
fprintf(f, "%d ", im->width());
|
||||||
|
|
||||||
|
/* Height */
|
||||||
|
|
||||||
|
fprintf(f, "%d ", im->height());
|
||||||
|
|
||||||
|
/* Maximum component value */
|
||||||
|
|
||||||
|
fprintf(f, "%d\n", mcv);
|
||||||
|
|
||||||
|
/* Automatic exposure adjustment information */
|
||||||
|
|
||||||
|
ale_real maxval = 1;
|
||||||
|
ale_real minval = (rezero ? im->minval() : (ale_real) 0);
|
||||||
|
if (minval > 0)
|
||||||
|
minval = 0;
|
||||||
|
pixel minval_pixel(minval, minval, minval);
|
||||||
|
|
||||||
|
if (exposure_scale) {
|
||||||
|
ale_real new_maxval = im->maxval();
|
||||||
|
|
||||||
|
if (new_maxval > maxval)
|
||||||
|
maxval = new_maxval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pixels */
|
||||||
|
|
||||||
|
for (i = 0; i < im->height(); i++)
|
||||||
|
for (j = 0; j < im->width(); j++) {
|
||||||
|
pixel value = im->get_pixel(i, j);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get nearest-neighbor defined values.
|
||||||
|
*
|
||||||
|
* XXX: While this implementation is correct, it is inefficient
|
||||||
|
* for large radii. A better implementation would search
|
||||||
|
* perimeters of squares of ever-increasing radius, tracking
|
||||||
|
* the best-so-far data until the square perimeter exceeded the
|
||||||
|
* best-so-far radius.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (k = 0; k < 3; k++)
|
||||||
|
if (isnan(value[k]))
|
||||||
|
for (int radius = 1; radius <= nn_defined_radius; radius++) {
|
||||||
|
double nearest_radius_squared = (radius + 1) * (radius + 1);
|
||||||
|
for (int ii = -radius; ii <= radius; ii++)
|
||||||
|
for (int jj = -radius; jj <= radius; jj++) {
|
||||||
|
if (!im->in_bounds(point(i + ii, j + jj)))
|
||||||
|
continue;
|
||||||
|
if (ii * ii + jj * jj < nearest_radius_squared
|
||||||
|
&& finite(im->get_pixel(i + ii, j + jj)[k])) {
|
||||||
|
value[k] = im->get_pixel(i + ii, j + jj)[k];
|
||||||
|
nearest_radius_squared = ii * ii + jj * jj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nearest_radius_squared < (radius + 1) * (radius + 1))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel exposure_adjust = (value - minval_pixel)
|
||||||
|
/ (maxval - minval);
|
||||||
|
pixel unlinearized = (e->unlinearize(exposure_adjust)).clamp();
|
||||||
|
|
||||||
|
for (k = 0; k < im->depth(); k++) {
|
||||||
|
|
||||||
|
uint16_t output_value = (uint16_t) ale_real_to_int(unlinearized[k], mcv);
|
||||||
|
|
||||||
|
if (plain) {
|
||||||
|
fprintf(f, "%d ", output_value);
|
||||||
|
} else {
|
||||||
|
if (mcv > 255)
|
||||||
|
fprintf(f, "%c", output_value >> 8);
|
||||||
|
fprintf(f, "%c", 0xff & output_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plain)
|
||||||
|
fprintf(f, "\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
34
d2/render.cc
Normal file
34
d2/render.cc
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See align.h for details on these variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned int render::rx_count;
|
||||||
|
exclusion *render::rx_parameters;
|
||||||
|
int render::rx_show;
|
||||||
|
render *render::directory[ACTIVE_RENDERER_COUNT];
|
||||||
|
int render::directory_length;
|
||||||
|
int render::extend;
|
||||||
|
ale_pos render::scale_factor;
|
||||||
|
ale_real render::wt = 1 / (ale_real) 10000;
|
||||||
376
d2/render.h
Normal file
376
d2/render.h
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
// Copyright 2002, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* render.h: A superclass for all rendering classes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __render_h__
|
||||||
|
#define __render_h__
|
||||||
|
|
||||||
|
#include "transformation.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "point.h"
|
||||||
|
|
||||||
|
#define ACTIVE_RENDERER_COUNT 30
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class render accepts messages synchronizing rendering steps through the
|
||||||
|
* methods sync(n) and sync(), and returns information about the currently
|
||||||
|
* rendered image via methods get_image() and get_defined(). This class is
|
||||||
|
* abstract, and must be subclassed to be instantiated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class render {
|
||||||
|
private:
|
||||||
|
static unsigned int rx_count;
|
||||||
|
static exclusion *rx_parameters;
|
||||||
|
static int rx_show;
|
||||||
|
static render *directory[ACTIVE_RENDERER_COUNT];
|
||||||
|
static int directory_length;
|
||||||
|
static int extend;
|
||||||
|
static ale_pos scale_factor;
|
||||||
|
static ale_real wt;
|
||||||
|
|
||||||
|
image **queue;
|
||||||
|
unsigned int queue_size;
|
||||||
|
int step_num;
|
||||||
|
int entry_number;
|
||||||
|
|
||||||
|
static int strpfix(const char *a, const char *b) {
|
||||||
|
return strncmp(a, b, strlen(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
if (directory_length >= ACTIVE_RENDERER_COUNT) {
|
||||||
|
fprintf(stderr, "\n\n*** Too many renderers in d2::render::render() ***\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
directory[directory_length] = this;
|
||||||
|
entry_number = directory_length;
|
||||||
|
|
||||||
|
directory_length++;
|
||||||
|
|
||||||
|
step_num = -1;
|
||||||
|
queue = NULL;
|
||||||
|
queue_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get extension state
|
||||||
|
*/
|
||||||
|
int is_extend() {
|
||||||
|
return extend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the scale factor
|
||||||
|
*/
|
||||||
|
ale_pos get_scale_factor() {
|
||||||
|
return scale_factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the current step number
|
||||||
|
*/
|
||||||
|
|
||||||
|
int get_step() {
|
||||||
|
return step_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform the current rendering step.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void step() = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for render-coordinate excluded regions. (Applies an offset to
|
||||||
|
* spatial coordinates internally.)
|
||||||
|
*/
|
||||||
|
static int is_excluded_r(point offset, point p, int f) {
|
||||||
|
|
||||||
|
for (unsigned int param = 0; param < rx_count; param++)
|
||||||
|
if (rx_parameters[param].type == exclusion::RENDER
|
||||||
|
&& p[0] + offset[0] >= rx_parameters[param].x[0]
|
||||||
|
&& p[0] + offset[0] <= rx_parameters[param].x[1]
|
||||||
|
&& p[1] + offset[1] >= rx_parameters[param].x[2]
|
||||||
|
&& p[1] + offset[1] <= rx_parameters[param].x[3]
|
||||||
|
&& f >= rx_parameters[param].x[4]
|
||||||
|
&& f <= rx_parameters[param].x[5])
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int is_excluded_r(point offset, int i, int j, int f) {
|
||||||
|
|
||||||
|
for (unsigned int param = 0; param < rx_count; param++)
|
||||||
|
if (rx_parameters[param].type == exclusion::RENDER
|
||||||
|
&& i + offset[0] >= rx_parameters[param].x[0]
|
||||||
|
&& i + offset[0] <= rx_parameters[param].x[1]
|
||||||
|
&& j + offset[1] >= rx_parameters[param].x[2]
|
||||||
|
&& j + offset[1] <= rx_parameters[param].x[3]
|
||||||
|
&& f >= rx_parameters[param].x[4]
|
||||||
|
&& f <= rx_parameters[param].x[5])
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int is_excluded_r(int i, int j, int f) {
|
||||||
|
return is_excluded_r(get_image()->offset(), i, j, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for frame-coordinate excluded regions.
|
||||||
|
*/
|
||||||
|
static int is_excluded_f(point p, int f) {
|
||||||
|
|
||||||
|
for (unsigned int param = 0; param < rx_count; param++)
|
||||||
|
if (rx_parameters[param].type == exclusion::FRAME
|
||||||
|
&& p[0] >= rx_parameters[param].x[0]
|
||||||
|
&& p[0] <= rx_parameters[param].x[1]
|
||||||
|
&& p[1] >= rx_parameters[param].x[2]
|
||||||
|
&& p[1] <= rx_parameters[param].x[3]
|
||||||
|
&& f >= rx_parameters[param].x[4]
|
||||||
|
&& f <= rx_parameters[param].x[5])
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int is_excluded_f(int i, int j, int f) {
|
||||||
|
|
||||||
|
for (unsigned int param = 0; param < rx_count; param++)
|
||||||
|
if (rx_parameters[param].type == exclusion::FRAME
|
||||||
|
&& i >= rx_parameters[param].x[0]
|
||||||
|
&& i <= rx_parameters[param].x[1]
|
||||||
|
&& j >= rx_parameters[param].x[2]
|
||||||
|
&& j <= rx_parameters[param].x[3]
|
||||||
|
&& f >= rx_parameters[param].x[4]
|
||||||
|
&& f <= rx_parameters[param].x[5])
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int render_count() {
|
||||||
|
return directory_length;
|
||||||
|
}
|
||||||
|
static render *render_num(int n) {
|
||||||
|
assert (n < directory_length);
|
||||||
|
return directory[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void render_init(unsigned int _rx_count, exclusion *_rx_parameters,
|
||||||
|
int _rx_show, int _extend, ale_pos _scale_factor) {
|
||||||
|
rx_count = _rx_count;
|
||||||
|
rx_show = _rx_show;
|
||||||
|
extend = _extend;
|
||||||
|
scale_factor = _scale_factor;
|
||||||
|
|
||||||
|
rx_parameters = (exclusion *) malloc(rx_count * sizeof(exclusion));
|
||||||
|
|
||||||
|
for (unsigned int region = 0; region < rx_count; region++) {
|
||||||
|
|
||||||
|
rx_parameters[region] = _rx_parameters[region];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scale spatial rendering coordinates
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (rx_parameters[region].type == exclusion::RENDER)
|
||||||
|
for (int p = 0; p < 4; p++)
|
||||||
|
rx_parameters[region].x[p] *= scale_factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_wt(ale_real _wt) {
|
||||||
|
wt = _wt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ale_real get_wt() {
|
||||||
|
return wt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_rx_show() {
|
||||||
|
return rx_show;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int get_rx_count() {
|
||||||
|
return rx_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const exclusion *get_rx_parameters() {
|
||||||
|
return rx_parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Current rendering result.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual const image *get_image() const = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Result of rendering at the given frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const image *get_image(unsigned int n) {
|
||||||
|
sync(n);
|
||||||
|
|
||||||
|
if (n == (unsigned int) step_num)
|
||||||
|
return get_image();
|
||||||
|
|
||||||
|
n = step_num - n - 1;
|
||||||
|
|
||||||
|
assert (n < queue_size);
|
||||||
|
|
||||||
|
return queue[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extend the rendering queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void extend_queue(unsigned int n) {
|
||||||
|
/*
|
||||||
|
* Increase the size of the queue, if necessary, to
|
||||||
|
* accommodate the given lag.
|
||||||
|
*/
|
||||||
|
if (n > queue_size) {
|
||||||
|
unsigned int new_size = n;
|
||||||
|
queue = (image **) realloc(queue, new_size * sizeof(image *));
|
||||||
|
assert(queue);
|
||||||
|
if (queue == NULL) {
|
||||||
|
fprintf(stderr, "\n\n*** VISE: Unable to allocate memory ***\n\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(queue + queue_size, 0, (new_size - queue_size) * sizeof(image *));
|
||||||
|
queue_size = new_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition map. Unit-depth image whose pixels are nonzero where
|
||||||
|
* the image is defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual const image *get_defined() const = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sync.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void sync(int n) {
|
||||||
|
assert (step_num >= -1);
|
||||||
|
for (int i = step_num + 1; i <= n; i++) {
|
||||||
|
if (queue_size > 0 && step_num >= 0) {
|
||||||
|
/*
|
||||||
|
* Shift the current queue so that the new head remains at the
|
||||||
|
* zero index. There are more time-efficient ways to handle
|
||||||
|
* queues, but the benefits are not clear in this case.
|
||||||
|
*/
|
||||||
|
delete queue[queue_size - 1];
|
||||||
|
for (int i = queue_size - 1; i > 0; i--) {
|
||||||
|
queue[i] = queue[i - 1];
|
||||||
|
}
|
||||||
|
queue[0] = get_image()->clone("Render queue clone");
|
||||||
|
}
|
||||||
|
|
||||||
|
step_num++;
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform any final rendering steps. Return a non-zero value if
|
||||||
|
* anything changed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual int sync() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set point rendering bounds, if possible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void init_point_renderer(unsigned int h, unsigned int w, unsigned int d) {
|
||||||
|
assert(0);
|
||||||
|
fprintf(stderr, "Error: init_point_renderer() not supported by this renderer\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point render.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void point_render(unsigned int i, unsigned int j, unsigned int f, transformation t) {
|
||||||
|
assert(0);
|
||||||
|
fprintf(stderr, "Error: point_render() not supported by this renderer\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish point rendering.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void finish_point_rendering() {
|
||||||
|
assert(0);
|
||||||
|
fprintf(stderr, "Error: finish_point_rendering() not supported by this renderer\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~render() {
|
||||||
|
directory[entry_number] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int entry() {
|
||||||
|
return entry_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void free_memory() = 0;
|
||||||
|
|
||||||
|
static void free_entry(int n) {
|
||||||
|
if (directory[n] != NULL) {
|
||||||
|
directory[n]->free_memory();
|
||||||
|
delete directory[n];
|
||||||
|
directory[n] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_all_memory() {
|
||||||
|
for (int i = 0; i < ACTIVE_RENDERER_COUNT; i++)
|
||||||
|
free_entry(i);
|
||||||
|
|
||||||
|
directory_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset() {
|
||||||
|
free_all_memory();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
519
d2/render/combine.h
Normal file
519
d2/render/combine.h
Normal file
@@ -0,0 +1,519 @@
|
|||||||
|
// Copyright 2002, 2007 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* combine.h: A renderer that combines two renderings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __combine_h__
|
||||||
|
#define __combine_h__
|
||||||
|
|
||||||
|
#include "../transformation.h"
|
||||||
|
#include "../image.h"
|
||||||
|
#include "../point.h"
|
||||||
|
#include "incremental.h"
|
||||||
|
#include "../filter/filter.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Combine two renderings.
|
||||||
|
*
|
||||||
|
* Available data is taken from the PARTIAL rendering. When no data from
|
||||||
|
* the PARTIAL rendering is available, data from the DEFAULT rendering
|
||||||
|
* is substituted.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class combine : public render {
|
||||||
|
private:
|
||||||
|
render *_default;
|
||||||
|
render *partial;
|
||||||
|
mutable image *output_image;
|
||||||
|
mutable image *defined_image;
|
||||||
|
int synced;
|
||||||
|
|
||||||
|
class refilter : public thread::decompose_domain {
|
||||||
|
combine *c;
|
||||||
|
const render *fine;
|
||||||
|
const render *coarse;
|
||||||
|
const filter::filter *f;
|
||||||
|
const image *fine_weight;
|
||||||
|
const image *fine_image;
|
||||||
|
const image *coarse_image;
|
||||||
|
const image *coarse_defined;
|
||||||
|
image *output_image;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to determine a distance by finding two nearby defined
|
||||||
|
* pixels, such that each pixel is in a 90-degree axis-aligned
|
||||||
|
* cone opposite the other.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_pos find_nonzero_weight_distance(int i, int j, int k) {
|
||||||
|
|
||||||
|
assert (i >= 0);
|
||||||
|
assert (j >= 0);
|
||||||
|
assert (i < (int) coarse_defined->height());
|
||||||
|
assert (j < (int) coarse_defined->width());
|
||||||
|
|
||||||
|
assert (coarse_defined->get_chan(i, j, k) > 0);
|
||||||
|
|
||||||
|
ale_pos zero = +0.0;
|
||||||
|
ale_pos one = +1.0;
|
||||||
|
|
||||||
|
ale_pos nearest = one / zero;
|
||||||
|
|
||||||
|
assert (isinf(nearest) && nearest > 0);
|
||||||
|
|
||||||
|
int radius = 0;
|
||||||
|
int in_bounds = 1;
|
||||||
|
|
||||||
|
int coords[2];
|
||||||
|
|
||||||
|
while (radius < nearest && in_bounds) {
|
||||||
|
in_bounds = 0;
|
||||||
|
|
||||||
|
for (int ii = i - radius; ii <= i + radius; ii++)
|
||||||
|
for (int jj = j - radius; jj <= j + radius;
|
||||||
|
jj += ((abs(i - ii) == radius)
|
||||||
|
? 1
|
||||||
|
: radius * 2)) {
|
||||||
|
if (ii < 0
|
||||||
|
|| jj < 0
|
||||||
|
|| ii >= (int) coarse_defined->height()
|
||||||
|
|| jj >= (int) coarse_defined->width()
|
||||||
|
|| !(coarse_defined->get_chan(ii, jj, k) > 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
in_bounds = 1;
|
||||||
|
|
||||||
|
if (!(fine_weight->get_chan(ii, jj, k) > 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ale_pos distance = sqrt( (ale_pos) ((i - ii) * (i - ii)
|
||||||
|
+ (j - jj) * (j - jj)));
|
||||||
|
|
||||||
|
if (distance < nearest) {
|
||||||
|
nearest = distance;
|
||||||
|
coords[0] = ii;
|
||||||
|
coords[1] = jj;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
radius++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isinf(nearest))
|
||||||
|
return nearest;
|
||||||
|
|
||||||
|
int cone_axis = 0;
|
||||||
|
int cone_dir = 1;
|
||||||
|
|
||||||
|
if (abs(coords[0] - i) < abs(coords[1] - j))
|
||||||
|
cone_axis = 1;
|
||||||
|
|
||||||
|
int orig_coords[2] = {i, j};
|
||||||
|
|
||||||
|
if (coords[cone_axis] - orig_coords[cone_axis] > 0)
|
||||||
|
cone_dir = -1;
|
||||||
|
|
||||||
|
nearest = one / zero;
|
||||||
|
|
||||||
|
assert (isinf(nearest) && nearest > 0);
|
||||||
|
|
||||||
|
radius = 1;
|
||||||
|
in_bounds = 1;
|
||||||
|
|
||||||
|
int coords2[2];
|
||||||
|
|
||||||
|
i = coords[0];
|
||||||
|
j = coords[1];
|
||||||
|
|
||||||
|
while (radius < nearest && in_bounds) {
|
||||||
|
in_bounds = 0;
|
||||||
|
|
||||||
|
coords2[cone_axis] = orig_coords[cone_axis] + radius * cone_dir;
|
||||||
|
|
||||||
|
for (coords2[1 - cone_axis] = orig_coords[1 - cone_axis] - radius;
|
||||||
|
coords2[1 - cone_axis] < orig_coords[1 - cone_axis] + radius;
|
||||||
|
coords2[1 - cone_axis]++) {
|
||||||
|
|
||||||
|
int ii = coords2[0];
|
||||||
|
int jj = coords2[1];
|
||||||
|
|
||||||
|
if (ii < 0
|
||||||
|
|| jj < 0
|
||||||
|
|| ii >= (int) coarse_defined->height()
|
||||||
|
|| jj >= (int) coarse_defined->width()
|
||||||
|
|| !(coarse_defined->get_chan(ii, jj, k) > 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
in_bounds = 1;
|
||||||
|
|
||||||
|
if (!(fine_weight->get_chan(ii, jj, k) > 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ale_pos distance = sqrt( (ale_pos) ((i - ii) * (i - ii)
|
||||||
|
+ (j - jj) * (j - jj)));
|
||||||
|
|
||||||
|
if (distance < nearest)
|
||||||
|
nearest = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
radius++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void subdomain_algorithm(unsigned int thread,
|
||||||
|
int i_min, int i_max, int j_min, int j_max) {
|
||||||
|
|
||||||
|
for (int i = i_min; i < i_max; i++)
|
||||||
|
for (int j = j_min; j < j_max; j++)
|
||||||
|
for (unsigned int k = 0; k < 3; k++){
|
||||||
|
|
||||||
|
if (!(coarse_defined->get_chan(i, j, k) > 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ale_pos filter_scale = 1;
|
||||||
|
ale_real filtered_weight;
|
||||||
|
ale_real filtered_value;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to set an initial filter scale based
|
||||||
|
* on the proximity of two nearby k-defined
|
||||||
|
* pixels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_pos n1 = find_nonzero_weight_distance(i, j, k);
|
||||||
|
|
||||||
|
if (!finite(n1)) {
|
||||||
|
output_image->set_chan(i, j, k, coarse_image->get_pixel(i, j)[k]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter_scale = n1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
filtered_weight = 0;
|
||||||
|
filtered_value = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lrintf() may be faster than ceil/floor() on some architectures.
|
||||||
|
* See render/psf/raster.h for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int support_extreme = (int) lrintf(f->support() * filter_scale);
|
||||||
|
assert (support_extreme >= 0);
|
||||||
|
|
||||||
|
for (int ii = -support_extreme;
|
||||||
|
ii < support_extreme; ii++)
|
||||||
|
for (int jj = -support_extreme;
|
||||||
|
jj < support_extreme; jj++) {
|
||||||
|
|
||||||
|
if (ii + i < 0
|
||||||
|
|| jj + j < 0
|
||||||
|
|| ii + i >= (int) fine_weight->height()
|
||||||
|
|| jj + j >= (int) fine_weight->width())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ale_real pw = fine_weight->get_chan(i + ii, j + jj, k);
|
||||||
|
|
||||||
|
if (!(pw > 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: Set the weight to one
|
||||||
|
* for now, to prevent
|
||||||
|
* interference from certainty
|
||||||
|
* values calculated under
|
||||||
|
* different assumptions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pw = 1;
|
||||||
|
|
||||||
|
ale_real w = pw * f->response(point(ii / filter_scale,
|
||||||
|
jj / filter_scale));
|
||||||
|
|
||||||
|
ale_real v = fine_image->get_pixel(i + ii, j + jj)[k];
|
||||||
|
|
||||||
|
if (!finite(w) || !finite(v))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
filtered_weight += w;
|
||||||
|
filtered_value += w * v;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filtered_weight < render::get_wt())
|
||||||
|
/* filter_scale += 1; */
|
||||||
|
filter_scale *= 2;
|
||||||
|
|
||||||
|
} while (filtered_weight < render::get_wt()
|
||||||
|
&& filter_scale < coarse_defined->width()
|
||||||
|
+ coarse_defined->height());
|
||||||
|
|
||||||
|
output_image->set_chan(i, j, k, filtered_value / filtered_weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
refilter(combine *_c,
|
||||||
|
const render *_fine,
|
||||||
|
const render *_coarse,
|
||||||
|
const filter::filter *_f,
|
||||||
|
const image *_fine_weight,
|
||||||
|
const image *_fine_image,
|
||||||
|
const image *_coarse_image,
|
||||||
|
const image *_coarse_defined,
|
||||||
|
image *_output_image) : decompose_domain(0, _coarse_defined->height(),
|
||||||
|
0, _coarse_defined->width()) {
|
||||||
|
|
||||||
|
c = _c;
|
||||||
|
fine = _fine;
|
||||||
|
coarse = _coarse;
|
||||||
|
f = _f;
|
||||||
|
fine_weight = _fine_weight;
|
||||||
|
fine_image = _fine_image;
|
||||||
|
coarse_image = _coarse_image;
|
||||||
|
coarse_defined = _coarse_defined;
|
||||||
|
output_image = _output_image;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const image *get_image_dynamic() const {
|
||||||
|
assert(typeid(*partial) == typeid(incremental));
|
||||||
|
|
||||||
|
if (typeid(*_default) != typeid(combine) || !synced) {
|
||||||
|
/*
|
||||||
|
* Degenerate case.
|
||||||
|
*/
|
||||||
|
output_image = _default->get_image()->clone("degenerate dynamic filter");
|
||||||
|
return output_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
combine *c = (combine *)_default;
|
||||||
|
const render *fine = c->get_partial();
|
||||||
|
const render *coarse = c->get_default();
|
||||||
|
const filter::filter *f = ((incremental *)partial)->get_invariant()->ssfe()->
|
||||||
|
get_scaled_filter()->get_filter();
|
||||||
|
const image *fine_weight = fine->get_defined();
|
||||||
|
const image *fine_image = fine->get_image();
|
||||||
|
const image *coarse_image = coarse->get_image();
|
||||||
|
const image *coarse_defined = coarse->get_defined();
|
||||||
|
|
||||||
|
output_image = new_image_ale_real(coarse_defined->height(),
|
||||||
|
coarse_defined->width(), 3, NULL);
|
||||||
|
|
||||||
|
output_image->set_offset(coarse_defined->offset());
|
||||||
|
|
||||||
|
assert (coarse_defined->width() == fine_image->width());
|
||||||
|
assert (coarse_defined->height() == fine_image->height());
|
||||||
|
assert (coarse_defined->width() == fine_weight->width());
|
||||||
|
assert (coarse_defined->height() == fine_weight->height());
|
||||||
|
|
||||||
|
ui::get()->refilter_start();
|
||||||
|
|
||||||
|
refilter r(c, fine, coarse, f, fine_weight, fine_image, coarse_image,
|
||||||
|
coarse_defined, output_image);
|
||||||
|
r.run();
|
||||||
|
|
||||||
|
ui::get()->refilter_done();
|
||||||
|
|
||||||
|
return output_image;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
combine(render *_default, render *partial) {
|
||||||
|
this->_default = _default;
|
||||||
|
this->partial = partial;
|
||||||
|
this->output_image = NULL;
|
||||||
|
this->defined_image = NULL;
|
||||||
|
this->synced = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~combine() {
|
||||||
|
if (output_image)
|
||||||
|
delete output_image;
|
||||||
|
if (defined_image)
|
||||||
|
delete defined_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Result of rendering.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual const image *get_image() const {
|
||||||
|
|
||||||
|
if (output_image)
|
||||||
|
return output_image;
|
||||||
|
|
||||||
|
assert(typeid(*partial) != typeid(combine));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dynamic filtering is handled separately.
|
||||||
|
*/
|
||||||
|
if (typeid(*partial) == typeid(incremental)
|
||||||
|
&& (((incremental *)partial)->get_invariant()->
|
||||||
|
ssfe()->get_scaled_filter()->is_dynamic()))
|
||||||
|
return get_image_dynamic();
|
||||||
|
|
||||||
|
const image *default_image = _default->get_image();
|
||||||
|
|
||||||
|
output_image = new_image_ale_real(default_image->height(),
|
||||||
|
default_image->width(), 3, NULL);
|
||||||
|
|
||||||
|
output_image->set_offset(default_image->offset());
|
||||||
|
|
||||||
|
const image *partial_image = partial->get_image();
|
||||||
|
const image *partial_weight = partial->get_defined();
|
||||||
|
|
||||||
|
assert (default_image->width() == partial_image->width());
|
||||||
|
assert (default_image->height() == partial_image->height());
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < default_image->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < default_image->width(); j++)
|
||||||
|
output_image->set_pixel(i, j,
|
||||||
|
((ale_real) ((pixel) partial_weight->get_pixel(i, j)).min_norm()
|
||||||
|
>= render::get_wt())
|
||||||
|
? partial_image->get_pixel(i, j)
|
||||||
|
: default_image->get_pixel(i, j));
|
||||||
|
|
||||||
|
return output_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition map. Unit-depth image whose pixels are nonzero where
|
||||||
|
* the image is defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual const image *get_defined() const {
|
||||||
|
unsigned int i, j, k;
|
||||||
|
|
||||||
|
if (defined_image)
|
||||||
|
return defined_image;
|
||||||
|
|
||||||
|
const image *partial_weight = partial->get_defined();
|
||||||
|
const image *default_weight = _default->get_defined();
|
||||||
|
|
||||||
|
assert (default_weight->width() == partial_weight->width());
|
||||||
|
assert (default_weight->height() == partial_weight->height());
|
||||||
|
|
||||||
|
defined_image = new_image_ale_real(default_weight->height(),
|
||||||
|
default_weight->width(), 3, NULL);
|
||||||
|
|
||||||
|
defined_image->set_offset(default_weight->offset());
|
||||||
|
|
||||||
|
for (i = 0; i < default_weight->height(); i++)
|
||||||
|
for (j = 0; j < default_weight->width(); j++)
|
||||||
|
for (k = 0; k < default_weight->depth(); k++)
|
||||||
|
defined_image->set_pixel(i, j,
|
||||||
|
((ale_real) ((pixel) partial_weight->get_pixel(i, j)).min_norm()
|
||||||
|
>= render::get_wt())
|
||||||
|
? partial_weight->get_pixel(i, j)
|
||||||
|
: default_weight->get_pixel(i, j));
|
||||||
|
|
||||||
|
return defined_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform rendering steps requiring no frames beyond frame N.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void sync(int n) {
|
||||||
|
render::sync(n);
|
||||||
|
if (output_image) {
|
||||||
|
delete output_image;
|
||||||
|
output_image = NULL;
|
||||||
|
}
|
||||||
|
if (defined_image) {
|
||||||
|
delete defined_image;
|
||||||
|
defined_image = NULL;
|
||||||
|
}
|
||||||
|
_default->sync(n);
|
||||||
|
partial->sync(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void step() {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int sync() {
|
||||||
|
if (output_image) {
|
||||||
|
delete output_image;
|
||||||
|
output_image = NULL;
|
||||||
|
}
|
||||||
|
if (defined_image) {
|
||||||
|
delete defined_image;
|
||||||
|
defined_image = NULL;
|
||||||
|
}
|
||||||
|
_default->sync();
|
||||||
|
partial->sync();
|
||||||
|
synced = 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void init_point_renderer(unsigned int h, unsigned int w, unsigned int d) {
|
||||||
|
_default->init_point_renderer(h, w, d);
|
||||||
|
partial->init_point_renderer(h, w, d);
|
||||||
|
output_image = new image_zero(h, w, d);
|
||||||
|
defined_image = new image_zero(h, w, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void point_render(unsigned int i, unsigned int j, unsigned int f, transformation t) {
|
||||||
|
_default->point_render(i, j, f, t);
|
||||||
|
partial->point_render(i, j, f, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void finish_point_rendering() {
|
||||||
|
_default->finish_point_rendering();
|
||||||
|
partial->finish_point_rendering();
|
||||||
|
delete defined_image;
|
||||||
|
delete output_image;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These will be generated upon a call to get_image() or
|
||||||
|
* get_defined().
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined_image = NULL;
|
||||||
|
output_image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const render *get_default() const {
|
||||||
|
return _default;
|
||||||
|
}
|
||||||
|
|
||||||
|
const render *get_partial() const {
|
||||||
|
return partial;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_memory() {
|
||||||
|
delete output_image;
|
||||||
|
delete defined_image;
|
||||||
|
output_image = NULL;
|
||||||
|
defined_image = NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
427
d2/render/incremental.h
Normal file
427
d2/render/incremental.h
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
// Copyright 2002, 2004, 2007 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __incremental_h__
|
||||||
|
#define __incremental_h__
|
||||||
|
|
||||||
|
#include "invariant.h"
|
||||||
|
#include "../render.h"
|
||||||
|
#include "../transformation.h"
|
||||||
|
#include "../image.h"
|
||||||
|
#include "../point.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class for incremental renderers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class incremental : public render {
|
||||||
|
protected:
|
||||||
|
image_weighted_avg *accum_image;
|
||||||
|
invariant *inv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set extents of image and weight according to a new image to be
|
||||||
|
* merged. This function should remove only superfluous undefined
|
||||||
|
* areas.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void set_extents_by_map(unsigned int frame_num, transformation t) {
|
||||||
|
|
||||||
|
assert (accum_image != NULL);
|
||||||
|
|
||||||
|
ale_pos extend_offset_i = accum_image->offset()[0];
|
||||||
|
ale_pos extend_offset_j = accum_image->offset()[1];
|
||||||
|
|
||||||
|
int extend_top = 0;
|
||||||
|
int extend_bottom = 0;
|
||||||
|
int extend_left = 0;
|
||||||
|
int extend_right = 0;
|
||||||
|
|
||||||
|
ale_pos zero = 0;
|
||||||
|
ale_pos infinity = 1 / zero;
|
||||||
|
|
||||||
|
assert (!finite(infinity));
|
||||||
|
assert (!isnan(infinity));
|
||||||
|
assert (infinity > 0);
|
||||||
|
|
||||||
|
point min, max;
|
||||||
|
|
||||||
|
min[0] = min[1] = infinity;
|
||||||
|
max[0] = max[1] = -infinity;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < t.unscaled_height(); i++)
|
||||||
|
for (unsigned int j = 0; j < t.unscaled_width(); j++) {
|
||||||
|
|
||||||
|
if (is_excluded_f(i, j, frame_num))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
point p = t.transform_unscaled(point(i, j));
|
||||||
|
|
||||||
|
if (is_excluded_r(accum_image->offset(), p, frame_num))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (p[0] < min[0]) {
|
||||||
|
min[0] = p[0];
|
||||||
|
}
|
||||||
|
if (p[0] > max[0]) {
|
||||||
|
max[0] = p[0];
|
||||||
|
}
|
||||||
|
if (p[1] < min[1]) {
|
||||||
|
min[1] = p[1];
|
||||||
|
}
|
||||||
|
if (p[1] > max[1]) {
|
||||||
|
max[1] = p[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!finite(max[0])
|
||||||
|
|| !finite(max[1])
|
||||||
|
|| !finite(min[0])
|
||||||
|
|| !finite(min[1]))
|
||||||
|
return;
|
||||||
|
|
||||||
|
extend_top = (int) ceil(extend_offset_i - floor(min[0]));
|
||||||
|
extend_left = (int) ceil(extend_offset_j - floor(min[1]));
|
||||||
|
extend_bottom = (int) ceil(ceil(max[0]) - (ale_pos) (accum_image->height() - 1 + extend_offset_i));
|
||||||
|
extend_right = (int) ceil(ceil(max[1]) - (ale_pos) (accum_image->width() - 1 + extend_offset_j));
|
||||||
|
|
||||||
|
accum_image->_extend(extend_top, extend_bottom,
|
||||||
|
extend_left, extend_right);
|
||||||
|
}
|
||||||
|
|
||||||
|
void increase_extents_by_map(unsigned int frame_num, transformation t) {
|
||||||
|
|
||||||
|
assert (accum_image != NULL);
|
||||||
|
|
||||||
|
ale_pos extend_offset_i = accum_image->offset()[0];
|
||||||
|
ale_pos extend_offset_j = accum_image->offset()[1];
|
||||||
|
|
||||||
|
int extend_top = 0;
|
||||||
|
int extend_bottom = 0;
|
||||||
|
int extend_left = 0;
|
||||||
|
int extend_right = 0;
|
||||||
|
|
||||||
|
double zero = 0;
|
||||||
|
double infinity = 1 / zero;
|
||||||
|
|
||||||
|
assert (!finite(infinity));
|
||||||
|
assert (!isnan(infinity));
|
||||||
|
assert (infinity > 0);
|
||||||
|
|
||||||
|
point min, max;
|
||||||
|
|
||||||
|
min[0] = min[1] = infinity;
|
||||||
|
max[0] = max[1] = -infinity;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < t.unscaled_height(); i++)
|
||||||
|
for (unsigned int j = 0; j < t.unscaled_width(); j++) {
|
||||||
|
|
||||||
|
if (is_excluded_f(i, j, frame_num))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
point p = t.transform_unscaled(point(i, j));
|
||||||
|
|
||||||
|
if (is_excluded_r(point(0, 0), p, frame_num))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (p[0] < min[0]) {
|
||||||
|
min[0] = p[0];
|
||||||
|
}
|
||||||
|
if (p[0] > max[0]) {
|
||||||
|
max[0] = p[0];
|
||||||
|
}
|
||||||
|
if (p[1] < min[1]) {
|
||||||
|
min[1] = p[1];
|
||||||
|
}
|
||||||
|
if (p[1] > max[1]) {
|
||||||
|
max[1] = p[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!finite(max[0])
|
||||||
|
|| !finite(max[1])
|
||||||
|
|| !finite(min[0])
|
||||||
|
|| !finite(min[1]))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ceil(min[0]) < extend_offset_i)
|
||||||
|
extend_top = (int) ceil(extend_offset_i - floor(min[0]));
|
||||||
|
if (ceil(min[1]) < extend_offset_j)
|
||||||
|
extend_left = (int) ceil(extend_offset_j - floor(min[1]));
|
||||||
|
if (floor(max[0]) > accum_image->height() - 1 + extend_offset_i)
|
||||||
|
extend_bottom = (int) ceil(ceil(max[0]) - (ale_pos) (accum_image->height() - 1 + extend_offset_i));
|
||||||
|
if (floor(max[1]) > accum_image->width() - 1 + extend_offset_j)
|
||||||
|
extend_right = (int) ceil(ceil(max[1]) - (ale_pos) (accum_image->width() - 1 + extend_offset_j));
|
||||||
|
|
||||||
|
accum_image->_extend(extend_top, extend_bottom,
|
||||||
|
extend_left, extend_right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Merge operation for a single pixel in the accumulated image.
|
||||||
|
*/
|
||||||
|
void _merge_pixel(int frame, const image *delta, transformation t, int i, int j, const filter::ssfe *_ssfe) {
|
||||||
|
|
||||||
|
if (_ssfe->ex_is_honored() && is_excluded_r(i, j, frame))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (accum_image->accumulate_norender(i, j))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pixel value to be merged, and the associated
|
||||||
|
* confidence
|
||||||
|
*/
|
||||||
|
|
||||||
|
pixel value, confidence;
|
||||||
|
|
||||||
|
if (exposure::get_confidence() != 0) {
|
||||||
|
_ssfe->filtered(i, j, frame, &value, &confidence, ((pixel) accum_image->get_pixel(i, j)), accum_image->get_weights()->get_pixel(i, j));
|
||||||
|
} else {
|
||||||
|
_ssfe->filtered(i, j, frame, &value, &confidence);
|
||||||
|
}
|
||||||
|
|
||||||
|
accum_image->accumulate(i, j, frame, value, confidence);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Merge part of a delta frame with part of the accumulated image using
|
||||||
|
* the specified transformation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class merge : public thread::decompose_domain {
|
||||||
|
incremental *instance;
|
||||||
|
int frame;
|
||||||
|
const image *delta;
|
||||||
|
transformation t;
|
||||||
|
invariant *inv;
|
||||||
|
image_weighted_avg *accum_image;
|
||||||
|
protected:
|
||||||
|
void prepare_subdomains(unsigned int N) {
|
||||||
|
ale_pos_disable_casting();
|
||||||
|
ale_real_disable_casting();
|
||||||
|
ale_accum_disable_casting();
|
||||||
|
}
|
||||||
|
void subdomain_algorithm(unsigned int thread,
|
||||||
|
int i_min, int i_max, int j_min, int j_max) {
|
||||||
|
|
||||||
|
point offset = accum_image->offset();
|
||||||
|
|
||||||
|
assert (accum_image != NULL);
|
||||||
|
assert (delta != NULL);
|
||||||
|
|
||||||
|
const filter::ssfe *_ssfe = inv->ssfe();
|
||||||
|
|
||||||
|
for (int i = i_min; i < i_max; i++)
|
||||||
|
for (int j = j_min; j < j_max; j++) {
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This is untested, but it should work, and is less
|
||||||
|
* verbose than what follows.
|
||||||
|
*/
|
||||||
|
|
||||||
|
instance->_merge_pixel(frame, delta, t, i, j, _ssfe);
|
||||||
|
#else
|
||||||
|
|
||||||
|
if (_ssfe->ex_is_honored() && instance->is_excluded_r(i, j, frame))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (accum_image->accumulate_norender(i, j))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pixel value to be merged, and the associated
|
||||||
|
* confidence
|
||||||
|
*/
|
||||||
|
|
||||||
|
pixel value, confidence;
|
||||||
|
|
||||||
|
if (exposure::get_confidence() != 0) {
|
||||||
|
_ssfe->filtered(i, j, frame, &value, &confidence,
|
||||||
|
((pixel) accum_image->get_pixel(i, j)),
|
||||||
|
accum_image->get_weights()->get_pixel(i, j));
|
||||||
|
} else {
|
||||||
|
_ssfe->filtered(i, j, frame, &value, &confidence);
|
||||||
|
}
|
||||||
|
|
||||||
|
accum_image->accumulate(i, j, frame, value, confidence);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void finish_subdomains(unsigned int N) {
|
||||||
|
ale_pos_enable_casting();
|
||||||
|
ale_real_enable_casting();
|
||||||
|
ale_accum_enable_casting();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
merge(incremental *_instance,
|
||||||
|
int _frame,
|
||||||
|
const image *_delta,
|
||||||
|
transformation _t) : decompose_domain(0, _instance->accum_image->height(),
|
||||||
|
0, _instance->accum_image->width()),
|
||||||
|
t(_t) {
|
||||||
|
|
||||||
|
instance = _instance;
|
||||||
|
frame = _frame;
|
||||||
|
delta = _delta;
|
||||||
|
t = _t;
|
||||||
|
|
||||||
|
inv = instance->inv;
|
||||||
|
accum_image = instance->accum_image;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
_merge(int frame, const image *delta, transformation t) {
|
||||||
|
|
||||||
|
ui::get()->d2_incremental_start();
|
||||||
|
|
||||||
|
point offset = accum_image->offset();
|
||||||
|
|
||||||
|
assert (accum_image != NULL);
|
||||||
|
assert (delta != NULL);
|
||||||
|
|
||||||
|
const filter::ssfe *_ssfe = inv->ssfe();
|
||||||
|
|
||||||
|
_ssfe->set_parameters(t, delta, offset);
|
||||||
|
|
||||||
|
merge m(this, frame, delta, t);
|
||||||
|
m.run();
|
||||||
|
|
||||||
|
ui::get()->d2_incremental_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
incremental(invariant *inv) {
|
||||||
|
this->inv = inv;
|
||||||
|
accum_image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invariant
|
||||||
|
*/
|
||||||
|
const invariant *get_invariant() const {
|
||||||
|
return inv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Result of rendering.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual const image *get_image() const {
|
||||||
|
assert (accum_image != NULL);
|
||||||
|
return accum_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition map. Unit-depth image whose pixels are nonzero where
|
||||||
|
* the image is defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual const image *get_defined() const {
|
||||||
|
assert (accum_image != NULL);
|
||||||
|
return accum_image->get_weights();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform the current rendering step.
|
||||||
|
*/
|
||||||
|
virtual void step() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dynamic invariants are not incrementally updated.
|
||||||
|
*/
|
||||||
|
if (inv->ssfe()->get_scaled_filter()->is_dynamic()) {
|
||||||
|
/*
|
||||||
|
* Create a trivial image for the case where there is
|
||||||
|
* no chain suffix.
|
||||||
|
*/
|
||||||
|
if (accum_image == NULL)
|
||||||
|
accum_image = new image_weighted_simple(1, 1, 3, inv);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (get_step() >= -1);
|
||||||
|
if (get_step() == 0) {
|
||||||
|
transformation t = align::of(0);
|
||||||
|
|
||||||
|
const image *im = image_rw::open(0);
|
||||||
|
|
||||||
|
ui::get()->rendering();
|
||||||
|
if (inv->is_median())
|
||||||
|
accum_image = new image_weighted_median(1, 1, 3);
|
||||||
|
else
|
||||||
|
accum_image = new image_weighted_simple(1, 1, 3, inv);
|
||||||
|
|
||||||
|
set_extents_by_map(0, t);
|
||||||
|
|
||||||
|
_merge(0, im, t);
|
||||||
|
|
||||||
|
image_rw::close(0);
|
||||||
|
} else if (align::match(get_step())) {
|
||||||
|
transformation t = align::of(get_step());
|
||||||
|
ui::get()->rendering();
|
||||||
|
if (is_extend())
|
||||||
|
increase_extents_by_map(get_step(), t);
|
||||||
|
const image *im = image_rw::open(get_step());
|
||||||
|
_merge(get_step(), im, t);
|
||||||
|
image_rw::close(get_step());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void init_point_renderer(unsigned int h, unsigned int w, unsigned int d) {
|
||||||
|
assert(accum_image == NULL);
|
||||||
|
|
||||||
|
if (inv->is_median())
|
||||||
|
accum_image = new image_weighted_median(h, w, d);
|
||||||
|
else
|
||||||
|
accum_image = new image_weighted_simple(h, w, d, inv);
|
||||||
|
|
||||||
|
assert(accum_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void point_render(unsigned int i, unsigned int j, unsigned int f, transformation t) {
|
||||||
|
const image *im = d2::image_rw::get_open(f);
|
||||||
|
|
||||||
|
const filter::ssfe *_ssfe = inv->ssfe();
|
||||||
|
|
||||||
|
_ssfe->set_parameters(t, im, accum_image->offset());
|
||||||
|
_merge_pixel(f, im, t, i, j, _ssfe);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void finish_point_rendering() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_memory() {
|
||||||
|
delete accum_image;
|
||||||
|
accum_image = NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
117
d2/render/invariant.h
Normal file
117
d2/render/invariant.h
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __invariant_h__
|
||||||
|
#define __invariant_h__
|
||||||
|
|
||||||
|
#include "../filter.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class for incremental renderer invariants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define min 0
|
||||||
|
#define max 1
|
||||||
|
#define avg 2
|
||||||
|
#define first 3
|
||||||
|
#define last 4
|
||||||
|
#define median 5
|
||||||
|
#define avgf 6
|
||||||
|
|
||||||
|
class invariant {
|
||||||
|
public:
|
||||||
|
int type;
|
||||||
|
double type_param;
|
||||||
|
filter::ssfe *s;
|
||||||
|
|
||||||
|
invariant(filter::ssfe *s) {
|
||||||
|
this->s = s;
|
||||||
|
type = 2;
|
||||||
|
type_param = 0;
|
||||||
|
}
|
||||||
|
int equals(const invariant *i) const {
|
||||||
|
return (i->type == type
|
||||||
|
&& i->type_param == type_param
|
||||||
|
&& s->equals(i->ssfe()));
|
||||||
|
}
|
||||||
|
const filter::ssfe *ssfe() const {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
int is_max() const {
|
||||||
|
return type == max;
|
||||||
|
}
|
||||||
|
int is_min() const {
|
||||||
|
return type == min;
|
||||||
|
}
|
||||||
|
int is_avg() const {
|
||||||
|
return type == avg;
|
||||||
|
}
|
||||||
|
int is_avgf() const {
|
||||||
|
return type == avgf;
|
||||||
|
}
|
||||||
|
int is_avgx() const {
|
||||||
|
return (type == avg || type == avgf);
|
||||||
|
}
|
||||||
|
int is_first() const {
|
||||||
|
return type == first;
|
||||||
|
}
|
||||||
|
int is_last() const {
|
||||||
|
return type == last;
|
||||||
|
}
|
||||||
|
int is_median() const {
|
||||||
|
return type == median;
|
||||||
|
}
|
||||||
|
void set_max() {
|
||||||
|
type = max;
|
||||||
|
}
|
||||||
|
void set_min() {
|
||||||
|
type = min;
|
||||||
|
}
|
||||||
|
void set_avg() {
|
||||||
|
type = avg;
|
||||||
|
}
|
||||||
|
void set_avgf(double p) {
|
||||||
|
type = avgf;
|
||||||
|
type_param = p;
|
||||||
|
}
|
||||||
|
void set_first() {
|
||||||
|
type = first;
|
||||||
|
}
|
||||||
|
void set_last() {
|
||||||
|
type = last;
|
||||||
|
}
|
||||||
|
void set_median() {
|
||||||
|
type = median;
|
||||||
|
}
|
||||||
|
double get_param() {
|
||||||
|
return type_param;
|
||||||
|
}
|
||||||
|
~invariant() {
|
||||||
|
delete s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
#undef avg
|
||||||
|
#undef first
|
||||||
|
#undef last
|
||||||
|
|
||||||
|
#endif
|
||||||
1388
d2/render/ipc.h
Normal file
1388
d2/render/ipc.h
Normal file
File diff suppressed because it is too large
Load Diff
329
d2/render/psf/backprojector.h
Normal file
329
d2/render/psf/backprojector.h
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __backprojector_h__
|
||||||
|
#define __backprojector_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "rasterizer.h"
|
||||||
|
#include "raster.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Backprojector for rasterized PSFs.
|
||||||
|
*
|
||||||
|
* This class converts a rasterized PSF into a rasterized backprojection array.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class backprojector : public raster {
|
||||||
|
raster *input;
|
||||||
|
public:
|
||||||
|
unsigned int varieties() const {
|
||||||
|
return input->varieties();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int select(unsigned int i, unsigned int j) const {
|
||||||
|
return input->select(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* Backprojection for the Irani-Peleg renderer
|
||||||
|
*
|
||||||
|
* Applying a special case of theorem 4.1 of the source paper by Irani
|
||||||
|
* and Peleg, convergence can be assured for a single image, with
|
||||||
|
* uniform PSF, no change in sampling rate, and taking the normalizing
|
||||||
|
* divisor c == 1, if H[psf](f)H[aux](f) is real and within the open
|
||||||
|
* interval (0, 2), where H[psf] is the frequency-domain representation
|
||||||
|
* of the point-spread function and H[aux] is the frequency-domain
|
||||||
|
* representation of the backprojection kernel. We can guarantee that
|
||||||
|
* H[psf](f)H[aux](f) is real by making H[aux](f) == k(f)H[psf](f)*,
|
||||||
|
* where k is a real function and '*' indicates the complex conjugate.
|
||||||
|
* If k(f) is equal to 1 for all f, then this is equivalent to the
|
||||||
|
* condition h[aux](x) == h[psf](-x), where h[] are the time domain
|
||||||
|
* representations of the respective functions. Since this negation
|
||||||
|
* of position is implicitly performed in ipc.h, we don't perform it
|
||||||
|
* here.
|
||||||
|
*
|
||||||
|
* However, to ensure that the range (0, 2) is satisfied, it may be
|
||||||
|
* necessary for k(f) to assume a value other than 1. We choose a
|
||||||
|
* constant function k, in accordance with the source paper's
|
||||||
|
* normalizing divisor c, but this is not required. We use FFTW
|
||||||
|
* when available, but it is likely that common cases will not observe
|
||||||
|
* any speed improvement.
|
||||||
|
*/
|
||||||
|
void initialize_response_array(ale_real *response_array) {
|
||||||
|
int cols = _filter_dim_j;
|
||||||
|
int rows = _filter_dim_i;
|
||||||
|
|
||||||
|
#ifdef USE_FFTW
|
||||||
|
fftw_complex *inout;
|
||||||
|
fftw_plan p_forward;
|
||||||
|
fftw_plan p_backward;
|
||||||
|
|
||||||
|
inout = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * cols * rows);
|
||||||
|
|
||||||
|
p_forward = fftw_plan_dft_2d(rows, cols, inout, inout, FFTW_FORWARD, FFTW_ESTIMATE);
|
||||||
|
p_backward = fftw_plan_dft_2d(rows, cols, inout, inout, FFTW_BACKWARD, FFTW_ESTIMATE);
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
|
||||||
|
for (int i = 0; i < rows * cols; i++) {
|
||||||
|
/*
|
||||||
|
* Write the values to the FFTW input array,
|
||||||
|
* shifting by (rows * cols - 1) / 2 in order
|
||||||
|
* to accommodate the implicit translation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inout[i][0] = response_array[((i + (rows * cols - 1)/2) * 3 + k)
|
||||||
|
% (rows * cols * 3)];
|
||||||
|
inout[i][1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fftw_execute(p_forward);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the frequency with maximum magnitude, then
|
||||||
|
* adjust this according to the sampling rate
|
||||||
|
* (filter resolution).
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_real max_magnitude = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < rows * cols; i++) {
|
||||||
|
ale_real input_magnitude;
|
||||||
|
|
||||||
|
input_magnitude = sqrt(pow(inout[i][0], 2) + pow(inout[i][1], 2));
|
||||||
|
if (input_magnitude > max_magnitude)
|
||||||
|
max_magnitude = input_magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_magnitude *= (4 * _height * _width) / (rows * cols);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scale the magnitude of all of the frequencies and perform
|
||||||
|
* conjugation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < rows * cols; i++) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust the magnitude
|
||||||
|
*
|
||||||
|
* Note: since we're currently dividing all frequencies
|
||||||
|
* by the same value, there's no need to divide in the
|
||||||
|
* frequency domain. However, we might want to do
|
||||||
|
* something else in the future, so it might be
|
||||||
|
* good to leave the code like this for now.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inout[i][0] = inout[i][0] * pow(0.9 / max_magnitude, 2);
|
||||||
|
inout[i][1] = inout[i][1] * pow(0.9 / max_magnitude, 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform conjugation
|
||||||
|
*
|
||||||
|
* Note: conjugation is implicit in ipc.h, so we omit the
|
||||||
|
* step here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* inout[i][1] = -inout[i][1]; */
|
||||||
|
}
|
||||||
|
|
||||||
|
fftw_execute(p_backward);
|
||||||
|
|
||||||
|
for (int i = 0; i < rows * cols; i++) {
|
||||||
|
/*
|
||||||
|
* Read the values from the FFTW output array,
|
||||||
|
* shifting by (rows * cols - 1) / 2 in order
|
||||||
|
* to accommodate the implicit translation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
response_array[((i + (rows * cols - 1)/2) * 3 + k)
|
||||||
|
% (rows * cols * 3)]
|
||||||
|
= inout[i][0]
|
||||||
|
/ (rows * cols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fftw_destroy_plan(p_forward);
|
||||||
|
fftw_destroy_plan(p_backward);
|
||||||
|
fftw_free(inout);
|
||||||
|
#else
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
ale_real *real1 = (ale_real *) calloc(rows * cols, sizeof(ale_real));
|
||||||
|
ale_real *imag1 = (ale_real *) calloc(rows * cols, sizeof(ale_real));
|
||||||
|
ale_real *real2 = (ale_real *) calloc(rows * cols, sizeof(ale_real));
|
||||||
|
ale_real *imag2 = (ale_real *) calloc(rows * cols, sizeof(ale_real));
|
||||||
|
|
||||||
|
assert (real1 && imag1 && real2 && imag2);
|
||||||
|
|
||||||
|
if (!(real1 && imag1 && real2 && imag2)) {
|
||||||
|
fprintf(stderr, "Unable to allocate memory in backprojector.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate frequencies. We implement the equations indicated by
|
||||||
|
* the FFTW3 info page (section "What FFTW Really Computes").
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < rows; i++)
|
||||||
|
for (int j = 0; j < cols; j++)
|
||||||
|
for (int jj = 0; jj < cols; jj++) {
|
||||||
|
real1[i * cols + j] += response_array[((i * cols + jj +
|
||||||
|
(rows * cols - 1)/2) * 3 + k)
|
||||||
|
% (rows * cols * 3)]
|
||||||
|
* (ale_real) cos((-2 * M_PI * j * jj) / cols);
|
||||||
|
imag1[i * cols + j] += response_array[((i * cols + jj +
|
||||||
|
(rows * cols - 1)/2) * 3 + k)
|
||||||
|
% (rows * cols * 3)]
|
||||||
|
* (ale_real) sin((-2 * M_PI * j * jj) / cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < rows; i++)
|
||||||
|
for (int j = 0; j < cols; j++)
|
||||||
|
for (int ii = 0; ii < rows; ii++) {
|
||||||
|
real2[i * cols + j] += real1[ii * cols + j]
|
||||||
|
* (ale_real) cos((-2 * M_PI * i * ii) / rows)
|
||||||
|
- imag1[ii * cols + j]
|
||||||
|
* (ale_real) sin((-2 * M_PI * i * ii) / rows);
|
||||||
|
imag2[i * cols + j] += real1[ii * cols + j]
|
||||||
|
* (ale_real) sin((-2 * M_PI * i * ii) / rows)
|
||||||
|
+ imag1[ii * cols + j]
|
||||||
|
* (ale_real) cos((-2 * M_PI * i * ii) / rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the frequency with maximum magnitude, then
|
||||||
|
* adjust this according to the sampling rate
|
||||||
|
* (filter resolution).
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_real max_magnitude = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < rows * cols; i++) {
|
||||||
|
ale_real input_magnitude;
|
||||||
|
|
||||||
|
input_magnitude = sqrt(pow(real2[i], 2) + pow(imag2[i], 2));
|
||||||
|
if (input_magnitude > max_magnitude)
|
||||||
|
max_magnitude = input_magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_magnitude *= (4 * _height * _width) / (rows * cols);
|
||||||
|
|
||||||
|
for (int i = 0; i < rows * cols; i++)
|
||||||
|
response_array[i * 3 + k] *= pow(0.9 / max_magnitude, 2);
|
||||||
|
|
||||||
|
free(real1);
|
||||||
|
free(imag1);
|
||||||
|
free(real2);
|
||||||
|
free(imag2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
backprojector (raster *input) {
|
||||||
|
this->input = input;
|
||||||
|
|
||||||
|
_height = -input->min_i();
|
||||||
|
assert (input->max_i() == _height);
|
||||||
|
|
||||||
|
_width = -input->min_j();
|
||||||
|
assert (input->max_j() == _width);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The element structure matches that of the input.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_filter_dim_i = input->max_elem_i();
|
||||||
|
_filter_dim_j = input->max_elem_j();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that the array has an odd number of elements in each
|
||||||
|
* direction. This allows us to move the center to the right
|
||||||
|
* place when using a discrete FT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert (_filter_dim_i % 2 == 1);
|
||||||
|
assert (_filter_dim_j % 2 == 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the number of arrays to create.
|
||||||
|
*/
|
||||||
|
|
||||||
|
num_arrays = input->varieties();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create arrays
|
||||||
|
*/
|
||||||
|
|
||||||
|
response_arrays = (ale_real **)malloc(num_arrays * sizeof(ale_real *));
|
||||||
|
|
||||||
|
if (!response_arrays) {
|
||||||
|
fprintf(stderr, "Could not allocate in backprojector.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int n = 0; n < num_arrays; n++) {
|
||||||
|
response_arrays[n] = (ale_real *)malloc(_filter_dim_i * _filter_dim_j * 3
|
||||||
|
* sizeof(ale_real));
|
||||||
|
|
||||||
|
if (!response_arrays[n]) {
|
||||||
|
fprintf(stderr, "Could not allocate in backprojector.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (unsigned int k = 0; k < 3; k++) {
|
||||||
|
response_arrays[n][i * _filter_dim_j * 3 + j * 3 + k]
|
||||||
|
= input->element(n, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize_response_array(response_arrays[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
avg_response = (ale_real *)malloc(_filter_dim_i * _filter_dim_j * 3
|
||||||
|
* sizeof(ale_real));
|
||||||
|
|
||||||
|
if (!avg_response) {
|
||||||
|
fprintf(stderr, "Could not allocate in backprojector.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (unsigned int k = 0; k < 3; k++) {
|
||||||
|
avg_response[i * _filter_dim_j * 3 + j * 3 + k]
|
||||||
|
= input->element(i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize_response_array(avg_response);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
compute_integrals();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
82
d2/render/psf/box.h
Normal file
82
d2/render/psf/box.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_box_h__
|
||||||
|
#define __psf_box_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function module.
|
||||||
|
*
|
||||||
|
* This module implements the box filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class box : public psf {
|
||||||
|
ale_real _radius;
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return -_radius; }
|
||||||
|
ale_real max_i() const { return _radius; }
|
||||||
|
ale_real min_j() const { return -_radius; }
|
||||||
|
ale_real max_j() const { return _radius; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response function
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety the responding pixel is provided, in
|
||||||
|
* case response is not uniform for all pixels (e.g. some sensor arrays
|
||||||
|
* stagger red, green, and blue sensors).
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig,
|
||||||
|
unsigned int variety) const {
|
||||||
|
|
||||||
|
psf_result result;
|
||||||
|
|
||||||
|
if (top < min_i())
|
||||||
|
top = min_i();
|
||||||
|
if (bot > max_i())
|
||||||
|
bot = max_i();
|
||||||
|
if (lef < min_j())
|
||||||
|
lef = min_j();
|
||||||
|
if (rig > max_j())
|
||||||
|
rig = max_j();
|
||||||
|
|
||||||
|
if (bot > top && rig > lef)
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
result.matrix(k, k) = (bot - top) * (rig - lef) / (4 * _radius * _radius);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
box(ale_real radius) {
|
||||||
|
_radius = radius;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
85
d2/render/psf/circle.h
Normal file
85
d2/render/psf/circle.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_circle_h__
|
||||||
|
#define __psf_circle_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function module.
|
||||||
|
*
|
||||||
|
* This module implements a circular filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class circle : public psf {
|
||||||
|
ale_real _radius;
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return -_radius; }
|
||||||
|
ale_real max_i() const { return _radius; }
|
||||||
|
ale_real min_j() const { return -_radius; }
|
||||||
|
ale_real max_j() const { return _radius; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response function
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety of the responding pixel is provided, in
|
||||||
|
* case response is not uniform for all pixels (e.g. some sensor arrays
|
||||||
|
* stagger red, green, and blue sensors).
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig,
|
||||||
|
unsigned int variety) const {
|
||||||
|
|
||||||
|
psf_result result;
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
result.matrix(k, k) = 0;
|
||||||
|
|
||||||
|
ale_real total = (bot - top) * (rig - lef) / (M_PI * _radius * _radius);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
for (int j = 0; j < 10; j++) {
|
||||||
|
ale_real one_half = 1 / (ale_real) 2;
|
||||||
|
ale_real r = pow(top + (bot - top) * ((i + one_half) / (ale_real) 10), 2)
|
||||||
|
+ pow(lef + (rig - lef) * ((j + one_half) / (ale_real) 10), 2);
|
||||||
|
if (r < _radius * _radius)
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
result.matrix(k, k) += (total / (ale_real) 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
circle(ale_real radius) {
|
||||||
|
_radius = radius;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
145
d2/render/psf/convolution.h
Normal file
145
d2/render/psf/convolution.h
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
// Copyright 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_convolution_h__
|
||||||
|
#define __psf_convolution_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: This doesn't work yet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function module.
|
||||||
|
*
|
||||||
|
* This module implements the convolution (f1 * f2) of point-spread functions f1 and
|
||||||
|
* f2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class convolution : public psf {
|
||||||
|
ale_pos _radius;
|
||||||
|
psf *f1, *f2;
|
||||||
|
ale_real _min_i, _max_i, _min_j, _max_j;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return _min_i; }
|
||||||
|
ale_real max_i() const { return _max_i; }
|
||||||
|
ale_real min_j() const { return _min_j; }
|
||||||
|
ale_real max_j() const { return _max_j; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the number of varieties supported by this PSF. These usually
|
||||||
|
* correspond to different points in the sensor array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int varieties() {
|
||||||
|
return f1->varieties() * f2->varieties();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select the variety appropriate for a given position in the sensor
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int select(unsigned int i, unsigned int j) {
|
||||||
|
return (f1->select(i, j) * f2->varieties() + f2->select(i, j));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response function
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety of the responding pixel is provided, in
|
||||||
|
* case response is not uniform for all pixels (e.g. some sensor arrays
|
||||||
|
* stagger red, green, and blue sensors).
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig,
|
||||||
|
unsigned int variety) const {
|
||||||
|
psf_result result;
|
||||||
|
psf_result r1, r2;
|
||||||
|
|
||||||
|
unsigned int v1 = variety / f2->varieties();
|
||||||
|
unsigned int v2 = variety % f2->varieties();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code uses a rasterized approximation of the filters involved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_real vertical_center = (top + bot) / 2;
|
||||||
|
ale_real horizontal_center = (lef + rig) / 2;
|
||||||
|
ale_real vertical_resolution = bot - top;
|
||||||
|
ale_real horizontal_resolution = rig - lef;
|
||||||
|
|
||||||
|
if (!(vertical_resolution > 0
|
||||||
|
&& horizontal_resolution > 0))
|
||||||
|
return result; /* zero */
|
||||||
|
|
||||||
|
for (ale_real i = f1->min_i() + (vertical_resolution / 2);
|
||||||
|
i < f1->max_i() - (vertical_resolution / 2);
|
||||||
|
i += vertical_resolution)
|
||||||
|
for (ale_real j = f1->min_j() + (horizontal_resolution / 2);
|
||||||
|
j < f1->max_j() - (horizontal_resolution / 2);
|
||||||
|
j += horizontal_resolution) {
|
||||||
|
|
||||||
|
ale_real t = i - (vertical_resolution / 2);
|
||||||
|
ale_real b = i + (vertical_resolution / 2);
|
||||||
|
ale_real l = j - (horizontal_resolution / 2);
|
||||||
|
ale_real r = j + (horizontal_resolution / 2);
|
||||||
|
ale_real vc = vertical_center;
|
||||||
|
ale_real hc = horizontal_center;
|
||||||
|
|
||||||
|
r1 = (*f1)(t, b, l, r, v1);
|
||||||
|
r2 = (*f2)(vc - b, vc - t, hc - r, hc - l, v2);
|
||||||
|
|
||||||
|
for (int k1 = 0; k1 < 3; k1++)
|
||||||
|
for (int k2 = 0; k2 < 3; k2++)
|
||||||
|
result.set_matrix(k1, k2, result.get_matrix(k1, k2)
|
||||||
|
+ r1.get_matrix(k1, k2)
|
||||||
|
* r2.get_matrix(k1, k2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
convolution(psf *f1, psf *f2) {
|
||||||
|
|
||||||
|
this->f1 = f1;
|
||||||
|
this->f2 = f2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: I'm fairly sure that this is correct for filters with
|
||||||
|
* zero-centered bounding boxes, and I _think_ it's correct for
|
||||||
|
* other filters also, but I haven't formally proven this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_min_i = f1->min_i() + f2->min_i();
|
||||||
|
_min_j = f1->min_j() + f2->min_j();
|
||||||
|
_max_i = f1->max_i() + f2->max_i();
|
||||||
|
_max_j = f1->max_j() + f2->max_j();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
127
d2/render/psf/gauss.h
Normal file
127
d2/render/psf/gauss.h
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// code by HJ Hornbeck, based on code copyright 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_gauss_h__
|
||||||
|
#define __psf_gauss_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A Gaussian point-spread function. It's aimed at duplicating the most common type
|
||||||
|
* of blurring in many optical systems. It is uniform across the entire image, so
|
||||||
|
* it can't correct for poor focus at the edges.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define D2_GAUSS_CUTOFF ((ale_real) 2.0)
|
||||||
|
|
||||||
|
class gauss : public psf {
|
||||||
|
ale_real sigma; // radius, in pixels per standard deviation
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disabled the following definition because some compilers may not be
|
||||||
|
* able to handle static const definitions within a class (and because
|
||||||
|
* the C++ specification may disallow such for non-integral types,
|
||||||
|
* anyway).
|
||||||
|
*
|
||||||
|
* -- dhilvert@auricle.dyndns.org 18-May-2007
|
||||||
|
*/
|
||||||
|
|
||||||
|
// static const ale_pos cutoff = 2; // standard deviations before we cut off
|
||||||
|
|
||||||
|
// helper variables
|
||||||
|
ale_real radius;
|
||||||
|
ale_real sigma_premult;
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
inline ale_real max_i() const { return radius; }
|
||||||
|
inline ale_real min_i() const { return -max_i(); } // we're symmetrical, so it works!
|
||||||
|
inline ale_real min_j() const { return -max_i(); }
|
||||||
|
inline ale_real max_j() const { return max_i(); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response function
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety of the responding pixel is provided, in
|
||||||
|
* case response is not uniform for all pixels (e.g. some sensor arrays
|
||||||
|
* stagger red, green, and blue sensors).
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig,
|
||||||
|
unsigned int variety) const {
|
||||||
|
|
||||||
|
psf_result result;
|
||||||
|
|
||||||
|
// calculate some needed values
|
||||||
|
ale_pos area_premult = (bot - top) * (rig - lef) / 25;
|
||||||
|
ale_real vert_step = (bot - top) / 4;
|
||||||
|
ale_real horiz_step = (rig - lef) / 4;
|
||||||
|
ale_real total = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// determine the final value by simple sampling:
|
||||||
|
for (ale_real i = top; i < bot + vert_step / 2; i += vert_step)
|
||||||
|
for (ale_real j = lef; j < rig + horiz_step / 2; j += horiz_step) {
|
||||||
|
|
||||||
|
// calculate radius for given sample
|
||||||
|
ale_real r = sqrt( i*i + j*j );
|
||||||
|
|
||||||
|
if ( r < radius ) // calculate gaussian falloff
|
||||||
|
total += exp( -r * r * sigma_premult ) ;
|
||||||
|
// outside our radius? must be 0...
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust for point sampling and area
|
||||||
|
total *= area_premult;
|
||||||
|
|
||||||
|
// pre-fill the colour result matrix
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
result.matrix(k, k) = 0;
|
||||||
|
|
||||||
|
// fill in the results
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
result.matrix(k, k) = total;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our glorious constructor
|
||||||
|
*/
|
||||||
|
gauss(ale_real sig) {
|
||||||
|
|
||||||
|
sigma = sig;
|
||||||
|
|
||||||
|
// fill in our helper variables
|
||||||
|
radius = sigma * D2_GAUSS_CUTOFF;
|
||||||
|
sigma_premult = 1 / (sigma * sigma);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef D2_GAUSS_CUTOFF
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
141
d2/render/psf/normalizer.h
Normal file
141
d2/render/psf/normalizer.h
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __normalizer_h__
|
||||||
|
#define __normalizer_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "rasterizer.h"
|
||||||
|
#include "raster.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normalizer for rasterized PSFs.
|
||||||
|
*
|
||||||
|
* This class normalizes a rasterized PSF.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class normalizer : public raster {
|
||||||
|
raster *input;
|
||||||
|
public:
|
||||||
|
unsigned int varieties() const {
|
||||||
|
return input->varieties();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int select(unsigned int i, unsigned int j) const {
|
||||||
|
return input->select(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initialize_response_array(ale_real *response_array) {
|
||||||
|
pixel integral;
|
||||||
|
|
||||||
|
integral = integrate(response_array);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (unsigned int k = 0; k < 3 ; k++)
|
||||||
|
response_array[i * _filter_dim_j * 3 + j * 3 + k] /= integral[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
normalizer (raster *input) {
|
||||||
|
this->input = input;
|
||||||
|
|
||||||
|
_height = -input->min_i();
|
||||||
|
assert (input->max_i() == _height);
|
||||||
|
|
||||||
|
_width = -input->min_j();
|
||||||
|
assert (input->max_j() == _width);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The element structure matches that of the input.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_filter_dim_i = input->max_elem_i();
|
||||||
|
_filter_dim_j = input->max_elem_j();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that the array has an odd number of elements in each
|
||||||
|
* direction. This allows us to move the center to the right
|
||||||
|
* place when using FFTW.
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert (_filter_dim_i % 2 == 1);
|
||||||
|
assert (_filter_dim_j % 2 == 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the number of arrays to create.
|
||||||
|
*/
|
||||||
|
|
||||||
|
num_arrays = input->varieties();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create arrays
|
||||||
|
*/
|
||||||
|
|
||||||
|
response_arrays = (ale_real **)malloc(num_arrays * sizeof(ale_real *));
|
||||||
|
|
||||||
|
if (!response_arrays) {
|
||||||
|
fprintf(stderr, "Could not allocate in normalizer.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int n = 0; n < num_arrays; n++) {
|
||||||
|
response_arrays[n] = (ale_real *)malloc(_filter_dim_i * _filter_dim_j * 3
|
||||||
|
* sizeof(ale_real));
|
||||||
|
|
||||||
|
if (!response_arrays[n]) {
|
||||||
|
fprintf(stderr, "Could not allocate in normalizer.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (unsigned int k = 0; k < 3; k++) {
|
||||||
|
response_arrays[n][i * _filter_dim_j * 3 + j * 3 + k]
|
||||||
|
= input->element(n, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize_response_array(response_arrays[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
avg_response = (ale_real *)malloc(_filter_dim_i * _filter_dim_j * 3
|
||||||
|
* sizeof(ale_real));
|
||||||
|
|
||||||
|
if (!avg_response) {
|
||||||
|
fprintf(stderr, "Could not allocate in normalizer.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (unsigned int k = 0; k < 3; k++) {
|
||||||
|
avg_response[i * _filter_dim_j * 3 + j * 3 + k]
|
||||||
|
= input->element(i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize_response_array(avg_response);
|
||||||
|
#endif
|
||||||
|
compute_integrals();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
184
d2/render/psf/psf.h
Normal file
184
d2/render/psf/psf.h
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_h__
|
||||||
|
#define __psf_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function module abstract base class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class psf {
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* Result type is a matrix.
|
||||||
|
*/
|
||||||
|
class psf_result {
|
||||||
|
friend class psf;
|
||||||
|
protected:
|
||||||
|
ale_real _matrix[3][3];
|
||||||
|
|
||||||
|
public:
|
||||||
|
psf_result() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simplified version -- diagonal matrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
_matrix[i][i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real get_matrix(unsigned int i, unsigned int j) {
|
||||||
|
assert (i < 3);
|
||||||
|
assert (j < 3);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simplified version -- diagonal matrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (i != j)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return _matrix[i][j];
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_matrix(unsigned int i, unsigned int j, ale_real value) {
|
||||||
|
assert (i < 3);
|
||||||
|
assert (j < 3);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simplified version -- diagonal matrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert (i == j || value == 0);
|
||||||
|
|
||||||
|
_matrix[i][j] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real &matrix(unsigned int i, unsigned int j) {
|
||||||
|
assert (i < 3);
|
||||||
|
assert (j < 3);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simplified version -- diagonal matrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert (i == j);
|
||||||
|
|
||||||
|
return _matrix[i][j];
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel operator()(pixel p) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simplified version -- diagonal matrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
return pixel(_matrix[0][0] * p[0],
|
||||||
|
_matrix[1][1] * p[1],
|
||||||
|
_matrix[2][2] * p[2]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Weights associated with the result
|
||||||
|
*/
|
||||||
|
pixel weight() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simplified version -- diagonal matrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
return pixel(
|
||||||
|
_matrix[0][0],
|
||||||
|
_matrix[1][1],
|
||||||
|
_matrix[2][2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator*=(ale_real scale) {
|
||||||
|
/*
|
||||||
|
* Simplified version -- diagonal matrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
_matrix[i][i] *= scale;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
virtual ale_real min_i() const = 0;
|
||||||
|
virtual ale_real max_i() const = 0;
|
||||||
|
virtual ale_real min_j() const = 0;
|
||||||
|
virtual ale_real max_j() const = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the number of varieties supported by this PSF. These usually
|
||||||
|
* correspond to different points in the sensor array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int varieties() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select the variety appropriate for a given position in the sensor
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int select(unsigned int i, unsigned int j) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. One of several varieties can be selected, usually
|
||||||
|
* based on position (e.g. some sensor arrays stagger red, green, and
|
||||||
|
* blue sensors).
|
||||||
|
*/
|
||||||
|
virtual psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real
|
||||||
|
rig, unsigned int variety) const = 0;
|
||||||
|
|
||||||
|
virtual psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real
|
||||||
|
rig, unsigned int variety, char channels) const {
|
||||||
|
return operator()(top, bot, lef, rig, variety);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Get the average pixel response. This function should be overloaded
|
||||||
|
* for PSFs that support multiple varieties.
|
||||||
|
*/
|
||||||
|
virtual psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig) const {
|
||||||
|
return operator()(top, bot, lef, rig, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual ~psf() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
333
d2/render/psf/psf_calibrate.h
Normal file
333
d2/render/psf/psf_calibrate.h
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_calibrate_h__
|
||||||
|
#define __psf_calibrate_h__
|
||||||
|
|
||||||
|
#include "../../image.h"
|
||||||
|
#include "../../render.h"
|
||||||
|
#include "../ipc.h"
|
||||||
|
|
||||||
|
class psf_calibrate : public ipc {
|
||||||
|
private:
|
||||||
|
double *psf_match_args;
|
||||||
|
public:
|
||||||
|
psf_calibrate(render *input, unsigned int iterations, int _inc, psf *lresponse, psf *nlresponse,
|
||||||
|
double *psf_match_args)
|
||||||
|
: ipc(input, iterations, _inc, lresponse, nlresponse, 1, 0, 0) {
|
||||||
|
fprintf(stderr, "\nIPC Calibration module.\n\n");
|
||||||
|
fprintf(stderr, "This module is designed for use with a calibration script.\n\n");
|
||||||
|
|
||||||
|
this->psf_match_args = psf_match_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ip_frame(ale_accum *diff, unsigned int *count, int m) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get alignment information for frame m.
|
||||||
|
*/
|
||||||
|
|
||||||
|
transformation t = align::of(m);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We create real and simulated input-frame data structures
|
||||||
|
* REAL and SIMULATED, as well as simulated input-frame weights
|
||||||
|
* SIM_WEIGHTS, used to track the weights of contributions to each
|
||||||
|
* simulated input-frame pixel component.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const image *real = image_rw::open(m);
|
||||||
|
image *simulated = new_image_ale_real(
|
||||||
|
real->height(),
|
||||||
|
real->width(), 3);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the simulated input frame SIMULATED from the image
|
||||||
|
* approximation APPROXIMATION, iterating over image
|
||||||
|
* approximation pixels and tracking contributions to simulated
|
||||||
|
* frame pixels in the data structure SIM_WEIGHTS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
image *sim_weights = new_image_ale_real(
|
||||||
|
simulated->height(),
|
||||||
|
simulated->width(), 3);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < approximation->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < approximation->width(); j++) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain the position Q and dimensions D of
|
||||||
|
* image approximation pixel (i, j) in the coordinate
|
||||||
|
* system of the simulated frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
point p = point(i + approximation->offset()[0], j + approximation->offset()[1]);
|
||||||
|
point q;
|
||||||
|
ale_pos d[2];
|
||||||
|
|
||||||
|
t.unscaled_map_area_inverse(p, &q, d);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over all simulated frame pixels influenced
|
||||||
|
* by the scene pixel (i, j), as determined by the
|
||||||
|
* response function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int ii = (int) floor(q[0] - d[0] + (ale_pos) lresponse->min_i());
|
||||||
|
ii <= ceil(q[0] + d[0] + (ale_pos) lresponse->max_i()); ii++)
|
||||||
|
for (int jj = (int) floor(q[1] - d[1] + (ale_pos) lresponse->min_j());
|
||||||
|
jj <= ceil(q[1] + d[1] + (ale_pos) lresponse->max_j()); jj++) {
|
||||||
|
|
||||||
|
ale_pos top = q[0] - d[0];
|
||||||
|
ale_pos bot = q[0] + d[0];
|
||||||
|
ale_pos lef = q[1] - d[1];
|
||||||
|
ale_pos rig = q[1] + d[1];
|
||||||
|
|
||||||
|
if (ii >= (int) 0
|
||||||
|
&& ii < (int) real->height()
|
||||||
|
&& jj >= (int) 0
|
||||||
|
&& jj < (int) real->width()) {
|
||||||
|
|
||||||
|
psf::psf_result r =
|
||||||
|
(*lresponse)(top - ii, bot - ii,
|
||||||
|
lef - jj, rig - jj,
|
||||||
|
lresponse->select(ii, jj));
|
||||||
|
|
||||||
|
sim_weights->set_pixel(ii, jj,
|
||||||
|
(pixel) sim_weights->get_pixel(ii, jj) + r.weight());
|
||||||
|
simulated->set_pixel(ii, jj,
|
||||||
|
(pixel) simulated->get_pixel(ii, jj) + r(approximation->get_pixel(i, j)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normalize SIMULATED by SIM_WEIGHTS
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < simulated->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < simulated->width(); j++)
|
||||||
|
simulated->set_pixel(i, j,
|
||||||
|
(pixel) simulated->get_pixel(i, j) / (pixel) sim_weights->get_pixel(i, j));
|
||||||
|
|
||||||
|
delete sim_weights;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If NLRESPONSE is defined, then redefine SIMULATED to account
|
||||||
|
* for this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (nlresponse != NULL) {
|
||||||
|
image *nlsimulated = new_image_ale_real(
|
||||||
|
simulated->height(),
|
||||||
|
simulated->width(), 3);
|
||||||
|
|
||||||
|
image *nlsim_weights = new_image_ale_real(
|
||||||
|
simulated->height(),
|
||||||
|
simulated->width(), 3);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < simulated->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < simulated->width(); j++) {
|
||||||
|
|
||||||
|
for (int ii = (int) floor(i - 0.5 + nlresponse->min_i());
|
||||||
|
ii <= ceil(i + 0.5 + nlresponse->max_i()); ii++)
|
||||||
|
for (int jj = (int) floor(j - 0.5 + nlresponse->min_j());
|
||||||
|
jj <= ceil(j + 0.5 + nlresponse->max_j()); jj++) {
|
||||||
|
|
||||||
|
ale_pos top = i - 0.5;
|
||||||
|
ale_pos bot = i + 0.5;
|
||||||
|
ale_pos lef = j - 0.5;
|
||||||
|
ale_pos rig = j + 0.5;
|
||||||
|
|
||||||
|
if (ii >= (int) 0
|
||||||
|
&& ii < (int) nlsimulated->height()
|
||||||
|
&& jj >= (int) 0
|
||||||
|
&& jj < (int) nlsimulated->width()) {
|
||||||
|
|
||||||
|
psf::psf_result r =
|
||||||
|
(*nlresponse)(top - ii, bot - ii,
|
||||||
|
lef - jj, rig - jj,
|
||||||
|
nlresponse->select(ii, jj));
|
||||||
|
|
||||||
|
nlsim_weights->set_pixel(ii, jj,
|
||||||
|
(pixel) nlsim_weights->get_pixel(ii, jj) + r.weight());
|
||||||
|
|
||||||
|
nlsimulated->set_pixel(ii, jj,
|
||||||
|
(pixel) nlsimulated->get_pixel(ii, jj) + r(real->exp().unlinearize(simulated->get_pixel(i, j))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normalize nlsimulated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < simulated->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < simulated->width(); j++)
|
||||||
|
nlsimulated->set_pixel(i, j,
|
||||||
|
(pixel) nlsimulated->get_pixel(i, j) / nlsim_weights->get_pixel(i, j));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linearize nlsimulated
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < simulated->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < simulated->width(); j++)
|
||||||
|
nlsimulated->set_pixel(i, j,
|
||||||
|
real->exp().linearize(nlsimulated->get_pixel(i, j)));
|
||||||
|
|
||||||
|
delete simulated;
|
||||||
|
delete nlsim_weights;
|
||||||
|
|
||||||
|
simulated = nlsimulated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For each SIMULATED pixel, calculate the difference from
|
||||||
|
* the corresponding REAL pixel, and update the sum of squares
|
||||||
|
* of differences.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_real margin_i1 = lresponse->min_i() + (nlresponse ? nlresponse->min_i() : ale_real_0);
|
||||||
|
ale_real margin_i2 = lresponse->max_i() + (nlresponse ? nlresponse->max_i() : ale_real_0);
|
||||||
|
ale_real margin_j1 = lresponse->min_j() + (nlresponse ? nlresponse->min_j() : ale_real_0);
|
||||||
|
ale_real margin_j2 = lresponse->max_j() + (nlresponse ? nlresponse->max_j() : ale_real_0);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < simulated->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < simulated->width(); j++) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Establish margins. This is designed to reduce the
|
||||||
|
* influence of boundary conditions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
point p;
|
||||||
|
|
||||||
|
p = t.transform_unscaled(point(i + margin_i1, j + margin_j1));
|
||||||
|
if (p[0] < 0 || p[0] > approximation->height()
|
||||||
|
|| p[1] < 0 || p[1] > approximation->width())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p = t.transform_unscaled(point(i + margin_i1, j + margin_j2));
|
||||||
|
if (p[0] < 0 || p[0] > approximation->height()
|
||||||
|
|| p[1] < 0 || p[1] > approximation->width())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p = t.transform_unscaled(point(i + margin_i2, j + margin_j1));
|
||||||
|
if (p[0] < 0 || p[0] > approximation->height()
|
||||||
|
|| p[1] < 0 || p[1] > approximation->width())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p = t.transform_unscaled(point(i + margin_i2, j + margin_j2));
|
||||||
|
if (p[0] < 0 || p[0] > approximation->height()
|
||||||
|
|| p[1] < 0 || p[1] > approximation->width())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Real and simulated responses
|
||||||
|
*/
|
||||||
|
|
||||||
|
pixel comp_real = real->get_pixel(i, j);
|
||||||
|
pixel comp_simu = simulated->get_pixel(i, j);
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < simulated->depth(); k++) {
|
||||||
|
|
||||||
|
if (!finite(comp_simu[k]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Error calculation
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((comp_real[k] < 1.0 || comp_simu[k] < 1.0 )
|
||||||
|
&& (comp_real[k] > 0 || comp_simu[k] > 0)
|
||||||
|
&& ((*count) < ULONG_MAX)) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* real and simulated are distinguishable
|
||||||
|
* within the dynamic range of the program
|
||||||
|
* inputs, so calculate the error for this
|
||||||
|
* channel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(*diff) += pow(comp_simu[k] - comp_real[k], 2);
|
||||||
|
(*count)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image_rw::close(m);
|
||||||
|
delete simulated;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ip() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input images 0 through count()-2 are frames captured with
|
||||||
|
* the device to be calibrated, so we combine the difference
|
||||||
|
* values for all of these frames against the calibration image
|
||||||
|
* count()-1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_accum diff = 0;
|
||||||
|
unsigned int channel_count = 0;
|
||||||
|
|
||||||
|
approximation = image_rw::copy(image_rw::count() - 1, "PSF_CALIBRATE reference");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "[%f %f %f %f %f %f] ", psf_match_args[0],
|
||||||
|
psf_match_args[1],
|
||||||
|
psf_match_args[2],
|
||||||
|
psf_match_args[3],
|
||||||
|
psf_match_args[4],
|
||||||
|
psf_match_args[5]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < approximation->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < approximation->width(); j++) {
|
||||||
|
approximation->set_pixel(i, j, (pixel) approximation->get_pixel(i, j)
|
||||||
|
* pixel(psf_match_args[0],
|
||||||
|
psf_match_args[1],
|
||||||
|
psf_match_args[2]));
|
||||||
|
approximation->set_pixel(i, j, (pixel) approximation->get_pixel(i, j)
|
||||||
|
+ pixel(psf_match_args[3],
|
||||||
|
psf_match_args[4],
|
||||||
|
psf_match_args[5]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int m = 0; m < image_rw::count() - 1; m++) {
|
||||||
|
_ip_frame(&diff, &channel_count, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff = pow(diff / (ale_accum) channel_count, 0.5);
|
||||||
|
|
||||||
|
fprintf(stderr, "\n\nPSF Error:: %e\n\n", (double) diff);
|
||||||
|
|
||||||
|
delete approximation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_memory() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
197
d2/render/psf/psf_parse.h
Normal file
197
d2/render/psf/psf_parse.h
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_parse_h__
|
||||||
|
#define __psf_parse_h__
|
||||||
|
|
||||||
|
#include "psf.h"
|
||||||
|
#include "box.h"
|
||||||
|
#include "circle.h"
|
||||||
|
#include "gauss.h"
|
||||||
|
#include "sum.h"
|
||||||
|
#include "convolution.h"
|
||||||
|
#include "scalar_mult.h"
|
||||||
|
#include "stdin.h"
|
||||||
|
#include "stdin_vg.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse strings describing point-spread functions, and return a psf object
|
||||||
|
* satisfying the string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class psf_parse {
|
||||||
|
private:
|
||||||
|
static int strpfix(const char *a, const char *b) {
|
||||||
|
return strncmp(a, b, strlen(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nomem() {
|
||||||
|
fprintf(stderr, "\n\n*** Error: unable to allocate memory in psf_parse. ***\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void syntax_error(const char *explanation) {
|
||||||
|
fprintf(stderr, "\n\n*** Error: PSF syntax: %s ***\n\n", explanation);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Evaluate a type string having no remaining binary operators.
|
||||||
|
*/
|
||||||
|
static psf *get_atomic(int is_linear, const char *orig_type) {
|
||||||
|
double param;
|
||||||
|
|
||||||
|
if (!strcmp(orig_type, "stdin")) {
|
||||||
|
|
||||||
|
fprintf(stderr, "\nInitializing ");
|
||||||
|
fprintf(stderr, is_linear ? "linear" : "non-linear");
|
||||||
|
fprintf(stderr, " PSF.\n");
|
||||||
|
|
||||||
|
return new psf_stdin();
|
||||||
|
} else if (!strcmp(orig_type, "stdin_vg")) {
|
||||||
|
|
||||||
|
fprintf(stderr, "\nInitializing ");
|
||||||
|
fprintf(stderr, is_linear ? "linear" : "non-linear");
|
||||||
|
fprintf(stderr, " PSF.\n");
|
||||||
|
|
||||||
|
return new psf_stdin_vg();
|
||||||
|
} else if (!strpfix("box=", orig_type)) {
|
||||||
|
if (sscanf(orig_type + strlen("box="), "%lf", ¶m) != 1)
|
||||||
|
syntax_error("Unable to get box diameter.");
|
||||||
|
return new box(param / 2);
|
||||||
|
} else if (!strpfix("circle=", orig_type)) {
|
||||||
|
if (sscanf(orig_type + strlen("circle="), "%lf", ¶m) != 1)
|
||||||
|
syntax_error("Unable to get circle diameter.");
|
||||||
|
return new circle(param / 2);
|
||||||
|
} else if (!strpfix("gauss=", orig_type)) {
|
||||||
|
if (sscanf(orig_type + strlen("gauss="), "%lf", ¶m) != 1)
|
||||||
|
syntax_error("Unable to parse gauss std deviation.");
|
||||||
|
return new gauss(param / 2);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "get_atomic type %s\n", orig_type);
|
||||||
|
syntax_error("Unable to get filter.");
|
||||||
|
}
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a scalar value
|
||||||
|
*/
|
||||||
|
static ale_real get_scalar(const char *orig_type) {
|
||||||
|
double result;
|
||||||
|
if (sscanf(orig_type, "%lf", &result) != 1)
|
||||||
|
syntax_error("Unable to get scalar value.");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split a type string with the binary operator having
|
||||||
|
* third-lowest precedence (i.e., scalar multiplication).
|
||||||
|
*/
|
||||||
|
static psf *get_scalar_mult(int is_linear, const char *orig_type) {
|
||||||
|
char *type = strdup(orig_type);
|
||||||
|
char *operator_index = (char *) type;
|
||||||
|
|
||||||
|
assert(type);
|
||||||
|
if (!type)
|
||||||
|
nomem();
|
||||||
|
|
||||||
|
while (*operator_index != '\0'
|
||||||
|
&& *operator_index != '*')
|
||||||
|
operator_index++;
|
||||||
|
|
||||||
|
if (*operator_index == '\0') {
|
||||||
|
free(type);
|
||||||
|
return get_atomic(is_linear, orig_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
*operator_index = '\0';
|
||||||
|
psf *result = new scalar_mult(get_scalar(type), get_scalar_mult(is_linear, operator_index + 1));
|
||||||
|
*operator_index = '*';
|
||||||
|
|
||||||
|
free(type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split a type string with the binary operator having
|
||||||
|
* second-lowest precedence (i.e., convolution).
|
||||||
|
*/
|
||||||
|
static psf *get_convolution(int is_linear, const char *orig_type) {
|
||||||
|
char *type = strdup(orig_type);
|
||||||
|
char *operator_index = (char *) type;
|
||||||
|
|
||||||
|
assert(type);
|
||||||
|
if (!type)
|
||||||
|
nomem();
|
||||||
|
|
||||||
|
while (*operator_index != '\0'
|
||||||
|
&& *operator_index != '^')
|
||||||
|
operator_index++;
|
||||||
|
|
||||||
|
if (*operator_index == '\0') {
|
||||||
|
free(type);
|
||||||
|
return get_scalar_mult(is_linear, orig_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
*operator_index = '\0';
|
||||||
|
psf *result = new convolution(get_scalar_mult(is_linear, type), get_convolution(is_linear, operator_index + 1));
|
||||||
|
*operator_index = '^';
|
||||||
|
|
||||||
|
free(type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split the type string using the binary operator with
|
||||||
|
* lowest precedence (addition).
|
||||||
|
*/
|
||||||
|
static psf *get_summation(int is_linear, const char *orig_type) {
|
||||||
|
char *type = strdup(orig_type);
|
||||||
|
char *plus_index = (char *) type;
|
||||||
|
|
||||||
|
assert(type);
|
||||||
|
if (!type)
|
||||||
|
nomem();
|
||||||
|
|
||||||
|
while (*plus_index != '\0'
|
||||||
|
&& *plus_index != '+')
|
||||||
|
plus_index++;
|
||||||
|
|
||||||
|
if (*plus_index == '\0') {
|
||||||
|
free(type);
|
||||||
|
return get_convolution(is_linear, orig_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
*plus_index = '\0';
|
||||||
|
psf *result = new sum(get_convolution(is_linear, type), get_summation(is_linear, plus_index + 1));
|
||||||
|
*plus_index = '+';
|
||||||
|
|
||||||
|
free(type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static psf *get(int is_linear, const char *orig_type) {
|
||||||
|
return get_summation(is_linear, orig_type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
109
d2/render/psf/psf_template.h
Normal file
109
d2/render/psf/psf_template.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_template_h__
|
||||||
|
#define __psf_template_h__
|
||||||
|
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function template.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <unsigned int rows, unsigned int cols>
|
||||||
|
class psf_template : public psf {
|
||||||
|
const ale_real (&response)[rows][cols][3];
|
||||||
|
ale_pos height, width;
|
||||||
|
public:
|
||||||
|
psf_template(ale_pos h, ale_pos w, const ale_real (&_response)[rows][cols][3]) : response(_response) {
|
||||||
|
height = h / 2;
|
||||||
|
width = w / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return -height; }
|
||||||
|
ale_real max_i() const { return height; }
|
||||||
|
ale_real min_j() const { return -width; }
|
||||||
|
ale_real max_j() const { return width; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response function
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety of the responding pixel is
|
||||||
|
* provided, in case response is not uniform for all pixels
|
||||||
|
* (e.g. some sensor arrays stagger red, green, and blue
|
||||||
|
* sensors).
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig,
|
||||||
|
unsigned int variety) const {
|
||||||
|
psf_result result;
|
||||||
|
|
||||||
|
if (top < min_i())
|
||||||
|
top = min_i();
|
||||||
|
if (bot > max_i())
|
||||||
|
bot = max_i();
|
||||||
|
if (lef < min_j())
|
||||||
|
lef = min_j();
|
||||||
|
if (rig > max_j())
|
||||||
|
rig = max_j();
|
||||||
|
|
||||||
|
int il = (int) floor((top - min_i()) / (max_i() - min_i()) * rows);
|
||||||
|
int ih = (int) floor((bot - min_i()) / (max_i() - min_i()) * rows);
|
||||||
|
int jl = (int) floor((lef - min_j()) / (max_j() - min_j()) * cols);
|
||||||
|
int jh = (int) floor((rig - min_j()) / (max_j() - min_j()) * cols);
|
||||||
|
|
||||||
|
for (int ii = il; ii <= ih; ii++)
|
||||||
|
for (int jj = jl; jj <= jh; jj++) {
|
||||||
|
|
||||||
|
ale_real ltop = ((ale_real) ii) / rows * (max_i() - min_i()) + min_i();
|
||||||
|
ale_real lbot = ((ale_real) ii + 1) / rows * (max_i() - min_i()) + min_i();
|
||||||
|
ale_real llef = ((ale_real) jj) / cols * (max_j() - min_j()) + min_j();
|
||||||
|
ale_real lrig = ((ale_real) jj + 1) / cols * (max_j() - min_j()) + min_j();
|
||||||
|
|
||||||
|
if (ltop < top)
|
||||||
|
ltop = top;
|
||||||
|
if (lbot > bot)
|
||||||
|
lbot = bot;
|
||||||
|
if (llef < lef)
|
||||||
|
llef = lef;
|
||||||
|
if (lrig > rig)
|
||||||
|
lrig = rig;
|
||||||
|
|
||||||
|
assert (ii >= 0);
|
||||||
|
assert (ii < (int) rows);
|
||||||
|
assert (jj >= 0);
|
||||||
|
assert (jj < (int) cols);
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
result.matrix(k, k) += ((lbot - ltop) * (lrig - llef)
|
||||||
|
* response[ii][jj][k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
309
d2/render/psf/raster.h
Normal file
309
d2/render/psf/raster.h
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __raster_h__
|
||||||
|
#define __raster_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Raster point-spread function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class raster : public psf {
|
||||||
|
protected:
|
||||||
|
ale_real _height;
|
||||||
|
ale_real _width;
|
||||||
|
unsigned int _filter_dim_i;
|
||||||
|
unsigned int _filter_dim_j;
|
||||||
|
unsigned int num_arrays;
|
||||||
|
ale_real **response_arrays;
|
||||||
|
ale_real **response_partials;
|
||||||
|
#if 0
|
||||||
|
ale_real *avg_response;
|
||||||
|
#endif
|
||||||
|
pixel *response_integrals;
|
||||||
|
#if 0
|
||||||
|
pixel avg_integral;
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return ale_real_unexceptional_negation(_height); }
|
||||||
|
ale_real max_i() const { return _height; }
|
||||||
|
ale_real min_j() const { return ale_real_unexceptional_negation(_width); }
|
||||||
|
ale_real max_j() const { return _width; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Element accessor methods.
|
||||||
|
*/
|
||||||
|
unsigned int max_elem_i() {
|
||||||
|
return _filter_dim_i;
|
||||||
|
}
|
||||||
|
unsigned int max_elem_j() {
|
||||||
|
return _filter_dim_j;
|
||||||
|
}
|
||||||
|
ale_real element(unsigned int n, unsigned int i, unsigned int j, unsigned int k) {
|
||||||
|
|
||||||
|
assert (n < num_arrays);
|
||||||
|
assert (i < _filter_dim_i);
|
||||||
|
assert (j < _filter_dim_j);
|
||||||
|
assert (k < 3);
|
||||||
|
|
||||||
|
return response_arrays[n][i * _filter_dim_j * 3 + j * 3 + k];
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
ale_real element(unsigned int i, unsigned int j, unsigned int k) {
|
||||||
|
assert (i < _filter_dim_i);
|
||||||
|
assert (j < _filter_dim_j);
|
||||||
|
assert (k < 3);
|
||||||
|
|
||||||
|
return avg_response[i * _filter_dim_j * 3 + j * 3 + k];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response function
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support.
|
||||||
|
*
|
||||||
|
* generic_response (private):
|
||||||
|
*
|
||||||
|
* A response array for this generic function is provided by the
|
||||||
|
* calling function, and a specific or average response is returned,
|
||||||
|
* based on this array.
|
||||||
|
*
|
||||||
|
* operator():
|
||||||
|
*
|
||||||
|
* The index of the specific response array is provided, from which the
|
||||||
|
* specific response is determined. Alternatively, if no index is
|
||||||
|
* specified, then the average response is returned.
|
||||||
|
*/
|
||||||
|
private:
|
||||||
|
psf_result generic_response(ale_real *response_partial, ale_real top, ale_real
|
||||||
|
bot, ale_real lef, ale_real rig, char channels) const {
|
||||||
|
|
||||||
|
assert (response_partial != NULL);
|
||||||
|
|
||||||
|
psf_result result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lrintf() can be more efficient than floor() or float-to-int
|
||||||
|
* casts. For more details, see Erik de Castro Lopo, "Faster
|
||||||
|
* Floating Point to Integer Conversions":
|
||||||
|
*
|
||||||
|
* http://mega-nerd.com/FPcast/
|
||||||
|
*
|
||||||
|
* In this case, lrintf() seems to be a bit faster than plain
|
||||||
|
* casting, and much faster than floor(0.5 + ...). Casting
|
||||||
|
* from round() seems to be an acceptable alternative to
|
||||||
|
* lrintf().
|
||||||
|
*
|
||||||
|
* Early calculation of common floating-point constants in the
|
||||||
|
* following code is based on an initial implementation by HJ
|
||||||
|
* Hornbeck.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_real i_element_scale = (ale_real) _filter_dim_i / (max_i() - min_i());
|
||||||
|
ale_real j_element_scale = (ale_real) _filter_dim_j / (max_j() - min_j());
|
||||||
|
|
||||||
|
int il = (int) lrintf(i_element_scale * (top - min_i()));
|
||||||
|
int ih = (int) lrintf(i_element_scale * (bot - min_i()));
|
||||||
|
int jl = (int) lrintf(j_element_scale * (lef - min_j()));
|
||||||
|
int jh = (int) lrintf(j_element_scale * (rig - min_j()));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bounds clamping may be faster when performed in integer
|
||||||
|
* arithmetic than in floating-point, so we do this after
|
||||||
|
* float-to-int conversion is complete.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (il < 0)
|
||||||
|
il = 0;
|
||||||
|
if (jl < 0)
|
||||||
|
jl = 0;
|
||||||
|
if (ih > (int) _filter_dim_i)
|
||||||
|
ih = (int) _filter_dim_i;
|
||||||
|
if (jh > (int) _filter_dim_j)
|
||||||
|
jh = (int) _filter_dim_j;
|
||||||
|
|
||||||
|
if (!(il < ih) || !(jl < jh))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
if (!((1 << k) & channels))
|
||||||
|
continue;
|
||||||
|
assert (ih > 0 && jh > 0);
|
||||||
|
assert (ih <= (int) _filter_dim_i);
|
||||||
|
assert (jh <= (int) _filter_dim_j);
|
||||||
|
|
||||||
|
ale_real result_k = 0;
|
||||||
|
|
||||||
|
if (il > 0 && jl > 0)
|
||||||
|
result_k += response_partial[k + 3 * (jl - 1) + 3 * _filter_dim_j * (il - 1)];
|
||||||
|
if (il > 0)
|
||||||
|
result_k -= response_partial[k + 3 * (jh - 1) + 3 * _filter_dim_j * (il - 1)];
|
||||||
|
if (jl > 0)
|
||||||
|
result_k -= response_partial[k + 3 * (jl - 1) + 3 * _filter_dim_j * (ih - 1)];
|
||||||
|
result_k += response_partial[k + 3 * (jh - 1) + 3 * _filter_dim_j * (ih - 1)];
|
||||||
|
result.set_matrix(k, k, result_k);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual unsigned int varieties() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned int select(unsigned int i, unsigned int j) const = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a specific pixel response.
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig, unsigned int variety,
|
||||||
|
char channels) const {
|
||||||
|
assert (variety < num_arrays);
|
||||||
|
|
||||||
|
ale_real *response_partial = response_partials[variety];
|
||||||
|
assert (response_partial != NULL);
|
||||||
|
|
||||||
|
return generic_response(response_partial, top, bot, lef, rig, channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig,
|
||||||
|
unsigned int variety) const {
|
||||||
|
return operator()(top, bot, lef, rig, variety, 0x7);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Get the average pixel response.
|
||||||
|
*/
|
||||||
|
psf_result operator()(float top, float bot, float lef, float rig) const {
|
||||||
|
return generic_response(avg_response, top, bot, lef, rig);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*
|
||||||
|
* Integrate over the whole PSF
|
||||||
|
*/
|
||||||
|
pixel integrate(ale_real *response_array) {
|
||||||
|
pixel result;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (unsigned int k = 0; k < 3 ; k++)
|
||||||
|
result[k] += response_array[i * _filter_dim_j * 3 + j * 3 + k];
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < 3; k++)
|
||||||
|
result[k] *= (((ale_real) 4 * _height * _width)
|
||||||
|
/ (ale_real) (_filter_dim_i * _filter_dim_j));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void partial_integrate(ale_real *target, ale_real *source) {
|
||||||
|
ale_real element_area = (ale_real) (max_i() - min_i())
|
||||||
|
* (ale_real) (max_j() - min_j())
|
||||||
|
/ (ale_real) (_filter_dim_i)
|
||||||
|
/ (ale_real) (_filter_dim_j);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (unsigned int k = 0; k < 3 ; k++) {
|
||||||
|
unsigned int index = i * _filter_dim_j * 3 + j * 3 + k;
|
||||||
|
target[index] = source[index] * element_area
|
||||||
|
+ ((j > 0) ? target[index - 3] : ale_real_0)
|
||||||
|
+ ((i > 0) ? target[index - _filter_dim_j * 3] : ale_real_0)
|
||||||
|
- ((i > 0
|
||||||
|
&& j > 0) ? target[index - _filter_dim_j * 3 - 3] : ale_real_0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute integrals.
|
||||||
|
*/
|
||||||
|
void compute_integrals() {
|
||||||
|
response_integrals = new pixel[num_arrays];
|
||||||
|
|
||||||
|
for (unsigned int n = 0; n < num_arrays; n++)
|
||||||
|
response_integrals[n] = integrate(response_arrays[n]);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
avg_integral = integrate(avg_response);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
response_partials = (ale_real **) malloc(sizeof(ale_real *) * num_arrays);
|
||||||
|
assert(response_partials);
|
||||||
|
for (unsigned int n = 0; n < num_arrays; n++) {
|
||||||
|
response_partials[n] = (ale_real *) malloc(sizeof(ale_real) * _filter_dim_i
|
||||||
|
* _filter_dim_j
|
||||||
|
* 3);
|
||||||
|
assert(response_partials[n]);
|
||||||
|
partial_integrate(response_partials[n], response_arrays[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return elements of given integrals
|
||||||
|
*/
|
||||||
|
pixel integral(unsigned int n) const {
|
||||||
|
assert (response_integrals != NULL);
|
||||||
|
return response_integrals[n];
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
pixel integral() const {
|
||||||
|
return avg_integral;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
raster () {
|
||||||
|
response_integrals = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~raster() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deallocate data structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (unsigned int n = 0; n < num_arrays; n++)
|
||||||
|
free(response_arrays[n]);
|
||||||
|
free(response_arrays);
|
||||||
|
#if 0
|
||||||
|
free(avg_response);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (response_integrals)
|
||||||
|
delete response_integrals;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
192
d2/render/psf/rasterizer.h
Normal file
192
d2/render/psf/rasterizer.h
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_rasterize_h__
|
||||||
|
#define __psf_rasterize_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "raster.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function rasterizer.
|
||||||
|
*
|
||||||
|
* These operations rasterize a PSF to a multiple of the resolution of the
|
||||||
|
* rendering grid for a given frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class rasterizer : public raster {
|
||||||
|
psf *input;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned int varieties() const {
|
||||||
|
return input->varieties();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int select(unsigned int i, unsigned int j) const {
|
||||||
|
return input->select(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
rasterizer (psf *input, transformation t) {
|
||||||
|
this->input = input;
|
||||||
|
|
||||||
|
_height = -input->min_i();
|
||||||
|
|
||||||
|
if (input->max_i() > _height)
|
||||||
|
_height = input->max_i();
|
||||||
|
|
||||||
|
_width = -input->min_j();
|
||||||
|
|
||||||
|
if (input->max_j() > _width)
|
||||||
|
_width = input->max_j();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Approximate the desired resolution.
|
||||||
|
*
|
||||||
|
* Assume that maximum resolution is reached at (at least) one
|
||||||
|
* of the corners of the image. (This should be true for
|
||||||
|
* projective, Euclidean, and translational transformations,
|
||||||
|
* but it would be worthwhile to check/prove this for the
|
||||||
|
* projective case at some point, since it's a bit less
|
||||||
|
* obvious.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
point min_diff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: this loop breaks when height <= 1 or width <= 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < t.unscaled_height(); i += (t.unscaled_height() - 1))
|
||||||
|
for (unsigned int j = 0; j < t.unscaled_width(); j += (t.unscaled_width() - 1)) {
|
||||||
|
point corner = point(i, j);
|
||||||
|
point delta1 = corner - t.scaled_inverse_transform(t.transform_scaled(corner) + point(1, 0));
|
||||||
|
point delta2 = corner - t.scaled_inverse_transform(t.transform_scaled(corner) + point(0, 1));
|
||||||
|
|
||||||
|
for (int index = 0; index < 2; index++) {
|
||||||
|
ale_pos d1 = fabs(delta1[index]);
|
||||||
|
ale_pos d2 = fabs(delta2[index]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take the largest change in each direction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ale_pos delta = (d1 > d2) ? d1 : d2;
|
||||||
|
|
||||||
|
if ((i == 0 && j == 0) || delta < min_diff[index])
|
||||||
|
min_diff[index] = delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real resolution_multiplier = 20; /* Arbitrary */
|
||||||
|
|
||||||
|
_filter_dim_i = (int) ceil((ale_real) 2 * _height * resolution_multiplier / (ale_real) min_diff[0]);
|
||||||
|
_filter_dim_j = (int) ceil((ale_real) 2 * _width * resolution_multiplier / (ale_real) min_diff[1]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that the array has an odd number of elements in each
|
||||||
|
* direction. This allows us to move the center to the right
|
||||||
|
* place when using FFTW.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (_filter_dim_i % 2 == 0)
|
||||||
|
_filter_dim_i++;
|
||||||
|
if (_filter_dim_j % 2 == 0)
|
||||||
|
_filter_dim_j++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the number of arrays to create.
|
||||||
|
*/
|
||||||
|
|
||||||
|
num_arrays = input->varieties();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create arrays
|
||||||
|
*/
|
||||||
|
|
||||||
|
response_arrays = (ale_real **)malloc(num_arrays * sizeof(ale_real *));
|
||||||
|
|
||||||
|
if (!response_arrays) {
|
||||||
|
fprintf(stderr, "Could not allocate in rasterizer.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_real stepsize_i = (2 * _height) / _filter_dim_i;
|
||||||
|
ale_real stepsize_j = (2 * _width) / _filter_dim_j;
|
||||||
|
ale_real divisor = stepsize_i * stepsize_j;
|
||||||
|
|
||||||
|
for (unsigned int n = 0; n < num_arrays; n++) {
|
||||||
|
response_arrays[n] = (ale_real *)malloc(_filter_dim_i * _filter_dim_j * 3
|
||||||
|
* sizeof(ale_real));
|
||||||
|
|
||||||
|
if (!response_arrays[n]) {
|
||||||
|
fprintf(stderr, "Could not allocate in rasterizer.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++) {
|
||||||
|
psf_result r
|
||||||
|
= (*input)(-_height + stepsize_i * (ale_real) i,
|
||||||
|
-_height + stepsize_i * (ale_real) (i + 1),
|
||||||
|
-_width + stepsize_j * (ale_real) j,
|
||||||
|
-_width + stepsize_j * (ale_real) (j + 1), n);
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < 3; k++) {
|
||||||
|
response_arrays[n][i * _filter_dim_j * 3 + j * 3 + k]
|
||||||
|
= r.matrix(k, k) / divisor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
avg_response = (ale_real *)malloc(_filter_dim_i * _filter_dim_j * 3
|
||||||
|
* sizeof(ale_real));
|
||||||
|
|
||||||
|
if (!avg_response) {
|
||||||
|
fprintf(stderr, "Could not allocate in rasterizer.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (unsigned int j = 0; j < _filter_dim_j; j++) {
|
||||||
|
psf::psf_result r
|
||||||
|
= (*input)(-_height + stepsize_i * i,
|
||||||
|
-_height + stepsize_i * (i + 1),
|
||||||
|
-_width + stepsize_j * j,
|
||||||
|
-_width + stepsize_j * (j + 1));
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < 3; k++)
|
||||||
|
avg_response[i * _filter_dim_j * 3 + j * 3 + k]
|
||||||
|
= r.matrix(k, k) / divisor;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
compute_integrals();
|
||||||
|
|
||||||
|
// fprintf(stderr, "(w=%f h=%f we=%d he=%d [", _width, _height, _filter_dim_j, _filter_dim_i);
|
||||||
|
// for (unsigned int i = 0; i < _filter_dim_i; i++)
|
||||||
|
// for (unsigned int j = 0; j < _filter_dim_j; j++)
|
||||||
|
// fprintf(stderr, "%f ", response_arrays[0][i * _filter_dim_j * 3 + j * 3 + 0]);
|
||||||
|
// fprintf(stderr, "])");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
101
d2/render/psf/scalar_mult.h
Normal file
101
d2/render/psf/scalar_mult.h
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_scalar_mult_h__
|
||||||
|
#define __psf_scalar_mult_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function module.
|
||||||
|
*
|
||||||
|
* This module implements the scalar_mult (f1 * f2) of point-spread functions f1 and
|
||||||
|
* f2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class scalar_mult : public psf {
|
||||||
|
ale_pos _radius;
|
||||||
|
psf *f;
|
||||||
|
ale_real scalar;
|
||||||
|
ale_real _min_i, _max_i, _min_j, _max_j;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return _min_i; }
|
||||||
|
ale_real max_i() const { return _max_i; }
|
||||||
|
ale_real min_j() const { return _min_j; }
|
||||||
|
ale_real max_j() const { return _max_j; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the number of varieties supported by this PSF. These usually
|
||||||
|
* correspond to different points in the sensor array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int varieties() {
|
||||||
|
return f->varieties();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select the variety appropriate for a given position in the sensor
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int select(unsigned int i, unsigned int j) {
|
||||||
|
return f->select(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response function
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety of the responding pixel is provided, in
|
||||||
|
* case response is not uniform for all pixels (e.g. some sensor arrays
|
||||||
|
* stagger red, green, and blue sensors).
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig,
|
||||||
|
unsigned int variety) const {
|
||||||
|
psf_result result;
|
||||||
|
psf_result r;
|
||||||
|
|
||||||
|
r = (*f)(top, bot, lef, rig, variety);
|
||||||
|
|
||||||
|
for (int k1 = 0; k1 < 3; k1++)
|
||||||
|
for (int k2 = 0; k2 < 3; k2++)
|
||||||
|
result.set_matrix(k1, k2, scalar * r.get_matrix(k1, k2));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar_mult(ale_real s, psf *f) {
|
||||||
|
this->scalar = s;
|
||||||
|
this->f = f;
|
||||||
|
|
||||||
|
_min_i = f->min_i();
|
||||||
|
_min_j = f->min_j();
|
||||||
|
_max_i = f->max_i();
|
||||||
|
_max_j = f->max_j();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
186
d2/render/psf/stdin.h
Normal file
186
d2/render/psf/stdin.h
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_stdin_h__
|
||||||
|
#define __psf_stdin_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function module.
|
||||||
|
*
|
||||||
|
* This response function is configured by input from stdin. A series of
|
||||||
|
* prompts indicates the information required.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class psf_stdin : public psf {
|
||||||
|
ale_real _height;
|
||||||
|
ale_real _width;
|
||||||
|
int _filter_dim_i;
|
||||||
|
int _filter_dim_j;
|
||||||
|
ale_real *response_array;
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return -_height; }
|
||||||
|
ale_real max_i() const { return _height; }
|
||||||
|
ale_real min_j() const { return -_width; }
|
||||||
|
ale_real max_j() const { return _width; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response functions
|
||||||
|
*
|
||||||
|
* response_generic() and operator()()
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety of the responding pixel is provided, in
|
||||||
|
* case response is not uniform for all pixels (e.g. some sensor arrays
|
||||||
|
* stagger red, green, and blue sensors).
|
||||||
|
*/
|
||||||
|
psf_result response_generic(ale_real *response_array, ale_real top, ale_real bot,
|
||||||
|
ale_real lef, ale_real rig) const {
|
||||||
|
|
||||||
|
assert (response_array != NULL);
|
||||||
|
|
||||||
|
psf_result result;
|
||||||
|
|
||||||
|
if (top < min_i())
|
||||||
|
top = min_i();
|
||||||
|
if (bot > max_i())
|
||||||
|
bot = max_i();
|
||||||
|
if (lef < min_j())
|
||||||
|
lef = min_j();
|
||||||
|
if (rig > max_j())
|
||||||
|
rig = max_j();
|
||||||
|
|
||||||
|
int il = (int) floor((top - min_i()) / (max_i() - min_i()) * _filter_dim_i);
|
||||||
|
int ih = (int) floor((bot - min_i()) / (max_i() - min_i()) * _filter_dim_i);
|
||||||
|
int jl = (int) floor((lef - min_j()) / (max_j() - min_j()) * _filter_dim_j);
|
||||||
|
int jh = (int) floor((rig - min_j()) / (max_j() - min_j()) * _filter_dim_j);
|
||||||
|
|
||||||
|
// fprintf(stderr, "(il, ih, jl, jh) = (%d, %d, %d, %d)\n", il, ih, jl, jh);
|
||||||
|
|
||||||
|
for (int ii = il; ii <= ih; ii++)
|
||||||
|
for (int jj = jl; jj <= jh; jj++) {
|
||||||
|
|
||||||
|
ale_real ltop = ((ale_real) ii) / _filter_dim_i * (max_i() - min_i()) + min_i();
|
||||||
|
ale_real lbot = ((ale_real) ii + 1) / _filter_dim_i * (max_i() - min_i()) + min_i();
|
||||||
|
ale_real llef = ((ale_real) jj) / _filter_dim_j * (max_j() - min_j()) + min_j();
|
||||||
|
ale_real lrig = ((ale_real) jj + 1) / _filter_dim_j * (max_j() - min_j()) + min_j();
|
||||||
|
|
||||||
|
if (ltop < top)
|
||||||
|
ltop = top;
|
||||||
|
if (lbot > bot)
|
||||||
|
lbot = bot;
|
||||||
|
if (llef < lef)
|
||||||
|
llef = lef;
|
||||||
|
if (lrig > rig)
|
||||||
|
lrig = rig;
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
result.matrix(k, k) += (ale_real) ((lbot - ltop) * (lrig - llef)
|
||||||
|
* response_array[3 * _filter_dim_j * ii + 3 * jj + k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real
|
||||||
|
rig, unsigned int variety) const {
|
||||||
|
return response_generic(response_array, top, bot, lef, rig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void class_error() {
|
||||||
|
fprintf(stderr, "\n\nALE Panic: Error acquiring input. Exiting.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
psf_stdin () {
|
||||||
|
|
||||||
|
printf("\nEnter filter support height, in units of pixels (e.g. 2.5): ");
|
||||||
|
fflush(stdout);
|
||||||
|
double dheight;
|
||||||
|
if (scanf("%lf", &dheight) != 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
_height = dheight / 2;
|
||||||
|
|
||||||
|
printf("\nEnter filter support width, in units of pixels (e.g. 2.5): ");
|
||||||
|
fflush(stdout);
|
||||||
|
double dwidth;
|
||||||
|
if (scanf("%lf", &dwidth) != 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
_width = dwidth / 2;
|
||||||
|
|
||||||
|
printf("\nEnter the number of rows in the filter (e.g. 3): ");
|
||||||
|
fflush(stdout);
|
||||||
|
if (scanf("%d", &_filter_dim_i) != 1 || _filter_dim_i < 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nEnter the number of columns in the filter (e.g. 3): ");
|
||||||
|
fflush(stdout);
|
||||||
|
if (scanf("%d", &_filter_dim_j) != 1 || _filter_dim_j < 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
response_array = (ale_real *) malloc(_filter_dim_i * _filter_dim_j * 3
|
||||||
|
* sizeof(ale_real));
|
||||||
|
|
||||||
|
if (response_array == NULL) {
|
||||||
|
fprintf(stderr, "\n\nCould not allocate filter.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nFilter elements are labeled as (row, column, channel). The red channel of\n");
|
||||||
|
printf("the top-left element is (0, 0, 0), and the blue channel of the bottom-right\n");
|
||||||
|
printf("element is (%d, %d, 2).\n\n", _filter_dim_i - 1, _filter_dim_j - 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
printf("Enter value for element (%d, %d, %d) (e.g. 2.5): ",
|
||||||
|
i, j, k);
|
||||||
|
fflush(stdout);
|
||||||
|
double delem;
|
||||||
|
if (scanf("%lf", &delem) != 1)
|
||||||
|
class_error();
|
||||||
|
response_array[i * _filter_dim_j * 3 + j * 3 + k] = delem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~psf_stdin() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't free this without creating a copy constructor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
free(response_array);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
224
d2/render/psf/stdin_vg.h
Normal file
224
d2/render/psf/stdin_vg.h
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_stdin_vg_h__
|
||||||
|
#define __psf_stdin_vg_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function module.
|
||||||
|
*
|
||||||
|
* This response function is configured by input from stdin. A series of
|
||||||
|
* prompts indicates the information required.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class psf_stdin_vg : public psf {
|
||||||
|
ale_real _height;
|
||||||
|
ale_real _width;
|
||||||
|
ale_real gap_width;
|
||||||
|
int _filter_dim_i;
|
||||||
|
int _filter_dim_j;
|
||||||
|
ale_real *response_array;
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return -_height; }
|
||||||
|
ale_real max_i() const { return _height; }
|
||||||
|
ale_real min_j() const { return -_width - fabs(gap_width); }
|
||||||
|
ale_real max_j() const { return _width + fabs(gap_width); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the number of varieties supported by this PSF. These usually
|
||||||
|
* correspond to different points in the sensor array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int varieties() const {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select the variety appropriate for a given position in the sensor
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int select(unsigned int i, unsigned int j) {
|
||||||
|
return (j % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response functions
|
||||||
|
*
|
||||||
|
* response_generic() and operator()()
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety of the responding pixel is provided, in
|
||||||
|
* case response is not uniform for all pixels (e.g. some sensor arrays
|
||||||
|
* stagger red, green, and blue sensors).
|
||||||
|
*/
|
||||||
|
psf_result response_generic(ale_real *response_array, ale_real top, ale_real bot,
|
||||||
|
ale_real lef, ale_real rig, unsigned int variety) const {
|
||||||
|
|
||||||
|
assert (response_array != NULL);
|
||||||
|
assert (variety < varieties());
|
||||||
|
|
||||||
|
psf_result result;
|
||||||
|
|
||||||
|
ale_pos offset = (gap_width / 2)
|
||||||
|
- (gap_width / 7) * variety;
|
||||||
|
|
||||||
|
lef -= offset;
|
||||||
|
rig -= offset;
|
||||||
|
|
||||||
|
if (top < min_i())
|
||||||
|
top = min_i();
|
||||||
|
if (bot > max_i())
|
||||||
|
bot = max_i();
|
||||||
|
if (lef < -_width)
|
||||||
|
lef = -_width;
|
||||||
|
if (rig > _width)
|
||||||
|
rig = _width;
|
||||||
|
|
||||||
|
int il = (int) floor((top - min_i()) / (max_i() - min_i()) * _filter_dim_i);
|
||||||
|
int ih = (int) floor((bot - min_i()) / (max_i() - min_i()) * _filter_dim_i);
|
||||||
|
int jl = (int) floor((lef + _width) / (_width * 2) * _filter_dim_j);
|
||||||
|
int jh = (int) floor((rig + _width) / (_width * 2) * _filter_dim_j);
|
||||||
|
|
||||||
|
// fprintf(stderr, "(il, ih, jl, jh) = (%d, %d, %d, %d)\n", il, ih, jl, jh);
|
||||||
|
|
||||||
|
for (int ii = il; ii <= ih; ii++)
|
||||||
|
for (int jj = jl; jj <= jh; jj++) {
|
||||||
|
|
||||||
|
ale_real ltop = ((ale_real) ii) / (ale_real) _filter_dim_i * (max_i() - min_i()) + min_i();
|
||||||
|
ale_real lbot = ((ale_real) ii + 1) / (ale_real) _filter_dim_i * (max_i() - min_i()) + min_i();
|
||||||
|
ale_real llef = ((ale_real) jj) / (ale_real) _filter_dim_j * ((ale_real) _width * (ale_real) 2) - _width;
|
||||||
|
ale_real lrig = ((ale_real) jj + 1) / (ale_real) _filter_dim_j * (_width * (ale_real) 2) - _width;
|
||||||
|
|
||||||
|
if (ltop < top)
|
||||||
|
ltop = top;
|
||||||
|
if (lbot > bot)
|
||||||
|
lbot = bot;
|
||||||
|
if (llef < lef)
|
||||||
|
llef = lef;
|
||||||
|
if (lrig > rig)
|
||||||
|
lrig = rig;
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
result.matrix(k, k) += (ale_real) ((lbot - ltop) * (lrig - llef)
|
||||||
|
* response_array[3 * _filter_dim_j * ii + 3 * jj + k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real
|
||||||
|
rig, unsigned int variety) const {
|
||||||
|
return response_generic(response_array, top, bot, lef, rig, variety);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig) const {
|
||||||
|
return response_generic(response_array, top, bot, lef, rig, 4);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void class_error() {
|
||||||
|
fprintf(stderr, "\n\nALE Panic: Error acquiring input. Exiting.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
psf_stdin_vg () {
|
||||||
|
|
||||||
|
printf("\nEnter vertical gap width, in units of pixels (e.g. 1.0): ");
|
||||||
|
fflush(stdout);
|
||||||
|
double dgap_width;
|
||||||
|
if (scanf("%lf", &dgap_width) != 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
gap_width = dgap_width;
|
||||||
|
|
||||||
|
printf("\nEnter filter support height, in units of pixels (e.g. 2.5): ");
|
||||||
|
fflush(stdout);
|
||||||
|
double dheight;
|
||||||
|
if (scanf("%lf", &dheight) != 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
_height = dheight / 2;
|
||||||
|
|
||||||
|
printf("\nEnter filter support width, in units of pixels (e.g. 2.5): ");
|
||||||
|
fflush(stdout);
|
||||||
|
double dwidth;
|
||||||
|
if (scanf("%lf", &dwidth) != 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
_width = dwidth / 2;
|
||||||
|
|
||||||
|
printf("\nEnter the number of rows in the filter (e.g. 3): ");
|
||||||
|
fflush(stdout);
|
||||||
|
if (scanf("%d", &_filter_dim_i) != 1 || _filter_dim_i < 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nEnter the number of columns in the filter (e.g. 3): ");
|
||||||
|
fflush(stdout);
|
||||||
|
if (scanf("%d", &_filter_dim_j) != 1 || _filter_dim_j < 1) {
|
||||||
|
class_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
response_array = (ale_real *) malloc(_filter_dim_i * _filter_dim_j * 3
|
||||||
|
* sizeof(ale_real));
|
||||||
|
|
||||||
|
if (response_array == NULL) {
|
||||||
|
fprintf(stderr, "\n\nCould not allocate filter.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nFilter elements are labeled as (row, column, channel). The red channel of\n");
|
||||||
|
printf("the top-left element is (0, 0, 0), and the blue channel of the bottom-right\n");
|
||||||
|
printf("element is (%d, %d, 2).\n\n", _filter_dim_i - 1, _filter_dim_j - 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < _filter_dim_i; i++)
|
||||||
|
for (int j = 0; j < _filter_dim_j; j++)
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
printf("Enter value for element (%d, %d, %d) (e.g. 2.5): ",
|
||||||
|
i, j, k);
|
||||||
|
fflush(stdout);
|
||||||
|
double delem;
|
||||||
|
if (scanf("%lf", &delem) != 1)
|
||||||
|
class_error();
|
||||||
|
response_array[i * _filter_dim_j * 3 + j * 3 + k] = delem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~psf_stdin_vg() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't free this without creating a copy constructor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
free(response_array);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
131
d2/render/psf/sum.h
Normal file
131
d2/render/psf/sum.h
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
// Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psf_sum_h__
|
||||||
|
#define __psf_sum_h__
|
||||||
|
|
||||||
|
#include "../../point.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-spread function module.
|
||||||
|
*
|
||||||
|
* This module implements the sum (f1 + f2) of point-spread functions f1 and
|
||||||
|
* f2. This is not a convolution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class sum : public psf {
|
||||||
|
ale_pos _radius;
|
||||||
|
psf *f1, *f2;
|
||||||
|
ale_real _min_i, _max_i, _min_j, _max_j;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* The following four functions indicate filter boundaries. Filter
|
||||||
|
* support may include everything up to and including the boundaries
|
||||||
|
* specified here.
|
||||||
|
*/
|
||||||
|
ale_real min_i() const { return _min_i; }
|
||||||
|
ale_real max_i() const { return _max_i; }
|
||||||
|
ale_real min_j() const { return _min_j; }
|
||||||
|
ale_real max_j() const { return _max_j; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the number of varieties supported by this PSF. These usually
|
||||||
|
* correspond to different points in the sensor array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int varieties() {
|
||||||
|
return f1->varieties() * f2->varieties();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select the variety appropriate for a given position in the sensor
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
virtual unsigned int select(unsigned int i, unsigned int j) {
|
||||||
|
return (f1->select(i, j) * f2->varieties() + f2->select(i, j));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response function
|
||||||
|
*
|
||||||
|
* Get the response to the rectangle bounded by (top, bot, lef, rig).
|
||||||
|
* This function must correctly handle points which fall outside of the
|
||||||
|
* filter support. The variety of the responding pixel is provided, in
|
||||||
|
* case response is not uniform for all pixels (e.g. some sensor arrays
|
||||||
|
* stagger red, green, and blue sensors).
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig,
|
||||||
|
unsigned int variety) const {
|
||||||
|
psf_result result;
|
||||||
|
psf_result r1, r2;
|
||||||
|
|
||||||
|
r1 = (*f1)(top, bot, lef, rig, variety / f2->varieties());
|
||||||
|
r2 = (*f2)(top, bot, lef, rig, variety % f2->varieties());
|
||||||
|
|
||||||
|
for (int k1 = 0; k1 < 3; k1++)
|
||||||
|
for (int k2 = 0; k2 < 3; k2++)
|
||||||
|
result.set_matrix(k1, k2, r1.get_matrix(k1, k2)
|
||||||
|
+ r2.get_matrix(k1, k2));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Get the average pixel response.
|
||||||
|
*/
|
||||||
|
psf_result operator()(ale_real top, ale_real bot, ale_real lef, ale_real rig) {
|
||||||
|
psf_result result;
|
||||||
|
psf_result r1, r2;
|
||||||
|
|
||||||
|
r1 = (*f1)(top, bot, lef, rig);
|
||||||
|
r2 = (*f2)(top, bot, lef, rig);
|
||||||
|
|
||||||
|
for (int k1 = 0; k1 < 3; k1++)
|
||||||
|
for (int k2 = 0; k2 < 3; k2++)
|
||||||
|
result.set_matrix(k1, k2, r1.get_matrix(k1, k2)
|
||||||
|
+ r2.get_matrix(k1, k2));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sum(psf *f1, psf *f2) {
|
||||||
|
this->f1 = f1;
|
||||||
|
this->f2 = f2;
|
||||||
|
|
||||||
|
_min_i = f1->min_i();
|
||||||
|
_min_j = f1->min_j();
|
||||||
|
_max_i = f1->max_i();
|
||||||
|
_max_j = f1->max_j();
|
||||||
|
|
||||||
|
if (_min_i > f2->min_i())
|
||||||
|
_min_i = f2->min_i();
|
||||||
|
if (_min_j > f2->min_j())
|
||||||
|
_min_j = f2->min_j();
|
||||||
|
if (_max_i < f2->max_i())
|
||||||
|
_max_i = f2->max_i();
|
||||||
|
if (_max_j < f2->max_j())
|
||||||
|
_max_j = f2->max_j();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
218
d2/render/usm.h
Normal file
218
d2/render/usm.h
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
// Copyright 2002, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* usm.h: A render subclass that implements an unsharp mask
|
||||||
|
* postprocessing algorithm.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __usm_h__
|
||||||
|
#define __usm_h__
|
||||||
|
|
||||||
|
#include "../image.h"
|
||||||
|
#include "../render.h"
|
||||||
|
#include "psf/psf.h"
|
||||||
|
|
||||||
|
class usm : public render {
|
||||||
|
|
||||||
|
int done;
|
||||||
|
int inc;
|
||||||
|
image *done_image;
|
||||||
|
render *input;
|
||||||
|
const image *input_image;
|
||||||
|
const image *input_defined;
|
||||||
|
ale_real scale_factor;
|
||||||
|
ale_real usm_multiplier;
|
||||||
|
psf *lresponse, *nlresponse;
|
||||||
|
const exposure *exp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USM value for point (i, j).
|
||||||
|
*/
|
||||||
|
pixel _usm(int i, int j, const image *im) {
|
||||||
|
|
||||||
|
pixel result;
|
||||||
|
|
||||||
|
ale_real d = scale_factor / 2;
|
||||||
|
|
||||||
|
pixel weight;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convolve with the linear filter, iterating over pixels
|
||||||
|
* according to the filter support, and tracking contribution
|
||||||
|
* weights in the variable WEIGHT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int ii = (int) floor(i - d + lresponse->min_i());
|
||||||
|
ii <= ceil(i + d + lresponse->max_i()); ii++)
|
||||||
|
for (int jj = (int) floor(j - d + lresponse->min_j());
|
||||||
|
jj <= ceil(j + d + lresponse->max_j()); jj++) {
|
||||||
|
|
||||||
|
ale_real top = ii - d;
|
||||||
|
ale_real bot = ii + d;
|
||||||
|
ale_real lef = jj - d;
|
||||||
|
ale_real rig = jj + d;
|
||||||
|
|
||||||
|
if (ii >= (int) 0
|
||||||
|
&& ii < (int) im->height()
|
||||||
|
&& jj >= (int) 0
|
||||||
|
&& jj < (int) im->width()
|
||||||
|
&& input_defined->get_pixel(ii, jj)[0]) {
|
||||||
|
|
||||||
|
class psf::psf_result r = (*lresponse)((top - i) / scale_factor,
|
||||||
|
(bot - i) / scale_factor,
|
||||||
|
(lef - j) / scale_factor,
|
||||||
|
(rig - j) / scale_factor);
|
||||||
|
|
||||||
|
if (nlresponse) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convolve with the non-linear filter,
|
||||||
|
* iterating over pixels according to the
|
||||||
|
* filter support, and tracking contribution
|
||||||
|
* weights in the variable WWEIGHT.
|
||||||
|
*
|
||||||
|
* Note: This approach is efficient
|
||||||
|
* space-wise, but inefficient timewise. There
|
||||||
|
* is probably a better approach to this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pixel rresult(0, 0, 0), wweight(0, 0, 0);
|
||||||
|
|
||||||
|
for (int iii = (int) floor(ii - d + nlresponse->min_i());
|
||||||
|
iii <= ceil(ii + d + lresponse->max_i()); iii++)
|
||||||
|
for (int jjj = (int) floor(jj - d + nlresponse->min_j());
|
||||||
|
jjj <= ceil(jj + d + lresponse->max_j()); jjj++) {
|
||||||
|
|
||||||
|
ale_real top = iii - d;
|
||||||
|
ale_real bot = iii + d;
|
||||||
|
ale_real lef = jjj - d;
|
||||||
|
ale_real rig = jjj + d;
|
||||||
|
|
||||||
|
if (iii >= (int) 0
|
||||||
|
&& iii < (int) im->height()
|
||||||
|
&& jjj >= (int) 0
|
||||||
|
&& jjj < (int) im->width()
|
||||||
|
&& input_defined->get_pixel(iii, jjj)[0]) {
|
||||||
|
|
||||||
|
class psf::psf_result r = (*nlresponse)((top - ii) / scale_factor,
|
||||||
|
(bot - ii) / scale_factor,
|
||||||
|
(lef - jj) / scale_factor,
|
||||||
|
(rig - jj) / scale_factor);
|
||||||
|
|
||||||
|
wweight += r.weight();
|
||||||
|
rresult += r(exp->unlinearize(im->get_pixel(iii, jjj)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += r(exp->linearize(rresult / wweight));
|
||||||
|
} else {
|
||||||
|
result += r(im->get_pixel(ii, jj));
|
||||||
|
}
|
||||||
|
|
||||||
|
weight += r.weight();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result /= weight;
|
||||||
|
result = im->get_pixel(i, j) - result;
|
||||||
|
|
||||||
|
if (finite(result[0])
|
||||||
|
&& finite(result[1])
|
||||||
|
&& finite(result[2]))
|
||||||
|
return result;
|
||||||
|
else
|
||||||
|
return pixel(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _filter() {
|
||||||
|
assert (done_image->height() == input_image->height());
|
||||||
|
assert (done_image->width() == input_image->width());
|
||||||
|
assert (done_image->depth() == input_image->depth());
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < done_image->height(); i++)
|
||||||
|
for (unsigned int j = 0; j < done_image->width(); j++) {
|
||||||
|
|
||||||
|
if (!input_defined->get_pixel(i, j)[0])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
done_image->set_pixel(i, j,
|
||||||
|
input_image->get_pixel(i, j)
|
||||||
|
+ usm_multiplier
|
||||||
|
* _usm(i, j, input_image));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
usm(render *input, ale_real scale_factor, ale_real usm_multiplier, int _inc,
|
||||||
|
psf *lresponse, psf *nlresponse, exposure *exp) {
|
||||||
|
this->input = input;
|
||||||
|
done = 0;
|
||||||
|
inc = _inc;
|
||||||
|
this->scale_factor = scale_factor;
|
||||||
|
this->usm_multiplier = usm_multiplier;
|
||||||
|
this->lresponse = lresponse;
|
||||||
|
this->nlresponse = nlresponse;
|
||||||
|
this->exp = exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const image *get_image() {
|
||||||
|
if (done)
|
||||||
|
return done_image;
|
||||||
|
else
|
||||||
|
return input->get_image();
|
||||||
|
}
|
||||||
|
|
||||||
|
const image *get_defined() {
|
||||||
|
return input->get_defined();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sync(int n) {
|
||||||
|
render::sync(n);
|
||||||
|
input->sync(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void step() {
|
||||||
|
}
|
||||||
|
|
||||||
|
int sync() {
|
||||||
|
input->sync();
|
||||||
|
fprintf(stderr, "Applying USM");
|
||||||
|
done = 1;
|
||||||
|
done_image = input->get_image()->clone("USM done_image");
|
||||||
|
input_image = input->get_image();
|
||||||
|
input_defined = input->get_defined();
|
||||||
|
_filter();
|
||||||
|
|
||||||
|
if (inc)
|
||||||
|
image_rw::output(done_image);
|
||||||
|
|
||||||
|
fprintf(stderr, ".\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~usm() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
74
d2/render/zero.h
Normal file
74
d2/render/zero.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* zero.h: A renderer for the zero filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __render_zero_h__
|
||||||
|
#define __render_zero_h__
|
||||||
|
|
||||||
|
#include "incremental.h"
|
||||||
|
#include "../image_zero.h"
|
||||||
|
|
||||||
|
class zero : public incremental {
|
||||||
|
public:
|
||||||
|
zero(invariant *inv) : incremental(inv) {
|
||||||
|
assert (typeid(*inv->ssfe()->get_scaled_filter()->get_filter()) == typeid(filter::zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform the current rendering step.
|
||||||
|
*/
|
||||||
|
virtual void step() {
|
||||||
|
assert (get_step() >= -1);
|
||||||
|
if (get_step() == 0) {
|
||||||
|
transformation t = align::of(0);
|
||||||
|
|
||||||
|
const image *im = image_rw::open(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: This approach to trimming pixels is probably a
|
||||||
|
* bit too aggressive. If it is changed, be sure to
|
||||||
|
* also change the corresponding lines in
|
||||||
|
* incremental.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned int trim_size = (int) ceil(get_scale_factor()) - 1;
|
||||||
|
|
||||||
|
accum_image = new image_zero((int) floor(im->height() * get_scale_factor()) - trim_size,
|
||||||
|
(int) floor(im->width() * get_scale_factor()) - trim_size, 3);
|
||||||
|
|
||||||
|
set_extents_by_map(0, t);
|
||||||
|
|
||||||
|
image_rw::close(0);
|
||||||
|
} else if (align::match(get_step())) {
|
||||||
|
transformation t = align::of(get_step());
|
||||||
|
if (is_extend())
|
||||||
|
increase_extents_by_map(get_step(), t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_memory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
222
d2/render_parse.h
Normal file
222
d2/render_parse.h
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __render_parse_h__
|
||||||
|
#define __render_parse_h__
|
||||||
|
|
||||||
|
#include "render.h"
|
||||||
|
#include "render/combine.h"
|
||||||
|
#include "render/invariant.h"
|
||||||
|
#include "render/incremental.h"
|
||||||
|
#include "render/zero.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse strings describing renderers, and return a renderer satisfying
|
||||||
|
* the string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class render_parse {
|
||||||
|
private:
|
||||||
|
static int strpfix(const char *a, const char *b) {
|
||||||
|
return strncmp(a, b, strlen(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nomem() {
|
||||||
|
fprintf(stderr, "\n\n*** Error: unable to allocate memory in render_parse. ***\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void syntax_error(const char *explanation) {
|
||||||
|
fprintf(stderr, "\n\n*** Error: Render syntax: %s ***\n\n", explanation);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static filter::filter *get_SF_atomic(const char *type) {
|
||||||
|
double param;
|
||||||
|
|
||||||
|
if (!strcmp("sinc", type)) {
|
||||||
|
return new filter::sinc();
|
||||||
|
} else if (!strpfix("lanc:", type)) {
|
||||||
|
if (sscanf(type + strlen("lanc:"), "%lf", ¶m) != 1)
|
||||||
|
syntax_error("Unable to get lanczos diameter.");
|
||||||
|
return new filter::lanczos(param/2);
|
||||||
|
} else if (!strpfix("triangle:", type)) {
|
||||||
|
if (sscanf(type + strlen("triangle:"), "%lf", ¶m) != 1)
|
||||||
|
syntax_error("Unable to get triangle diameter.");
|
||||||
|
return new filter::triangle(param/2);
|
||||||
|
} else if (!strpfix("box:", type)) {
|
||||||
|
if (sscanf(type + strlen("box:"), "%lf", ¶m) != 1)
|
||||||
|
syntax_error("Unable to get box diameter.");
|
||||||
|
return new filter::box(param/2);
|
||||||
|
} else if (!strpfix("gauss:", type)) {
|
||||||
|
if (sscanf(type + strlen("gauss:"), "%lf", ¶m) != 1)
|
||||||
|
syntax_error("Unable to get gauss deviation.");
|
||||||
|
return new filter::gauss(param);
|
||||||
|
} else if (!strpfix("zero", type)) {
|
||||||
|
return new filter::zero();
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "get_SF_atomic type %s\n", type);
|
||||||
|
syntax_error("Unable to get filter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This line should never be reached; it's included to avoid
|
||||||
|
* 'unreachable' messages emitted by some compilers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static filter::filter *get_SF(const char *orig_type) {
|
||||||
|
char *type = strdup(orig_type);
|
||||||
|
if (type == NULL)
|
||||||
|
nomem();
|
||||||
|
|
||||||
|
char *star_index = (char *) type;
|
||||||
|
while (*star_index != '\0'
|
||||||
|
&& *star_index != '*')
|
||||||
|
star_index++;
|
||||||
|
|
||||||
|
if (*star_index == '\0') {
|
||||||
|
free(type);
|
||||||
|
return get_SF_atomic(orig_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
*star_index = '\0';
|
||||||
|
filter::filter *result = new filter::mult(
|
||||||
|
get_SF_atomic(type),
|
||||||
|
get_SF(star_index + 1));
|
||||||
|
*star_index = '*';
|
||||||
|
free(type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static filter::scaled_filter *get_SSF(const char *type) {
|
||||||
|
if (!strpfix("coarse:", type)) {
|
||||||
|
return new filter::scaled_filter(get_SF(type + strlen("coarse:")), 1);
|
||||||
|
} else if (!strpfix("fine:", type)) {
|
||||||
|
return new filter::scaled_filter(get_SF(type + strlen("fine:")), 0);
|
||||||
|
} else if (!strpfix("auto:", type)) {
|
||||||
|
return new filter::scaled_filter(get_SF(type + strlen("auto:")), 2);
|
||||||
|
} else {
|
||||||
|
return new filter::scaled_filter(get_SF(type), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static filter::ssfe *get_SSFE(const char *type) {
|
||||||
|
if (!strpfix("ex:", type)) {
|
||||||
|
return new filter::ssfe(get_SSF(type + strlen("ex:")), 1);
|
||||||
|
} else if (!strpfix("nex:", type)) {
|
||||||
|
return new filter::ssfe(get_SSF(type + strlen("nex:")), 0);
|
||||||
|
} else {
|
||||||
|
return new filter::ssfe(get_SSF(type), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static render *get_invariant(const char *type) {
|
||||||
|
double param;
|
||||||
|
int offset;
|
||||||
|
invariant *i;
|
||||||
|
if (!strpfix("min:", type)) {
|
||||||
|
i = new invariant(get_SSFE(type + strlen("min:")));
|
||||||
|
i->set_min();
|
||||||
|
} else if (!strpfix("max:", type)) {
|
||||||
|
i = new invariant(get_SSFE(type + strlen("max:")));
|
||||||
|
i->set_max();
|
||||||
|
} else if (!strpfix("last:", type)) {
|
||||||
|
i = new invariant(get_SSFE(type + strlen("last:")));
|
||||||
|
i->set_last();
|
||||||
|
} else if (!strpfix("first:", type)) {
|
||||||
|
i = new invariant(get_SSFE(type + strlen("first:")));
|
||||||
|
i->set_first();
|
||||||
|
} else if (!strpfix("avg:", type)) {
|
||||||
|
i = new invariant(get_SSFE(type + strlen("avg:")));
|
||||||
|
i->set_avg();
|
||||||
|
} else if (!strpfix("avgf:", type)) {
|
||||||
|
if (sscanf(type + strlen("avgf:"), "%lf%n", ¶m, &offset) != 1)
|
||||||
|
syntax_error("Unable to get avgf weight criterion.");
|
||||||
|
i = new invariant(get_SSFE(type + strlen("avgf:") + offset + strlen(":")));
|
||||||
|
i->set_avgf(param);
|
||||||
|
} else if (!strpfix("median:", type)) {
|
||||||
|
i = new invariant(get_SSFE(type + strlen("median:")));
|
||||||
|
i->set_median();
|
||||||
|
} else {
|
||||||
|
i = new invariant(get_SSFE(type));
|
||||||
|
i->set_avg();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < render::render_count(); index++)
|
||||||
|
if (typeid(*render::render_num(index)) == typeid(incremental)
|
||||||
|
&& i->equals(((incremental *)render::render_num(index))->get_invariant())) {
|
||||||
|
delete i;
|
||||||
|
return (incremental *)render::render_num(index);
|
||||||
|
} else if (typeid(*i->ssfe()->get_scaled_filter()->get_filter()) == typeid(filter::zero)) {
|
||||||
|
return new zero(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fprintf(stderr, " new '%s'.\n", type);
|
||||||
|
|
||||||
|
return new incremental(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static render *get_combination(const char *ptype, const char *dtype) {
|
||||||
|
render *partial = get_invariant(ptype);
|
||||||
|
render *_default = get(dtype);
|
||||||
|
for (int index = 0; index < render::render_count(); index++)
|
||||||
|
if (typeid(*render::render_num(index)) == typeid(combine)
|
||||||
|
&& _default == ((combine *)render::render_num(index))->get_default()
|
||||||
|
&& partial == ((combine *)render::render_num(index))->get_partial()) {
|
||||||
|
return render::render_num(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fprintf(stderr, " new '%s,%s'.\n", ptype, dtype);
|
||||||
|
|
||||||
|
return new combine(_default, partial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static render *get(const char *orig_type) {
|
||||||
|
char *type = strdup(orig_type);
|
||||||
|
if (type == NULL)
|
||||||
|
nomem();
|
||||||
|
|
||||||
|
char *comma_index = (char *) type;
|
||||||
|
while (*comma_index != '\0'
|
||||||
|
&& *comma_index != ',')
|
||||||
|
comma_index++;
|
||||||
|
|
||||||
|
if (*comma_index == '\0') {
|
||||||
|
free(type);
|
||||||
|
return get_invariant(orig_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
*comma_index = '\0';
|
||||||
|
render *result = get_combination(type, comma_index + 1);
|
||||||
|
*comma_index = ',';
|
||||||
|
|
||||||
|
free(type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
114
d2/spixel.h
Normal file
114
d2/spixel.h
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __spixel_h__
|
||||||
|
#define __spixel_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure to describe a pixel to be used in storage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class spixel {
|
||||||
|
private:
|
||||||
|
ale_sreal x[3];
|
||||||
|
|
||||||
|
public:
|
||||||
|
spixel() {
|
||||||
|
x[0] = 0;
|
||||||
|
x[1] = 0;
|
||||||
|
x[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel(pixel p) {
|
||||||
|
x[0] = p[0];
|
||||||
|
x[1] = p[1];
|
||||||
|
x[2] = p[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel(ale_sreal x0, ale_sreal x1, ale_sreal x2) {
|
||||||
|
x[0] = x0;
|
||||||
|
x[1] = x1;
|
||||||
|
x[2] = x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator pixel() const {
|
||||||
|
pixel result;
|
||||||
|
|
||||||
|
result[0] = x[0];
|
||||||
|
result[1] = x[1];
|
||||||
|
result[2] = x[2];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ale_sreal &operator[](unsigned int i) const {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This may be expensive.
|
||||||
|
*/
|
||||||
|
assert (i < 3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_sreal &operator[](unsigned int i) {
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This may be expensive.
|
||||||
|
*/
|
||||||
|
assert (i < 3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ale_sreal min_norm() const {
|
||||||
|
ale_sreal m = x[0];
|
||||||
|
if (x[1] < m)
|
||||||
|
m = x[1];
|
||||||
|
if (x[2] < m)
|
||||||
|
m = x[2];
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel operator+=(pixel p) {
|
||||||
|
return spixel(x[0] += p[0], x[1] += p[1], x[2] += p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel operator*=(pixel p) {
|
||||||
|
return spixel(x[0] *= p[0], x[1] *= p[1], x[2] *= p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel operator*=(ale_real d) {
|
||||||
|
return spixel(x[0] *= d, x[1] *= d, x[2] *= d);
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel operator/=(pixel p) {
|
||||||
|
return spixel(x[0] /= p[0], x[1] /= p[1], x[2] /= p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
spixel operator/=(ale_real d) {
|
||||||
|
return spixel(x[0] /= d, x[1] /= d, x[2] /= d);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
28
d2/tfile.cc
Normal file
28
d2/tfile.cc
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tfile.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See tfile.h for details on these variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int tfile_input_version = 0;
|
||||||
|
int tfile_output_version = 0;
|
||||||
917
d2/tfile.h
Normal file
917
d2/tfile.h
Normal file
@@ -0,0 +1,917 @@
|
|||||||
|
// Copyright 2002, 2003, 2007 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||||
|
// <dhilvert@ugcs.caltech.edu>
|
||||||
|
|
||||||
|
/* This file is part of the Anti-Lamenessing Engine.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The Anti-Lamenessing Engine 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tfile.h: Read and write transformation data files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This version of ALE reads transformation data file versions 0, 1, 2, and 3,
|
||||||
|
* and writes version 2 and 3 transformation data files. Data file versions 1
|
||||||
|
* and higher are identified by a version command "V x", where x is the version
|
||||||
|
* number, prior to any transformation command. Data file version 0 is
|
||||||
|
* identified by having no version command.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __tfile_h__
|
||||||
|
#define __tfile_h__
|
||||||
|
|
||||||
|
#include "transformation.h"
|
||||||
|
|
||||||
|
#define TFILE_VERSION 3
|
||||||
|
#define TFILE_VERSION_MAX 3
|
||||||
|
|
||||||
|
extern int tfile_input_version;
|
||||||
|
extern int tfile_output_version;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure to describe a transformation data file to load data from.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct tload_t {
|
||||||
|
const char *filename;
|
||||||
|
FILE *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure to describe a transformation data file to write data to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct tsave_t {
|
||||||
|
const char *filename;
|
||||||
|
const char *target;
|
||||||
|
const char *orig;
|
||||||
|
pixel orig_apm;
|
||||||
|
FILE *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new tload_t transformation data file structure, used for
|
||||||
|
* reading data from transformation data files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline struct tload_t *tload_new(const char *filename) {
|
||||||
|
FILE *file = fopen (filename, "r");
|
||||||
|
struct tload_t *result = NULL;
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
fprintf(stderr, "tload: Error: could not open transformation data file '%s'.", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = (struct tload_t *)
|
||||||
|
malloc(sizeof(struct tload_t));
|
||||||
|
result->filename = filename;
|
||||||
|
result->file = file;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the first transformation from a transformation data file associated with
|
||||||
|
* transformation data file structure T, or return the default transformation
|
||||||
|
* if no transformation is available.
|
||||||
|
*
|
||||||
|
* T is a pointer to the tload_t transformation data file structure.
|
||||||
|
*
|
||||||
|
* IS_P is nonzero if a projective transformation is expected.
|
||||||
|
*
|
||||||
|
* DEFAULT_TRANSFORM is the default transformation result.
|
||||||
|
*
|
||||||
|
* IS_DEFAULT is used to signal a non-default transformation result.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline transformation tload_first(struct tload_t *t, int is_p,
|
||||||
|
transformation default_transform, int *is_default) {
|
||||||
|
|
||||||
|
transformation result = default_transform;
|
||||||
|
|
||||||
|
*is_default = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is no file, return the default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search through the initial part of the file to determine
|
||||||
|
* its version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip comments
|
||||||
|
*/
|
||||||
|
|
||||||
|
int first_character;
|
||||||
|
|
||||||
|
first_character = fgetc(t->file);
|
||||||
|
|
||||||
|
while (first_character == ' '
|
||||||
|
|| first_character == 0xa
|
||||||
|
|| first_character == 0xd
|
||||||
|
|| first_character == '\t'
|
||||||
|
|| first_character == '#') {
|
||||||
|
ungetc(first_character, t->file);
|
||||||
|
char line[1024];
|
||||||
|
fgets(line, 1024, t->file);
|
||||||
|
if (strlen(line) >= 1023) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ntrans-load: Error: line too long in input file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
first_character = fgetc(t->file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first_character != EOF)
|
||||||
|
ungetc(first_character, t->file);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for version 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (first_character != 'V')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must be version 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain version from version command string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char line[1024];
|
||||||
|
fgets(line, 1024, t->file);
|
||||||
|
if (strlen(line) >= 1023) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ntrans-load: Error: line too long in input file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = sscanf(line, "V %d", &tfile_input_version);
|
||||||
|
|
||||||
|
if (count < 1) {
|
||||||
|
fprintf(stderr, "Error in transformation "
|
||||||
|
"file version command.\n");
|
||||||
|
exit(1);
|
||||||
|
} else if (tfile_input_version > TFILE_VERSION_MAX) {
|
||||||
|
fprintf(stderr, "Unsupported transformation "
|
||||||
|
"file version %d\n",
|
||||||
|
tfile_input_version);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle versions lower than 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tfile_input_version < 3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Versions lower than 3 use the default transformation
|
||||||
|
* for the original frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read each line of the file until we find a transformation
|
||||||
|
* or EOF.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (!feof(t->file)) {
|
||||||
|
char line[1024];
|
||||||
|
|
||||||
|
fgets(line, 1024, t->file);
|
||||||
|
|
||||||
|
if (feof(t->file))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (strlen(line) >= 1023) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ntrans-load: Error: line too long in input file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (line[0]) {
|
||||||
|
case ' ':
|
||||||
|
case 0xa:
|
||||||
|
case 0xd:
|
||||||
|
case '\t':
|
||||||
|
case '#':
|
||||||
|
/* Comment or whitespace */
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
case 'd':
|
||||||
|
/* Default transformation */
|
||||||
|
return result;
|
||||||
|
case 'B':
|
||||||
|
case 'b':
|
||||||
|
if (tfile_input_version < 3) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Barrel distortion not supported "
|
||||||
|
"for version %d input files.\n"
|
||||||
|
"trans-load: Hint: Use version 3 "
|
||||||
|
"file syntax.\n", tfile_input_version);
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
unsigned int count;
|
||||||
|
unsigned int pos = 0, chars;
|
||||||
|
unsigned int bdc;
|
||||||
|
double dparameters[BARREL_DEGREE];
|
||||||
|
ale_pos parameters[BARREL_DEGREE];
|
||||||
|
|
||||||
|
count = sscanf(line, "B %u%n", &bdc, &chars);
|
||||||
|
pos += chars;
|
||||||
|
|
||||||
|
if (count < 1) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Malformed 'B' command.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bdc > result.bd_max()) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Barrel distortion degree %d "
|
||||||
|
"is too large. (Maximum is %d.)\n"
|
||||||
|
"trans-load: Hint: "
|
||||||
|
"Reduce degree or re-compile "
|
||||||
|
"with BD_DEGREE=%d\n", bdc, BARREL_DEGREE, bdc);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < bdc; d++) {
|
||||||
|
count = sscanf(line + pos, "%lf%n", &dparameters[d], &chars);
|
||||||
|
pos += chars;
|
||||||
|
|
||||||
|
if (count < 1) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Malformed 'B' command.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
parameters[d] = dparameters[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.bd_set(bdc, parameters);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
case 'p':
|
||||||
|
/* Projective transformation data */
|
||||||
|
*is_default = 0;
|
||||||
|
if (is_p == 0) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Projective data for euclidean "
|
||||||
|
"transformation.\n"
|
||||||
|
"trans-load: Hint: "
|
||||||
|
"Use command-line option --projective.\n");
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
double width, height, values[8];
|
||||||
|
int count, i;
|
||||||
|
point x[4];
|
||||||
|
|
||||||
|
count = sscanf(line + 1, " %lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &width, &height,
|
||||||
|
&values[0], &values[1], &values[2], &values[3],
|
||||||
|
&values[4], &values[5], &values[6], &values[7]);
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
for (int j = 1; j >= 0; j--)
|
||||||
|
x[i][j] = values[index++];
|
||||||
|
|
||||||
|
if (count < 10)
|
||||||
|
fprintf(stderr, "\ntrans-load: warning:"
|
||||||
|
"Missing args for 'P'\n");
|
||||||
|
|
||||||
|
for (i = 0; i < count - 2; i++) {
|
||||||
|
ale_pos factor = (i % 2)
|
||||||
|
? ((double) result.scaled_width() / width)
|
||||||
|
: ((double) result.scaled_height() / height);
|
||||||
|
|
||||||
|
x[i / 2][i % 2] *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.gpt_set(x);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
case 'e':
|
||||||
|
/* Euclidean transformation data */
|
||||||
|
*is_default = 0;
|
||||||
|
{
|
||||||
|
double width, height;
|
||||||
|
double values[3] = {0, 0, 0};
|
||||||
|
int count, i;
|
||||||
|
ale_pos eu[3];
|
||||||
|
|
||||||
|
count = sscanf(line + 1, " %lf%lf%lf%lf%lf",
|
||||||
|
&width, &height,
|
||||||
|
&values[0], &values[1], &values[2]);
|
||||||
|
|
||||||
|
eu[1] = values[0];
|
||||||
|
eu[0] = values[1];
|
||||||
|
eu[2] = values[2];
|
||||||
|
|
||||||
|
if (count < 5)
|
||||||
|
fprintf(stderr, "\ntrans-load: warning:"
|
||||||
|
"Missing args for 'E'\n");
|
||||||
|
|
||||||
|
for (i = 0; (i < count - 2) && (i < 2); i++) {
|
||||||
|
ale_pos factor = (i % 2)
|
||||||
|
? ((double) result.scaled_width() / width)
|
||||||
|
: ((double) result.scaled_height() / height);
|
||||||
|
|
||||||
|
eu[i] *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.eu_set(eu);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ntrans-load: Error in tload_first: unrecognized command '%s'\n",
|
||||||
|
line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EOF reached: return default transformation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the next transformation from a transformation data file associated with
|
||||||
|
* transformation data file structure T, or return the default transformation
|
||||||
|
* if no transformation is available.
|
||||||
|
*
|
||||||
|
* T is a pointer to the tload_t transformation data file structure.
|
||||||
|
*
|
||||||
|
* IS_P is nonzero if a projective transformation is expected.
|
||||||
|
*
|
||||||
|
* DEFAULT_TRANSFORM is the default transformation result.
|
||||||
|
*
|
||||||
|
* IS_DEFAULT is used to signal a non-default transformation result.
|
||||||
|
*
|
||||||
|
* IS_PRIMARY is used to differentiate primary and non-primary
|
||||||
|
* transformations
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline transformation tload_next(struct tload_t *t, int is_p,
|
||||||
|
transformation default_transform, int *is_default,
|
||||||
|
int is_primary) {
|
||||||
|
|
||||||
|
transformation result = default_transform;
|
||||||
|
|
||||||
|
*is_default = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read each line of the file until we find a transformation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (t && !feof(t->file)) {
|
||||||
|
|
||||||
|
char c = fgetc(t->file);
|
||||||
|
if (!feof(t->file) && c != EOF)
|
||||||
|
ungetc(c, t->file);
|
||||||
|
|
||||||
|
if (feof(t->file)
|
||||||
|
|| (!is_primary
|
||||||
|
&& c != EOF
|
||||||
|
&& (c == 'E'
|
||||||
|
|| c == 'e'
|
||||||
|
|| c == 'P'
|
||||||
|
|| c == 'p'
|
||||||
|
|| c == 'D'
|
||||||
|
|| c == 'd'
|
||||||
|
|| c == 'B'
|
||||||
|
|| c == 'b'))) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char line[1024];
|
||||||
|
|
||||||
|
fgets(line, 1024, t->file);
|
||||||
|
|
||||||
|
if (feof(t->file))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (strlen(line) >= 1023) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ntrans-load: warning: line too long in input file\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (line[0]) {
|
||||||
|
case ' ':
|
||||||
|
case 0xa:
|
||||||
|
case 0xd:
|
||||||
|
case '\t':
|
||||||
|
case '#':
|
||||||
|
/* Comment or whitespace */
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
case 'd':
|
||||||
|
/* Default transformation */
|
||||||
|
return result;
|
||||||
|
case 'B':
|
||||||
|
case 'b':
|
||||||
|
if (tfile_input_version < 3) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Barrel distortion not supported "
|
||||||
|
"for version %d input files.\n"
|
||||||
|
"trans-load: Hint: Use version 3 "
|
||||||
|
"file syntax.\n", tfile_input_version);
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
unsigned int count;
|
||||||
|
unsigned int pos = 0, chars;
|
||||||
|
unsigned int bdc;
|
||||||
|
ale_pos parameters[BARREL_DEGREE];
|
||||||
|
double dparameters[BARREL_DEGREE];
|
||||||
|
|
||||||
|
count = sscanf(line, "B %u%n", &bdc, &chars);
|
||||||
|
pos += chars;
|
||||||
|
|
||||||
|
if (count < 1) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Malformed 'B' command.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bdc > result.bd_max()) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Barrel distortion degree %d "
|
||||||
|
"is too large. (Maximum is %d.)\n"
|
||||||
|
"trans-load: Hint: "
|
||||||
|
"Reduce degree or re-compile "
|
||||||
|
"with BD_DEGREE=%d\n", bdc, BARREL_DEGREE, bdc);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < bdc; d++) {
|
||||||
|
count = sscanf(line + pos, "%lf%n", &dparameters[d], &chars);
|
||||||
|
pos += chars;
|
||||||
|
|
||||||
|
if (count < 1) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Malformed 'B' command.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
parameters[d] = dparameters[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.bd_set(bdc, parameters);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Q':
|
||||||
|
case 'q':
|
||||||
|
if (is_primary)
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
case 'p':
|
||||||
|
/* Projective transformation data */
|
||||||
|
if (is_p == 0) {
|
||||||
|
fprintf(stderr, "\ntrans-load: Error: "
|
||||||
|
"Projective data for euclidean "
|
||||||
|
"transformation.\n"
|
||||||
|
"trans-load: Hint: "
|
||||||
|
"Use command-line option --projective.\n");
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
double width, height, values[8];
|
||||||
|
int count, i;
|
||||||
|
point x[4];
|
||||||
|
transformation::multi_coordinate mc1, mc2;
|
||||||
|
|
||||||
|
count = sscanf(line + 1, " %lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%d%d%d", &width, &height,
|
||||||
|
&values[0], &values[1], &values[2], &values[3],
|
||||||
|
&values[4], &values[5], &values[6], &values[7],
|
||||||
|
&mc1.degree, &mc1.x, &mc1.y);
|
||||||
|
|
||||||
|
if (count == 13) {
|
||||||
|
mc2 = default_transform.get_current_coordinate();
|
||||||
|
|
||||||
|
if (mc1.degree < mc2.degree
|
||||||
|
|| mc1.degree == mc2.degree && mc1.y < mc2.y
|
||||||
|
|| mc1.degree == mc2.degree && mc1.y == mc2.y && mc1.x < mc2.x)
|
||||||
|
break;
|
||||||
|
if (mc1.degree != mc2.degree
|
||||||
|
|| mc1.x != mc2.x
|
||||||
|
|| mc1.y != mc2.y) {
|
||||||
|
if (!result.exists(mc1))
|
||||||
|
break;
|
||||||
|
result.set_current_index(result.get_index(mc1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
for (int j = 1; j >= 0; j--)
|
||||||
|
x[i][j] = values[index++];
|
||||||
|
|
||||||
|
if (count < 10)
|
||||||
|
fprintf(stderr, "\ntrans-load: warning:"
|
||||||
|
"Missing args for 'P'\n");
|
||||||
|
|
||||||
|
for (i = 0; i < count - 2; i++) {
|
||||||
|
ale_pos factor = (i % 2)
|
||||||
|
? ((double) result.scaled_width() / width)
|
||||||
|
: ((double) result.scaled_height() / height);
|
||||||
|
|
||||||
|
x[i / 2][i % 2] *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tfile_input_version < 1) {
|
||||||
|
/*
|
||||||
|
* Accommodate older versions
|
||||||
|
* of tfile.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
ale_pos y = x[i][0];
|
||||||
|
x[i][0] = x[i][1];
|
||||||
|
x[i][1] = y;
|
||||||
|
}
|
||||||
|
result.gpt_v0_set(x);
|
||||||
|
} else {
|
||||||
|
result.gpt_set(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
*is_default = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
case 'f':
|
||||||
|
if (is_primary)
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
case 'e':
|
||||||
|
/* Euclidean transformation data */
|
||||||
|
{
|
||||||
|
double width, height;
|
||||||
|
double values[3] = {0, 0, 0};
|
||||||
|
int count, i;
|
||||||
|
ale_pos eu[3];
|
||||||
|
transformation::multi_coordinate mc1, mc2;
|
||||||
|
|
||||||
|
count = sscanf(line + 1, " %lf%lf%lf%lf%lf%d%d%d",
|
||||||
|
&width, &height,
|
||||||
|
&values[0], &values[1], &values[2],
|
||||||
|
&mc1.degree, &mc1.x, &mc1.y);
|
||||||
|
|
||||||
|
if (count == 8) {
|
||||||
|
mc2 = default_transform.get_current_coordinate();
|
||||||
|
|
||||||
|
if (mc1.degree < mc2.degree
|
||||||
|
|| mc1.degree == mc2.degree && mc1.y < mc2.y
|
||||||
|
|| mc1.degree == mc2.degree && mc1.y == mc2.y && mc1.x < mc2.x)
|
||||||
|
break;
|
||||||
|
if (mc1.degree != mc2.degree
|
||||||
|
|| mc1.x != mc2.x
|
||||||
|
|| mc1.y != mc2.y) {
|
||||||
|
if (!result.exists(mc1))
|
||||||
|
break;
|
||||||
|
result.set_current_index(result.get_index(mc1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eu[1] = values[0];
|
||||||
|
eu[0] = values[1];
|
||||||
|
eu[2] = values[2];
|
||||||
|
|
||||||
|
if (tfile_input_version < 2) {
|
||||||
|
ale_pos t = eu[0];
|
||||||
|
eu[0] = eu[1];
|
||||||
|
eu[1] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (count < 5)
|
||||||
|
fprintf(stderr, "\ntrans-load: warning:"
|
||||||
|
"Missing args for 'E'\n");
|
||||||
|
|
||||||
|
for (i = 0; (i < count - 2) && (i < 2); i++) {
|
||||||
|
ale_pos factor = (i % 2)
|
||||||
|
? ((double) result.scaled_width() / width)
|
||||||
|
: ((double) result.scaled_height() / height);
|
||||||
|
|
||||||
|
eu[i] *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tfile_input_version < 1) {
|
||||||
|
result.eu_v0_set(eu);
|
||||||
|
} else {
|
||||||
|
result.eu_set(eu);
|
||||||
|
}
|
||||||
|
|
||||||
|
*is_default = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ntrans-load: Error in tload_next: unrecognized command '%s'\n",
|
||||||
|
line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new tsave_t transformation data file structure, used for
|
||||||
|
* writing data to transformation data files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline struct tsave_t *tsave_new(const char *filename) {
|
||||||
|
FILE *file = fopen (filename, "w");
|
||||||
|
struct tsave_t *result = NULL;
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
fprintf(stderr, "tsave: Error: could not open transformation data file '%s'.", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = (struct tsave_t *)
|
||||||
|
malloc(sizeof(struct tsave_t));
|
||||||
|
result->filename = filename;
|
||||||
|
result->file = file;
|
||||||
|
result->orig = "unknown";
|
||||||
|
result->target = "unknown";
|
||||||
|
|
||||||
|
fprintf(file, "# created by ALE transformation file handler version %d\n",
|
||||||
|
TFILE_VERSION);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the first transformation to a transformation data file associated with
|
||||||
|
* transformation data file structure T, or do nothing if T is NULL. This
|
||||||
|
* function also establishes the output file version.
|
||||||
|
*
|
||||||
|
* OFFSET is the transformation to be saved.
|
||||||
|
*
|
||||||
|
* IS_PROJECTIVE indicates whether to write a projective transformation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tsave_first(struct tsave_t *t, transformation offset, int is_projective) {
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
t->file = fopen(t->filename, "a");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the output version to use. We use version 3 output syntax only when
|
||||||
|
* necessary. This comprises two cases:
|
||||||
|
*
|
||||||
|
* (i) an input file is used, and this file uses version 3 syntax.
|
||||||
|
* (ii) non-degenerate barrel distortion correction is selected.
|
||||||
|
*
|
||||||
|
* (i) can be directly examined. When (i) does not hold, (ii) can be
|
||||||
|
* inferred from offset.bd_count(), since this value should be constant
|
||||||
|
* when (i) does not hold. XXX: This logic should be reviewed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tfile_input_version == 3 || offset.bd_count() > 0)
|
||||||
|
tfile_output_version = 3;
|
||||||
|
else
|
||||||
|
tfile_output_version = 2;
|
||||||
|
|
||||||
|
|
||||||
|
fprintf(t->file, "# producing transformation file syntax version %d\n", tfile_output_version);
|
||||||
|
fprintf(t->file, "V %d\n", tfile_output_version);
|
||||||
|
|
||||||
|
fprintf(t->file, "# Comment: Target output file is %s\n", t->target);
|
||||||
|
fprintf(t->file, "# Comment: Original frame is %s\n", t->orig);
|
||||||
|
fprintf(t->file, "# Comment: Avg magnitude [r=%f g=%f b=%f]\n", (double) t->orig_apm[0], (double) t->orig_apm[1], (double) t->orig_apm[2]);
|
||||||
|
|
||||||
|
if (tfile_output_version < 3) {
|
||||||
|
fclose(t->file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset.bd_count() > 0) {
|
||||||
|
assert (tfile_output_version >= 3);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
fprintf(t->file, "B ");
|
||||||
|
fprintf(t->file, "%u ", offset.bd_count());
|
||||||
|
for (i = 0; i < offset.bd_count(); i++)
|
||||||
|
fprintf(t->file, "%f ", (double) offset.bd_get(i));
|
||||||
|
fprintf(t->file, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (is_projective) {
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
fprintf(t->file, "P ");
|
||||||
|
fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height());
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
for (j = 1; j >= 0; j--)
|
||||||
|
fprintf(t->file, "%f ", (double) offset.gpt_get(i, j));
|
||||||
|
} else {
|
||||||
|
fprintf(t->file, "E ");
|
||||||
|
fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height());
|
||||||
|
fprintf(t->file, "%f ", (double) offset.eu_get(1));
|
||||||
|
fprintf(t->file, "%f ", (double) offset.eu_get(0));
|
||||||
|
fprintf(t->file, "%f ", (double) offset.eu_get(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(t->file, "\n");
|
||||||
|
|
||||||
|
fclose(t->file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the next transformation to a transformation data file associated with
|
||||||
|
* transformation data file structure T, or do nothing if T is NULL.
|
||||||
|
*
|
||||||
|
* OFFSET is the transformation to be saved.
|
||||||
|
*
|
||||||
|
* IS_PROJECTIVE indicates whether to write a projective transformation.
|
||||||
|
*
|
||||||
|
* IS_PRIMARY indicates whether to write a primary transformation
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tsave_next(struct tsave_t *t, transformation offset, int is_projective,
|
||||||
|
int is_primary) {
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
t->file = fopen(t->filename, "a");
|
||||||
|
|
||||||
|
if (is_primary && offset.bd_count() > 0) {
|
||||||
|
assert (tfile_output_version >= 3);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
fprintf(t->file, "B ");
|
||||||
|
fprintf(t->file, "%u ", offset.bd_count());
|
||||||
|
for (i = 0; i < offset.bd_count(); i++)
|
||||||
|
fprintf(t->file, "%f ", (double) offset.bd_get(i));
|
||||||
|
fprintf(t->file, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_projective) {
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
fprintf(t->file, is_primary ? "P " : "Q ");
|
||||||
|
fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height());
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
for (j = 1; j >= 0; j--)
|
||||||
|
fprintf(t->file, "%f ", (double) offset.gpt_get(i, j));
|
||||||
|
} else {
|
||||||
|
fprintf(t->file, is_primary ? "E " : "F ");
|
||||||
|
fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height());
|
||||||
|
fprintf(t->file, "%f ", (double) offset.eu_get(1));
|
||||||
|
fprintf(t->file, "%f ", (double) offset.eu_get(0));
|
||||||
|
fprintf(t->file, "%f ", (double) offset.eu_get(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_primary) {
|
||||||
|
transformation::multi_coordinate mc = offset.get_current_coordinate();
|
||||||
|
fprintf(t->file, "%d %d %d ", mc.degree, mc.x, mc.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(t->file, "\n");
|
||||||
|
|
||||||
|
fclose(t->file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write information to a transformation file indicating the target output
|
||||||
|
* file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tsave_target(struct tsave_t *t, const char *filename) {
|
||||||
|
if (t == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
t->target = filename;
|
||||||
|
if (t != NULL) {
|
||||||
|
t->file = fopen(t->filename, "a");
|
||||||
|
|
||||||
|
|
||||||
|
fclose(t->file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write information to a transformation data file indicating the filename
|
||||||
|
* of the original frame (i.e. the first frame in the sequence of input
|
||||||
|
* frames).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tsave_orig(struct tsave_t *t, const char *filename, pixel apm) {
|
||||||
|
if (t == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
t->orig = filename;
|
||||||
|
t->orig_apm = apm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write information to a transformation data file indicating the filename
|
||||||
|
* of a supplemental frame (i.e. a frame in the sequence of input frames
|
||||||
|
* that is not the first frame).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tsave_info(struct tsave_t *t, const char *filename) {
|
||||||
|
if (t != NULL) {
|
||||||
|
t->file = fopen(t->filename, "a");
|
||||||
|
|
||||||
|
fprintf(t->file, "# Comment: Supplemental frame %s\n", filename);
|
||||||
|
|
||||||
|
fclose(t->file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write information to a transformation data file indicating the tonal
|
||||||
|
* registration multiplier.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tsave_trm(struct tsave_t *t, ale_real r, ale_real g, ale_real b) {
|
||||||
|
if (t != NULL) {
|
||||||
|
t->file = fopen(t->filename, "a");
|
||||||
|
|
||||||
|
fprintf(t->file, "# Comment: Exposure [r=%f g=%f b=%f]\n", (double) r, (double) g, (double) b);
|
||||||
|
|
||||||
|
fclose(t->file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write information to a transformation data file indicating the average
|
||||||
|
* pixel magnitude.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tsave_apm(struct tsave_t *t, ale_real r, ale_real g, ale_real b) {
|
||||||
|
if (t != NULL) {
|
||||||
|
t->file = fopen(t->filename, "a");
|
||||||
|
|
||||||
|
fprintf(t->file, "# Comment: Avg magnitude [r=%f g=%f b=%f]\n", (double) r, (double) g, (double) b);
|
||||||
|
|
||||||
|
fclose(t->file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy a tload_t transformation data file structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tload_delete(struct tload_t *victim) {
|
||||||
|
if (victim)
|
||||||
|
fclose(victim->file);
|
||||||
|
free(victim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy a tsave_t transformation data file structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void tsave_delete(struct tsave_t *victim) {
|
||||||
|
free(victim);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user