initial commit

This commit is contained in:
Mauro Torrez 2022-07-30 14:46:04 -03:00
commit 47650131de
312 changed files with 212465 additions and 0 deletions

61
AUTHORS Normal file
View 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
View 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
View 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>.

1339
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

291
INSTALL Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

439
NEWS Normal file
View 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
View 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
View 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.

1
VERSION Normal file
View File

@ -0,0 +1 @@
0.9.0.3

1348
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

242
ale Executable file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

76
ale_math.h Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

26288
autom4te.cache/output.1 Normal file

File diff suppressed because it is too large Load Diff

26288
autom4te.cache/output.2 Normal file

File diff suppressed because it is too large Load Diff

647
autom4te.cache/requests Normal file
View 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

File diff suppressed because it is too large Load Diff

1473
autom4te.cache/traces.1 Normal file

File diff suppressed because it is too large Load Diff

4393
autom4te.cache/traces.2 Normal file

File diff suppressed because it is too large Load Diff

139
bootstrap Executable file
View 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'."

View 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:

View 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.

View 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:

View 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
View 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

File diff suppressed because it is too large Load Diff

308
config.h.in Normal file
View 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

File diff suppressed because it is too large Load Diff

26288
configure vendored Executable file

File diff suppressed because it is too large Load Diff

375
configure.in Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

43
d2/exclusion.h Normal file
View 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
View 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
View 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

View 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

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

420
d2/image_ale_real.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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", &param) != 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", &param) != 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", &param) != 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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", &param) != 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", &param) != 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", &param) != 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", &param) != 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", &param, &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
View 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
View 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
View 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