mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-29 01:25:38 +00:00
Squashed 'external/CImg/' content from commit c0becdf8
git-subtree-dir: external/CImg git-subtree-split: c0becdf881b0f3e2445975cac01c2422170d1fd9
This commit is contained in:
commit
3b12410b91
20
.travis.yml
Normal file
20
.travis.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
language: cpp
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
script:
|
||||||
|
- cd examples
|
||||||
|
- make CXX='g++-4.8' travis
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- gcc-4.8
|
||||||
|
- g++-4.8
|
||||||
|
- clang
|
||||||
|
- libpng12-dev
|
||||||
|
- libjpeg-dev
|
||||||
|
- libmagick++-dev
|
||||||
|
- libgraphicsmagick++1-dev
|
||||||
|
- libfftw3-dev
|
||||||
|
- zlib1g-dev
|
508
Licence_CeCILL-C_V1-en.txt
Normal file
508
Licence_CeCILL-C_V1-en.txt
Normal file
|
@ -0,0 +1,508 @@
|
||||||
|
|
||||||
|
CeCILL-C FREE SOFTWARE LICENSE AGREEMENT
|
||||||
|
|
||||||
|
|
||||||
|
Notice
|
||||||
|
|
||||||
|
This Agreement is a Free Software license agreement that is the result
|
||||||
|
of discussions between its authors in order to ensure compliance with
|
||||||
|
the two main principles guiding its drafting:
|
||||||
|
|
||||||
|
* firstly, compliance with the principles governing the distribution
|
||||||
|
of Free Software: access to source code, broad rights granted to
|
||||||
|
users,
|
||||||
|
* secondly, the election of a governing law, French law, with which
|
||||||
|
it is conformant, both as regards the law of torts and
|
||||||
|
intellectual property law, and the protection that it offers to
|
||||||
|
both authors and holders of the economic rights over software.
|
||||||
|
|
||||||
|
The authors of the CeCILL-C (for Ce[a] C[nrs] I[nria] L[logiciel] L[ibre])
|
||||||
|
license are:
|
||||||
|
|
||||||
|
Commissariat à l'Energie Atomique - CEA, a public scientific, technical
|
||||||
|
and industrial research establishment, having its principal place of
|
||||||
|
business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France.
|
||||||
|
|
||||||
|
Centre National de la Recherche Scientifique - CNRS, a public scientific
|
||||||
|
and technological establishment, having its principal place of business
|
||||||
|
at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
|
||||||
|
|
||||||
|
Institut National de Recherche en Informatique et en Automatique -
|
||||||
|
INRIA, a public scientific and technological establishment, having its
|
||||||
|
principal place of business at Domaine de Voluceau, Rocquencourt, BP
|
||||||
|
105, 78153 Le Chesnay cedex, France.
|
||||||
|
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The purpose of this Free Software license agreement is to grant users the
|
||||||
|
right to modify and re-use the software governed by this license.
|
||||||
|
|
||||||
|
The exercising of this right is conditional on the obligation to make
|
||||||
|
available to the community the modifications made to the source code of the
|
||||||
|
software so as to contribute to its evolution.
|
||||||
|
|
||||||
|
In consideration of access to the source code and the rights to copy,
|
||||||
|
modify and redistribute granted by the license, users are provided only
|
||||||
|
with a limited warranty and the software's author, the holder of the
|
||||||
|
economic rights, and the successive licensors only have limited liability.
|
||||||
|
|
||||||
|
In this respect, the risks associated with loading, using, modifying
|
||||||
|
and/or developing or reproducing the software by the user are brought to
|
||||||
|
the user's attention, given its Free Software status, which may make it
|
||||||
|
complicated to use, with the result that its use is reserved for
|
||||||
|
developers and experienced professionals having in-depth computer
|
||||||
|
knowledge. Users are therefore encouraged to load and test the suitability
|
||||||
|
of the software as regards their requirements in conditions enabling the
|
||||||
|
security of their systems and/or data to be ensured and, more generally, to
|
||||||
|
use and operate it in the same conditions of security. This Agreement may be
|
||||||
|
freely reproduced and published, provided it is not altered, and that no
|
||||||
|
provisions are either added or removed herefrom.
|
||||||
|
|
||||||
|
This Agreement may apply to any or all software for which the holder of
|
||||||
|
the economic rights decides to submit the use thereof to its provisions.
|
||||||
|
|
||||||
|
|
||||||
|
Article 1 - DEFINITIONS
|
||||||
|
|
||||||
|
For the purpose of this Agreement, when the following expressions
|
||||||
|
commence with a capital letter, they shall have the following meaning:
|
||||||
|
|
||||||
|
Agreement: means this license agreement, and its possible subsequent
|
||||||
|
versions and annexes.
|
||||||
|
|
||||||
|
Software: means the software in its Object Code and/or Source Code form
|
||||||
|
and, where applicable, its documentation, "as is" when the Licensee
|
||||||
|
accepts the Agreement.
|
||||||
|
|
||||||
|
Initial Software: means the Software in its Source Code and possibly its
|
||||||
|
Object Code form and, where applicable, its documentation, "as is" when
|
||||||
|
it is first distributed under the terms and conditions of the Agreement.
|
||||||
|
|
||||||
|
Modified Software: means the Software modified by at least one Integrated
|
||||||
|
Contribution.
|
||||||
|
|
||||||
|
Source Code: means all the Software's instructions and program lines to
|
||||||
|
which access is required so as to modify the Software.
|
||||||
|
|
||||||
|
Object Code: means the binary files originating from the compilation of
|
||||||
|
the Source Code.
|
||||||
|
|
||||||
|
Holder: means the holder(s) of the economic rights over the Initial
|
||||||
|
Software.
|
||||||
|
|
||||||
|
Licensee: means the Software user(s) having accepted the Agreement.
|
||||||
|
|
||||||
|
Contributor: means a Licensee having made at least one Integrated
|
||||||
|
Contribution.
|
||||||
|
|
||||||
|
Licensor: means the Holder, or any other individual or legal entity, who
|
||||||
|
distributes the Software under the Agreement.
|
||||||
|
|
||||||
|
Integrated Contribution: means any or all modifications, corrections,
|
||||||
|
translations, adaptations and/or new functions integrated into the Source
|
||||||
|
Code by any or all Contributors.
|
||||||
|
|
||||||
|
Related Module: means a set of sources files including their documentation
|
||||||
|
that, without modification to the Source Code, enables supplementary
|
||||||
|
functions or services in addition to those offered by the Software.
|
||||||
|
|
||||||
|
Derivative Software: means any combination of the Software, modified or not,
|
||||||
|
and of a Related Module.
|
||||||
|
|
||||||
|
Parties: mean both the Licensee and the Licensor.
|
||||||
|
|
||||||
|
These expressions may be used both in singular and plural form.
|
||||||
|
|
||||||
|
|
||||||
|
Article 2 - PURPOSE
|
||||||
|
|
||||||
|
The purpose of the Agreement is the grant by the Licensor to the
|
||||||
|
Licensee of a non-exclusive, transferable and worldwide license for the
|
||||||
|
Software as set forth in Article 5 hereinafter for the whole term of the
|
||||||
|
protection granted by the rights over said Software.
|
||||||
|
|
||||||
|
|
||||||
|
Article 3 - ACCEPTANCE
|
||||||
|
|
||||||
|
3.1 The Licensee shall be deemed as having accepted the terms and
|
||||||
|
conditions of this Agreement upon the occurrence of the first of the
|
||||||
|
following events:
|
||||||
|
|
||||||
|
* (i) loading the Software by any or all means, notably, by
|
||||||
|
downloading from a remote server, or by loading from a physical
|
||||||
|
medium;
|
||||||
|
* (ii) the first time the Licensee exercises any of the rights
|
||||||
|
granted hereunder.
|
||||||
|
|
||||||
|
3.2 One copy of the Agreement, containing a notice relating to the
|
||||||
|
characteristics of the Software, to the limited warranty, and to the
|
||||||
|
fact that its use is restricted to experienced users has been provided
|
||||||
|
to the Licensee prior to its acceptance as set forth in Article 3.1
|
||||||
|
hereinabove, and the Licensee hereby acknowledges that it has read and
|
||||||
|
understood it.
|
||||||
|
|
||||||
|
|
||||||
|
Article 4 - EFFECTIVE DATE AND TERM
|
||||||
|
|
||||||
|
|
||||||
|
4.1 EFFECTIVE DATE
|
||||||
|
|
||||||
|
The Agreement shall become effective on the date when it is accepted by
|
||||||
|
the Licensee as set forth in Article 3.1.
|
||||||
|
|
||||||
|
|
||||||
|
4.2 TERM
|
||||||
|
|
||||||
|
The Agreement shall remain in force for the entire legal term of
|
||||||
|
protection of the economic rights over the Software.
|
||||||
|
|
||||||
|
|
||||||
|
Article 5 - SCOPE OF RIGHTS GRANTED
|
||||||
|
|
||||||
|
The Licensor hereby grants to the Licensee, who accepts, the following
|
||||||
|
rights over the Software for any or all use, and for the term of the
|
||||||
|
Agreement, on the basis of the terms and conditions set forth hereinafter.
|
||||||
|
|
||||||
|
Besides, if the Licensor owns or comes to own one or more patents
|
||||||
|
protecting all or part of the functions of the Software or of its
|
||||||
|
components, the Licensor undertakes not to enforce the rights granted by
|
||||||
|
these patents against successive Licensees using, exploiting or
|
||||||
|
modifying the Software. If these patents are transferred, the Licensor
|
||||||
|
undertakes to have the transferees subscribe to the obligations set
|
||||||
|
forth in this paragraph.
|
||||||
|
|
||||||
|
|
||||||
|
5.1 RIGHT OF USE
|
||||||
|
|
||||||
|
The Licensee is authorized to use the Software, without any limitation
|
||||||
|
as to its fields of application, with it being hereinafter specified
|
||||||
|
that this comprises:
|
||||||
|
|
||||||
|
1. permanent or temporary reproduction of all or part of the Software
|
||||||
|
by any or all means and in any or all form.
|
||||||
|
2. loading, displaying, running, or storing the Software on any or
|
||||||
|
all medium.
|
||||||
|
3. entitlement to observe, study or test its operation so as to
|
||||||
|
determine the ideas and principles behind any or all constituent
|
||||||
|
elements of said Software. This shall apply when the Licensee
|
||||||
|
carries out any or all loading, displaying, running, transmission
|
||||||
|
or storage operation as regards the Software, that it is entitled
|
||||||
|
to carry out hereunder.
|
||||||
|
|
||||||
|
|
||||||
|
5.2 RIGHT OF MODIFICATION
|
||||||
|
|
||||||
|
The right of modification includes the right to translate, adapt, arrange,
|
||||||
|
or make any or all modifications to the Software, and the right to
|
||||||
|
reproduce the resulting Software. It includes, in particular, the right
|
||||||
|
to create a Derivative Software.
|
||||||
|
|
||||||
|
The Licensee is authorized to make any or all modification to the
|
||||||
|
Software provided that it includes an explicit notice that it is the
|
||||||
|
author of said modification and indicates the date of the creation thereof.
|
||||||
|
|
||||||
|
|
||||||
|
5.3 RIGHT OF DISTRIBUTION
|
||||||
|
|
||||||
|
In particular, the right of distribution includes the right to publish,
|
||||||
|
transmit and communicate the Software to the general public on any or
|
||||||
|
all medium, and by any or all means, and the right to market, either in
|
||||||
|
consideration of a fee, or free of charge, one or more copies of the
|
||||||
|
Software by any means.
|
||||||
|
|
||||||
|
The Licensee is further authorized to distribute copies of the modified
|
||||||
|
or unmodified Software to third parties according to the terms and
|
||||||
|
conditions set forth hereinafter.
|
||||||
|
|
||||||
|
|
||||||
|
5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
|
||||||
|
|
||||||
|
The Licensee is authorized to distribute true copies of the Software in
|
||||||
|
Source Code or Object Code form, provided that said distribution
|
||||||
|
complies with all the provisions of the Agreement and is accompanied by:
|
||||||
|
|
||||||
|
1. a copy of the Agreement,
|
||||||
|
|
||||||
|
2. a notice relating to the limitation of both the Licensor's
|
||||||
|
warranty and liability as set forth in Articles 8 and 9,
|
||||||
|
|
||||||
|
and that, in the event that only the Object Code of the Software is
|
||||||
|
redistributed, the Licensee allows effective access to the full Source Code
|
||||||
|
of the Software at a minimum during the entire period of its distribution
|
||||||
|
of the Software, it being understood that the additional cost of acquiring
|
||||||
|
the Source Code shall not exceed the cost of transferring the data.
|
||||||
|
|
||||||
|
|
||||||
|
5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
|
||||||
|
|
||||||
|
When the Licensee makes an Integrated Contribution to the Software, the terms
|
||||||
|
and conditions for the distribution of the resulting Modified Software become
|
||||||
|
subject to all the provisions of this Agreement.
|
||||||
|
|
||||||
|
The Licensee is authorized to distribute the Modified Software, in source
|
||||||
|
code or object code form, provided that said distribution complies with all
|
||||||
|
the provisions of the Agreement and is accompanied by:
|
||||||
|
|
||||||
|
1. a copy of the Agreement,
|
||||||
|
2. a notice relating to the limitation of both the Licensor's warranty and
|
||||||
|
liability as set forth in Articles 8 and 9,
|
||||||
|
|
||||||
|
and that, in the event that only the object code of the Modified Software is
|
||||||
|
redistributed, the Licensee allows effective access to the full source code
|
||||||
|
of the Modified Software at a minimum during the entire period of its
|
||||||
|
distribution of the Modified Software, it being understood that the
|
||||||
|
additional cost of acquiring the source code shall not exceed the cost of
|
||||||
|
transferring the data.
|
||||||
|
|
||||||
|
5.3.3 DISTRIBUTION OF DERIVATIVE SOFTWARE
|
||||||
|
|
||||||
|
When the Licensee creates Derivative Software, this Derivative Software may
|
||||||
|
be distributed under a license agreement other than this Agreement, subject
|
||||||
|
to compliance with the requirement to include a notice concerning the rights
|
||||||
|
over the Software as defined in Article 6.4. In the event the creation of the
|
||||||
|
Derivative Software required modification of the Source Code, the Licensee
|
||||||
|
undertakes that:
|
||||||
|
|
||||||
|
1. the resulting Modified Software will be governed by this Agreement,
|
||||||
|
2. the Integrated Contributions in the resulting Modified Software will be
|
||||||
|
clearly identified and documented,
|
||||||
|
3. the Licensee will allow effective access to the source code of the
|
||||||
|
Modified Software, at a minimum during the entire period of
|
||||||
|
distribution of the Derivative Software, such that such modifications
|
||||||
|
may be carried over in a subsequent version of the Software; it being
|
||||||
|
understood that the additional cost of purchasing the source code of
|
||||||
|
the Modified Software shall not exceed the cost of transferring the
|
||||||
|
data.
|
||||||
|
|
||||||
|
|
||||||
|
5.3.4 COMPATIBILITY WITH THE CeCILL LICENSE
|
||||||
|
|
||||||
|
When a Modified Software contains an Integrated Contribution subject to the
|
||||||
|
CeCill license agreement, or when a Derivative Software contains a Related
|
||||||
|
Module subject to the CeCill license agreement, the provisions set forth in
|
||||||
|
the third item of Article 6.4 are optional.
|
||||||
|
|
||||||
|
|
||||||
|
Article 6 - INTELLECTUAL PROPERTY
|
||||||
|
|
||||||
|
|
||||||
|
6.1 OVER THE INITIAL SOFTWARE
|
||||||
|
|
||||||
|
The Holder owns the economic rights over the Initial Software. Any or
|
||||||
|
all use of the Initial Software is subject to compliance with the terms
|
||||||
|
and conditions under which the Holder has elected to distribute its work
|
||||||
|
and no one shall be entitled to modify the terms and conditions for the
|
||||||
|
distribution of said Initial Software.
|
||||||
|
|
||||||
|
The Holder undertakes that the Initial Software will remain ruled at
|
||||||
|
least by the current license, for the duration set forth in Article 4.2.
|
||||||
|
|
||||||
|
|
||||||
|
6.2 OVER THE INTEGRATED CONTRIBUTIONS
|
||||||
|
|
||||||
|
A Licensee who develops an Integrated Contribution is the owner of the
|
||||||
|
intellectual property rights over this Contribution as defined by
|
||||||
|
applicable law.
|
||||||
|
|
||||||
|
|
||||||
|
6.3 OVER THE RELATED MODULES
|
||||||
|
|
||||||
|
A Licensee who develops an Related Module is the owner of the
|
||||||
|
intellectual property rights over this Related Module as defined by
|
||||||
|
applicable law and is free to choose the type of agreement that shall
|
||||||
|
govern its distribution under the conditions defined in Article 5.3.3.
|
||||||
|
|
||||||
|
|
||||||
|
6.4 NOTICE OF RIGHTS
|
||||||
|
|
||||||
|
The Licensee expressly undertakes:
|
||||||
|
|
||||||
|
1. not to remove, or modify, in any manner, the intellectual property
|
||||||
|
notices attached to the Software;
|
||||||
|
2. to reproduce said notices, in an identical manner, in the copies
|
||||||
|
of the Software modified or not;
|
||||||
|
3. to ensure that use of the Software, its intellectual property
|
||||||
|
notices and the fact that it is governed by the Agreement is
|
||||||
|
indicated in a text that is easily accessible, specifically from
|
||||||
|
the interface of any Derivative Software.
|
||||||
|
|
||||||
|
The Licensee undertakes not to directly or indirectly infringe the
|
||||||
|
intellectual property rights of the Holder and/or Contributors on the
|
||||||
|
Software and to take, where applicable, vis-à-vis its staff, any and all
|
||||||
|
measures required to ensure respect of said intellectual property rights
|
||||||
|
of the Holder and/or Contributors.
|
||||||
|
|
||||||
|
|
||||||
|
Article 7 - RELATED SERVICES
|
||||||
|
|
||||||
|
7.1 Under no circumstances shall the Agreement oblige the Licensor to
|
||||||
|
provide technical assistance or maintenance services for the Software.
|
||||||
|
|
||||||
|
However, the Licensor is entitled to offer this type of services. The
|
||||||
|
terms and conditions of such technical assistance, and/or such
|
||||||
|
maintenance, shall be set forth in a separate instrument. Only the
|
||||||
|
Licensor offering said maintenance and/or technical assistance services
|
||||||
|
shall incur liability therefor.
|
||||||
|
|
||||||
|
7.2 Similarly, any Licensor is entitled to offer to its licensees, under
|
||||||
|
its sole responsibility, a warranty, that shall only be binding upon
|
||||||
|
itself, for the redistribution of the Software and/or the Modified
|
||||||
|
Software, under terms and conditions that it is free to decide. Said
|
||||||
|
warranty, and the financial terms and conditions of its application,
|
||||||
|
shall be subject of a separate instrument executed between the Licensor
|
||||||
|
and the Licensee.
|
||||||
|
|
||||||
|
|
||||||
|
Article 8 - LIABILITY
|
||||||
|
|
||||||
|
8.1 Subject to the provisions of Article 8.2, the Licensee shall be
|
||||||
|
entitled to claim compensation for any direct loss it may have suffered
|
||||||
|
from the Software as a result of a fault on the part of the relevant
|
||||||
|
Licensor, subject to providing evidence thereof.
|
||||||
|
|
||||||
|
8.2 The Licensor's liability is limited to the commitments made under
|
||||||
|
this Agreement and shall not be incurred as a result of in particular:
|
||||||
|
(i) loss due the Licensee's total or partial failure to fulfill its
|
||||||
|
obligations, (ii) direct or consequential loss that is suffered by the
|
||||||
|
Licensee due to the use or performance of the Software, and (iii) more
|
||||||
|
generally, any consequential loss. In particular the Parties expressly
|
||||||
|
agree that any or all pecuniary or business loss (i.e. loss of data,
|
||||||
|
loss of profits, operating loss, loss of customers or orders,
|
||||||
|
opportunity cost, any disturbance to business activities) or any or all
|
||||||
|
legal proceedings instituted against the Licensee by a third party,
|
||||||
|
shall constitute consequential loss and shall not provide entitlement to
|
||||||
|
any or all compensation from the Licensor.
|
||||||
|
|
||||||
|
|
||||||
|
Article 9 - WARRANTY
|
||||||
|
|
||||||
|
9.1 The Licensee acknowledges that the scientific and technical
|
||||||
|
state-of-the-art when the Software was distributed did not enable all
|
||||||
|
possible uses to be tested and verified, nor for the presence of
|
||||||
|
possible defects to be detected. In this respect, the Licensee's
|
||||||
|
attention has been drawn to the risks associated with loading, using,
|
||||||
|
modifying and/or developing and reproducing the Software which are
|
||||||
|
reserved for experienced users.
|
||||||
|
|
||||||
|
The Licensee shall be responsible for verifying, by any or all means,
|
||||||
|
the suitability of the product for its requirements, its good working order,
|
||||||
|
and for ensuring that it shall not cause damage to either persons or
|
||||||
|
properties.
|
||||||
|
|
||||||
|
9.2 The Licensor hereby represents, in good faith, that it is entitled
|
||||||
|
to grant all the rights over the Software (including in particular the
|
||||||
|
rights set forth in Article 5).
|
||||||
|
|
||||||
|
9.3 The Licensee acknowledges that the Software is supplied "as is" by
|
||||||
|
the Licensor without any other express or tacit warranty, other than
|
||||||
|
that provided for in Article 9.2 and, in particular, without any warranty
|
||||||
|
as to its commercial value, its secured, safe, innovative or relevant
|
||||||
|
nature.
|
||||||
|
|
||||||
|
Specifically, the Licensor does not warrant that the Software is free
|
||||||
|
from any error, that it will operate without interruption, that it will
|
||||||
|
be compatible with the Licensee's own equipment and software
|
||||||
|
configuration, nor that it will meet the Licensee's requirements.
|
||||||
|
|
||||||
|
9.4 The Licensor does not either expressly or tacitly warrant that the
|
||||||
|
Software does not infringe any third party intellectual property right
|
||||||
|
relating to a patent, software or any other property right. Therefore,
|
||||||
|
the Licensor disclaims any and all liability towards the Licensee
|
||||||
|
arising out of any or all proceedings for infringement that may be
|
||||||
|
instituted in respect of the use, modification and redistribution of the
|
||||||
|
Software. Nevertheless, should such proceedings be instituted against
|
||||||
|
the Licensee, the Licensor shall provide it with technical and legal
|
||||||
|
assistance for its defense. Such technical and legal assistance shall be
|
||||||
|
decided on a case-by-case basis between the relevant Licensor and the
|
||||||
|
Licensee pursuant to a memorandum of understanding. The Licensor
|
||||||
|
disclaims any and all liability as regards the Licensee's use of the
|
||||||
|
name of the Software. No warranty is given as regards the existence of
|
||||||
|
prior rights over the name of the Software or as regards the existence
|
||||||
|
of a trademark.
|
||||||
|
|
||||||
|
|
||||||
|
Article 10 - TERMINATION
|
||||||
|
|
||||||
|
10.1 In the event of a breach by the Licensee of its obligations
|
||||||
|
hereunder, the Licensor may automatically terminate this Agreement
|
||||||
|
thirty (30) days after notice has been sent to the Licensee and has
|
||||||
|
remained ineffective.
|
||||||
|
|
||||||
|
10.2 A Licensee whose Agreement is terminated shall no longer be
|
||||||
|
authorized to use, modify or distribute the Software. However, any
|
||||||
|
licenses that it may have granted prior to termination of the Agreement
|
||||||
|
shall remain valid subject to their having been granted in compliance
|
||||||
|
with the terms and conditions hereof.
|
||||||
|
|
||||||
|
|
||||||
|
Article 11 - MISCELLANEOUS
|
||||||
|
|
||||||
|
|
||||||
|
11.1 EXCUSABLE EVENTS
|
||||||
|
|
||||||
|
Neither Party shall be liable for any or all delay, or failure to
|
||||||
|
perform the Agreement, that may be attributable to an event of force
|
||||||
|
majeure, an act of God or an outside cause, such as defective
|
||||||
|
functioning or interruptions of the electricity or telecommunications
|
||||||
|
networks, network paralysis following a virus attack, intervention by
|
||||||
|
government authorities, natural disasters, water damage, earthquakes,
|
||||||
|
fire, explosions, strikes and labor unrest, war, etc.
|
||||||
|
|
||||||
|
11.2 Any failure by either Party, on one or more occasions, to invoke
|
||||||
|
one or more of the provisions hereof, shall under no circumstances be
|
||||||
|
interpreted as being a waiver by the interested Party of its right to
|
||||||
|
invoke said provision(s) subsequently.
|
||||||
|
|
||||||
|
11.3 The Agreement cancels and replaces any or all previous agreements,
|
||||||
|
whether written or oral, between the Parties and having the same
|
||||||
|
purpose, and constitutes the entirety of the agreement between said
|
||||||
|
Parties concerning said purpose. No supplement or modification to the
|
||||||
|
terms and conditions hereof shall be effective as between the Parties
|
||||||
|
unless it is made in writing and signed by their duly authorized
|
||||||
|
representatives.
|
||||||
|
|
||||||
|
11.4 In the event that one or more of the provisions hereof were to
|
||||||
|
conflict with a current or future applicable act or legislative text,
|
||||||
|
said act or legislative text shall prevail, and the Parties shall make
|
||||||
|
the necessary amendments so as to comply with said act or legislative
|
||||||
|
text. All other provisions shall remain effective. Similarly, invalidity
|
||||||
|
of a provision of the Agreement, for any reason whatsoever, shall not
|
||||||
|
cause the Agreement as a whole to be invalid.
|
||||||
|
|
||||||
|
|
||||||
|
11.5 LANGUAGE
|
||||||
|
|
||||||
|
The Agreement is drafted in both French and English and both versions
|
||||||
|
are deemed authentic.
|
||||||
|
|
||||||
|
|
||||||
|
Article 12 - NEW VERSIONS OF THE AGREEMENT
|
||||||
|
|
||||||
|
12.1 Any person is authorized to duplicate and distribute copies of this
|
||||||
|
Agreement.
|
||||||
|
|
||||||
|
12.2 So as to ensure coherence, the wording of this Agreement is
|
||||||
|
protected and may only be modified by the authors of the License, who
|
||||||
|
reserve the right to periodically publish updates or new versions of the
|
||||||
|
Agreement, each with a separate number. These subsequent versions may
|
||||||
|
address new issues encountered by Free Software.
|
||||||
|
|
||||||
|
12.3 Any Software distributed under a given version of the Agreement
|
||||||
|
may only be subsequently distributed under the same version of the
|
||||||
|
Agreement or a subsequent version.
|
||||||
|
|
||||||
|
|
||||||
|
Article 13 - GOVERNING LAW AND JURISDICTION
|
||||||
|
|
||||||
|
13.1 The Agreement is governed by French law. The Parties agree to
|
||||||
|
endeavor to seek an amicable solution to any disagreements or disputes
|
||||||
|
that may arise during the performance of the Agreement.
|
||||||
|
|
||||||
|
13.2 Failing an amicable solution within two (2) months as from their
|
||||||
|
occurrence, and unless emergency proceedings are necessary, the
|
||||||
|
disagreements or disputes shall be referred to the Paris Courts having
|
||||||
|
jurisdiction, by the more diligent Party.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.0 dated 2006-07-12.
|
504
Licence_CeCILL_V2-en.txt
Normal file
504
Licence_CeCILL_V2-en.txt
Normal file
|
@ -0,0 +1,504 @@
|
||||||
|
|
||||||
|
CeCILL FREE SOFTWARE LICENSE AGREEMENT
|
||||||
|
|
||||||
|
|
||||||
|
Notice
|
||||||
|
|
||||||
|
This Agreement is a Free Software license agreement that is the result
|
||||||
|
of discussions between its authors in order to ensure compliance with
|
||||||
|
the two main principles guiding its drafting:
|
||||||
|
|
||||||
|
* firstly, compliance with the principles governing the distribution
|
||||||
|
of Free Software: access to source code, broad rights granted to
|
||||||
|
users,
|
||||||
|
* secondly, the election of a governing law, French law, with which
|
||||||
|
it is conformant, both as regards the law of torts and
|
||||||
|
intellectual property law, and the protection that it offers to
|
||||||
|
both authors and holders of the economic rights over software.
|
||||||
|
|
||||||
|
The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[logiciel] L[ibre])
|
||||||
|
license are:
|
||||||
|
|
||||||
|
Commissariat à l'Energie Atomique - CEA, a public scientific, technical
|
||||||
|
and industrial research establishment, having its principal place of
|
||||||
|
business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France.
|
||||||
|
|
||||||
|
Centre National de la Recherche Scientifique - CNRS, a public scientific
|
||||||
|
and technological research establishment, having its principal place of
|
||||||
|
business at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
|
||||||
|
|
||||||
|
Institut National de Recherche en Informatique et en Automatique -
|
||||||
|
INRIA, a public scientific and technological establishment, having its
|
||||||
|
principal place of business at Domaine de Voluceau, Rocquencourt, BP
|
||||||
|
105, 78153 Le Chesnay cedex, France.
|
||||||
|
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The purpose of this Free Software license agreement is to grant users
|
||||||
|
the right to modify and redistribute the software governed by this
|
||||||
|
license within the framework of an open source distribution model.
|
||||||
|
|
||||||
|
The exercising of these rights is conditional upon certain obligations
|
||||||
|
for users so as to preserve this status for all subsequent redistributions.
|
||||||
|
|
||||||
|
In consideration of access to the source code and the rights to copy,
|
||||||
|
modify and redistribute granted by the license, users are provided only
|
||||||
|
with a limited warranty and the software's author, the holder of the
|
||||||
|
economic rights, and the successive licensors only have limited liability.
|
||||||
|
|
||||||
|
In this respect, the risks associated with loading, using, modifying
|
||||||
|
and/or developing or reproducing the software by the user are brought to
|
||||||
|
the user's attention, given its Free Software status, which may make it
|
||||||
|
complicated to use, with the result that its use is reserved for
|
||||||
|
developers and experienced professionals having in-depth computer
|
||||||
|
knowledge. Users are therefore encouraged to load and test the suitability
|
||||||
|
of the software as regards their requirements in conditions enabling
|
||||||
|
the security of their systems and/or data to be ensured and, more
|
||||||
|
generally, to use and operate it in the same conditions of security.
|
||||||
|
This Agreement may be freely reproduced and published, provided it is not
|
||||||
|
altered, and that no provisions are either added or removed herefrom.
|
||||||
|
|
||||||
|
This Agreement may apply to any or all software for which the holder of
|
||||||
|
the economic rights decides to submit the use thereof to its provisions.
|
||||||
|
|
||||||
|
|
||||||
|
Article 1 - DEFINITIONS
|
||||||
|
|
||||||
|
For the purpose of this Agreement, when the following expressions
|
||||||
|
commence with a capital letter, they shall have the following meaning:
|
||||||
|
|
||||||
|
Agreement: means this license agreement, and its possible subsequent
|
||||||
|
versions and annexes.
|
||||||
|
|
||||||
|
Software: means the software in its Object Code and/or Source Code form
|
||||||
|
and, where applicable, its documentation, "as is" when the Licensee
|
||||||
|
accepts the Agreement.
|
||||||
|
|
||||||
|
Initial Software: means the Software in its Source Code and possibly its
|
||||||
|
Object Code form and, where applicable, its documentation, "as is" when
|
||||||
|
it is first distributed under the terms and conditions of the Agreement.
|
||||||
|
|
||||||
|
Modified Software: means the Software modified by at least one
|
||||||
|
Contribution.
|
||||||
|
|
||||||
|
Source Code: means all the Software's instructions and program lines to
|
||||||
|
which access is required so as to modify the Software.
|
||||||
|
|
||||||
|
Object Code: means the binary files originating from the compilation of
|
||||||
|
the Source Code.
|
||||||
|
|
||||||
|
Holder: means the holder(s) of the economic rights over the Initial
|
||||||
|
Software.
|
||||||
|
|
||||||
|
Licensee: means the Software user(s) having accepted the Agreement.
|
||||||
|
|
||||||
|
Contributor: means a Licensee having made at least one Contribution.
|
||||||
|
|
||||||
|
Licensor: means the Holder, or any other individual or legal entity, who
|
||||||
|
distributes the Software under the Agreement.
|
||||||
|
|
||||||
|
Contribution: means any or all modifications, corrections, translations,
|
||||||
|
adaptations and/or new functions integrated into the Software by any or
|
||||||
|
all Contributors, as well as any or all Internal Modules.
|
||||||
|
|
||||||
|
Module: means a set of sources files including their documentation that
|
||||||
|
enables supplementary functions or services in addition to those offered
|
||||||
|
by the Software.
|
||||||
|
|
||||||
|
External Module: means any or all Modules, not derived from the
|
||||||
|
Software, so that this Module and the Software run in separate address
|
||||||
|
spaces, with one calling the other when they are run.
|
||||||
|
|
||||||
|
Internal Module: means any or all Module, connected to the Software so
|
||||||
|
that they both execute in the same address space.
|
||||||
|
|
||||||
|
GNU GPL: means the GNU General Public License version 2 or any
|
||||||
|
subsequent version, as published by the Free Software Foundation Inc.
|
||||||
|
|
||||||
|
Parties: mean both the Licensee and the Licensor.
|
||||||
|
|
||||||
|
These expressions may be used both in singular and plural form.
|
||||||
|
|
||||||
|
|
||||||
|
Article 2 - PURPOSE
|
||||||
|
|
||||||
|
The purpose of the Agreement is the grant by the Licensor to the
|
||||||
|
Licensee of a non-exclusive, transferable and worldwide license for the
|
||||||
|
Software as set forth in Article 5 hereinafter for the whole term of the
|
||||||
|
protection granted by the rights over said Software.
|
||||||
|
|
||||||
|
|
||||||
|
Article 3 - ACCEPTANCE
|
||||||
|
|
||||||
|
3.1 The Licensee shall be deemed as having accepted the terms and
|
||||||
|
conditions of this Agreement upon the occurrence of the first of the
|
||||||
|
following events:
|
||||||
|
|
||||||
|
* (i) loading the Software by any or all means, notably, by
|
||||||
|
downloading from a remote server, or by loading from a physical
|
||||||
|
medium;
|
||||||
|
* (ii) the first time the Licensee exercises any of the rights
|
||||||
|
granted hereunder.
|
||||||
|
|
||||||
|
3.2 One copy of the Agreement, containing a notice relating to the
|
||||||
|
characteristics of the Software, to the limited warranty, and to the
|
||||||
|
fact that its use is restricted to experienced users has been provided
|
||||||
|
to the Licensee prior to its acceptance as set forth in Article 3.1
|
||||||
|
hereinabove, and the Licensee hereby acknowledges that it has read and
|
||||||
|
understood it.
|
||||||
|
|
||||||
|
|
||||||
|
Article 4 - EFFECTIVE DATE AND TERM
|
||||||
|
|
||||||
|
|
||||||
|
4.1 EFFECTIVE DATE
|
||||||
|
|
||||||
|
The Agreement shall become effective on the date when it is accepted by
|
||||||
|
the Licensee as set forth in Article 3.1.
|
||||||
|
|
||||||
|
|
||||||
|
4.2 TERM
|
||||||
|
|
||||||
|
The Agreement shall remain in force for the entire legal term of
|
||||||
|
protection of the economic rights over the Software.
|
||||||
|
|
||||||
|
|
||||||
|
Article 5 - SCOPE OF RIGHTS GRANTED
|
||||||
|
|
||||||
|
The Licensor hereby grants to the Licensee, who accepts, the following
|
||||||
|
rights over the Software for any or all use, and for the term of the
|
||||||
|
Agreement, on the basis of the terms and conditions set forth hereinafter.
|
||||||
|
|
||||||
|
Besides, if the Licensor owns or comes to own one or more patents
|
||||||
|
protecting all or part of the functions of the Software or of its
|
||||||
|
components, the Licensor undertakes not to enforce the rights granted by
|
||||||
|
these patents against successive Licensees using, exploiting or
|
||||||
|
modifying the Software. If these patents are transferred, the Licensor
|
||||||
|
undertakes to have the transferees subscribe to the obligations set
|
||||||
|
forth in this paragraph.
|
||||||
|
|
||||||
|
|
||||||
|
5.1 RIGHT OF USE
|
||||||
|
|
||||||
|
The Licensee is authorized to use the Software, without any limitation
|
||||||
|
as to its fields of application, with it being hereinafter specified
|
||||||
|
that this comprises:
|
||||||
|
|
||||||
|
1. permanent or temporary reproduction of all or part of the Software
|
||||||
|
by any or all means and in any or all form.
|
||||||
|
|
||||||
|
2. loading, displaying, running, or storing the Software on any or
|
||||||
|
all medium.
|
||||||
|
|
||||||
|
3. entitlement to observe, study or test its operation so as to
|
||||||
|
determine the ideas and principles behind any or all constituent
|
||||||
|
elements of said Software. This shall apply when the Licensee
|
||||||
|
carries out any or all loading, displaying, running, transmission
|
||||||
|
or storage operation as regards the Software, that it is entitled
|
||||||
|
to carry out hereunder.
|
||||||
|
|
||||||
|
|
||||||
|
5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS
|
||||||
|
|
||||||
|
The right to make Contributions includes the right to translate, adapt,
|
||||||
|
arrange, or make any or all modifications to the Software, and the right
|
||||||
|
to reproduce the resulting software.
|
||||||
|
|
||||||
|
The Licensee is authorized to make any or all Contributions to the
|
||||||
|
Software provided that it includes an explicit notice that it is the
|
||||||
|
author of said Contribution and indicates the date of the creation thereof.
|
||||||
|
|
||||||
|
|
||||||
|
5.3 RIGHT OF DISTRIBUTION
|
||||||
|
|
||||||
|
In particular, the right of distribution includes the right to publish,
|
||||||
|
transmit and communicate the Software to the general public on any or
|
||||||
|
all medium, and by any or all means, and the right to market, either in
|
||||||
|
consideration of a fee, or free of charge, one or more copies of the
|
||||||
|
Software by any means.
|
||||||
|
|
||||||
|
The Licensee is further authorized to distribute copies of the modified
|
||||||
|
or unmodified Software to third parties according to the terms and
|
||||||
|
conditions set forth hereinafter.
|
||||||
|
|
||||||
|
|
||||||
|
5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
|
||||||
|
|
||||||
|
The Licensee is authorized to distribute true copies of the Software in
|
||||||
|
Source Code or Object Code form, provided that said distribution
|
||||||
|
complies with all the provisions of the Agreement and is accompanied by:
|
||||||
|
|
||||||
|
1. a copy of the Agreement,
|
||||||
|
|
||||||
|
2. a notice relating to the limitation of both the Licensor's
|
||||||
|
warranty and liability as set forth in Articles 8 and 9,
|
||||||
|
|
||||||
|
and that, in the event that only the Object Code of the Software is
|
||||||
|
redistributed, the Licensee allows future Licensees unhindered access to
|
||||||
|
the full Source Code of the Software by indicating how to access it, it
|
||||||
|
being understood that the additional cost of acquiring the Source Code
|
||||||
|
shall not exceed the cost of transferring the data.
|
||||||
|
|
||||||
|
|
||||||
|
5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
|
||||||
|
|
||||||
|
When the Licensee makes a Contribution to the Software, the terms and
|
||||||
|
conditions for the distribution of the resulting Modified Software
|
||||||
|
become subject to all the provisions of this Agreement.
|
||||||
|
|
||||||
|
The Licensee is authorized to distribute the Modified Software, in
|
||||||
|
source code or object code form, provided that said distribution
|
||||||
|
complies with all the provisions of the Agreement and is accompanied by:
|
||||||
|
|
||||||
|
1. a copy of the Agreement,
|
||||||
|
|
||||||
|
2. a notice relating to the limitation of both the Licensor's
|
||||||
|
warranty and liability as set forth in Articles 8 and 9,
|
||||||
|
|
||||||
|
and that, in the event that only the Object Code of the Modified
|
||||||
|
Software is redistributed, the Licensee allows future Licensees
|
||||||
|
unhindered access to the full source code of the Modified Software by
|
||||||
|
indicating how to access it, it being understood that the additional
|
||||||
|
cost of acquiring the source code shall not exceed the cost of
|
||||||
|
transferring the data.
|
||||||
|
|
||||||
|
|
||||||
|
5.3.3 DISTRIBUTION OF EXTERNAL MODULES
|
||||||
|
|
||||||
|
When the Licensee has developed an External Module, the terms and
|
||||||
|
conditions of this Agreement do not apply to said External Module, that
|
||||||
|
may be distributed under a separate license agreement.
|
||||||
|
|
||||||
|
|
||||||
|
5.3.4 COMPATIBILITY WITH THE GNU GPL
|
||||||
|
|
||||||
|
The Licensee can include a code that is subject to the provisions of one
|
||||||
|
of the versions of the GNU GPL in the Modified or unmodified Software,
|
||||||
|
and distribute that entire code under the terms of the same version of
|
||||||
|
the GNU GPL.
|
||||||
|
|
||||||
|
The Licensee can include the Modified or unmodified Software in a code
|
||||||
|
that is subject to the provisions of one of the versions of the GNU GPL,
|
||||||
|
and distribute that entire code under the terms of the same version of
|
||||||
|
the GNU GPL.
|
||||||
|
|
||||||
|
|
||||||
|
Article 6 - INTELLECTUAL PROPERTY
|
||||||
|
|
||||||
|
|
||||||
|
6.1 OVER THE INITIAL SOFTWARE
|
||||||
|
|
||||||
|
The Holder owns the economic rights over the Initial Software. Any or
|
||||||
|
all use of the Initial Software is subject to compliance with the terms
|
||||||
|
and conditions under which the Holder has elected to distribute its work
|
||||||
|
and no one shall be entitled to modify the terms and conditions for the
|
||||||
|
distribution of said Initial Software.
|
||||||
|
|
||||||
|
The Holder undertakes that the Initial Software will remain ruled at
|
||||||
|
least by the current license, for the duration set forth in Article 4.2.
|
||||||
|
|
||||||
|
|
||||||
|
6.2 OVER THE CONTRIBUTIONS
|
||||||
|
|
||||||
|
A Licensee who develops a Contribution is the owner of the intellectual
|
||||||
|
property rights over this Contribution as defined by applicable law.
|
||||||
|
|
||||||
|
|
||||||
|
6.3 OVER THE EXTERNAL MODULES
|
||||||
|
|
||||||
|
A Licensee who develops an External Module is the owner of the
|
||||||
|
intellectual property rights over this External Module as defined by
|
||||||
|
applicable law and is free to choose the type of agreement that shall
|
||||||
|
govern its distribution.
|
||||||
|
|
||||||
|
|
||||||
|
6.4 JOINT PROVISIONS
|
||||||
|
|
||||||
|
The Licensee expressly undertakes:
|
||||||
|
|
||||||
|
1. not to remove, or modify, in any manner, the intellectual property
|
||||||
|
notices attached to the Software;
|
||||||
|
|
||||||
|
2. to reproduce said notices, in an identical manner, in the copies
|
||||||
|
of the Software modified or not.
|
||||||
|
|
||||||
|
The Licensee undertakes not to directly or indirectly infringe the
|
||||||
|
intellectual property rights of the Holder and/or Contributors on the
|
||||||
|
Software and to take, where applicable, vis-à-vis its staff, any and all
|
||||||
|
measures required to ensure respect of said intellectual property rights
|
||||||
|
of the Holder and/or Contributors.
|
||||||
|
|
||||||
|
|
||||||
|
Article 7 - RELATED SERVICES
|
||||||
|
|
||||||
|
7.1 Under no circumstances shall the Agreement oblige the Licensor to
|
||||||
|
provide technical assistance or maintenance services for the Software.
|
||||||
|
|
||||||
|
However, the Licensor is entitled to offer this type of services. The
|
||||||
|
terms and conditions of such technical assistance, and/or such
|
||||||
|
maintenance, shall be set forth in a separate instrument. Only the
|
||||||
|
Licensor offering said maintenance and/or technical assistance services
|
||||||
|
shall incur liability therefor.
|
||||||
|
|
||||||
|
7.2 Similarly, any Licensor is entitled to offer to its licensees, under
|
||||||
|
its sole responsibility, a warranty, that shall only be binding upon
|
||||||
|
itself, for the redistribution of the Software and/or the Modified
|
||||||
|
Software, under terms and conditions that it is free to decide. Said
|
||||||
|
warranty, and the financial terms and conditions of its application,
|
||||||
|
shall be subject of a separate instrument executed between the Licensor
|
||||||
|
and the Licensee.
|
||||||
|
|
||||||
|
|
||||||
|
Article 8 - LIABILITY
|
||||||
|
|
||||||
|
8.1 Subject to the provisions of Article 8.2, the Licensee shall be
|
||||||
|
entitled to claim compensation for any direct loss it may have suffered
|
||||||
|
from the Software as a result of a fault on the part of the relevant
|
||||||
|
Licensor, subject to providing evidence thereof.
|
||||||
|
|
||||||
|
8.2 The Licensor's liability is limited to the commitments made under
|
||||||
|
this Agreement and shall not be incurred as a result of in particular:
|
||||||
|
(i) loss due the Licensee's total or partial failure to fulfill its
|
||||||
|
obligations, (ii) direct or consequential loss that is suffered by the
|
||||||
|
Licensee due to the use or performance of the Software, and (iii) more
|
||||||
|
generally, any consequential loss. In particular the Parties expressly
|
||||||
|
agree that any or all pecuniary or business loss (i.e. loss of data,
|
||||||
|
loss of profits, operating loss, loss of customers or orders,
|
||||||
|
opportunity cost, any disturbance to business activities) or any or all
|
||||||
|
legal proceedings instituted against the Licensee by a third party,
|
||||||
|
shall constitute consequential loss and shall not provide entitlement to
|
||||||
|
any or all compensation from the Licensor.
|
||||||
|
|
||||||
|
|
||||||
|
Article 9 - WARRANTY
|
||||||
|
|
||||||
|
9.1 The Licensee acknowledges that the scientific and technical
|
||||||
|
state-of-the-art when the Software was distributed did not enable all
|
||||||
|
possible uses to be tested and verified, nor for the presence of
|
||||||
|
possible defects to be detected. In this respect, the Licensee's
|
||||||
|
attention has been drawn to the risks associated with loading, using,
|
||||||
|
modifying and/or developing and reproducing the Software which are
|
||||||
|
reserved for experienced users.
|
||||||
|
|
||||||
|
The Licensee shall be responsible for verifying, by any or all means,
|
||||||
|
the suitability of the product for its requirements, its good working order,
|
||||||
|
and for ensuring that it shall not cause damage to either persons or
|
||||||
|
properties.
|
||||||
|
|
||||||
|
9.2 The Licensor hereby represents, in good faith, that it is entitled
|
||||||
|
to grant all the rights over the Software (including in particular the
|
||||||
|
rights set forth in Article 5).
|
||||||
|
|
||||||
|
9.3 The Licensee acknowledges that the Software is supplied "as is" by
|
||||||
|
the Licensor without any other express or tacit warranty, other than
|
||||||
|
that provided for in Article 9.2 and, in particular, without any warranty
|
||||||
|
as to its commercial value, its secured, safe, innovative or relevant
|
||||||
|
nature.
|
||||||
|
|
||||||
|
Specifically, the Licensor does not warrant that the Software is free
|
||||||
|
from any error, that it will operate without interruption, that it will
|
||||||
|
be compatible with the Licensee's own equipment and software
|
||||||
|
configuration, nor that it will meet the Licensee's requirements.
|
||||||
|
|
||||||
|
9.4 The Licensor does not either expressly or tacitly warrant that the
|
||||||
|
Software does not infringe any third party intellectual property right
|
||||||
|
relating to a patent, software or any other property right. Therefore,
|
||||||
|
the Licensor disclaims any and all liability towards the Licensee
|
||||||
|
arising out of any or all proceedings for infringement that may be
|
||||||
|
instituted in respect of the use, modification and redistribution of the
|
||||||
|
Software. Nevertheless, should such proceedings be instituted against
|
||||||
|
the Licensee, the Licensor shall provide it with technical and legal
|
||||||
|
assistance for its defense. Such technical and legal assistance shall be
|
||||||
|
decided on a case-by-case basis between the relevant Licensor and the
|
||||||
|
Licensee pursuant to a memorandum of understanding. The Licensor
|
||||||
|
disclaims any and all liability as regards the Licensee's use of the
|
||||||
|
name of the Software. No warranty is given as regards the existence of
|
||||||
|
prior rights over the name of the Software or as regards the existence
|
||||||
|
of a trademark.
|
||||||
|
|
||||||
|
|
||||||
|
Article 10 - TERMINATION
|
||||||
|
|
||||||
|
10.1 In the event of a breach by the Licensee of its obligations
|
||||||
|
hereunder, the Licensor may automatically terminate this Agreement
|
||||||
|
thirty (30) days after notice has been sent to the Licensee and has
|
||||||
|
remained ineffective.
|
||||||
|
|
||||||
|
10.2 A Licensee whose Agreement is terminated shall no longer be
|
||||||
|
authorized to use, modify or distribute the Software. However, any
|
||||||
|
licenses that it may have granted prior to termination of the Agreement
|
||||||
|
shall remain valid subject to their having been granted in compliance
|
||||||
|
with the terms and conditions hereof.
|
||||||
|
|
||||||
|
|
||||||
|
Article 11 - MISCELLANEOUS
|
||||||
|
|
||||||
|
|
||||||
|
11.1 EXCUSABLE EVENTS
|
||||||
|
|
||||||
|
Neither Party shall be liable for any or all delay, or failure to
|
||||||
|
perform the Agreement, that may be attributable to an event of force
|
||||||
|
majeure, an act of God or an outside cause, such as defective
|
||||||
|
functioning or interruptions of the electricity or telecommunications
|
||||||
|
networks, network paralysis following a virus attack, intervention by
|
||||||
|
government authorities, natural disasters, water damage, earthquakes,
|
||||||
|
fire, explosions, strikes and labor unrest, war, etc.
|
||||||
|
|
||||||
|
11.2 Any failure by either Party, on one or more occasions, to invoke
|
||||||
|
one or more of the provisions hereof, shall under no circumstances be
|
||||||
|
interpreted as being a waiver by the interested Party of its right to
|
||||||
|
invoke said provision(s) subsequently.
|
||||||
|
|
||||||
|
11.3 The Agreement cancels and replaces any or all previous agreements,
|
||||||
|
whether written or oral, between the Parties and having the same
|
||||||
|
purpose, and constitutes the entirety of the agreement between said
|
||||||
|
Parties concerning said purpose. No supplement or modification to the
|
||||||
|
terms and conditions hereof shall be effective as between the Parties
|
||||||
|
unless it is made in writing and signed by their duly authorized
|
||||||
|
representatives.
|
||||||
|
|
||||||
|
11.4 In the event that one or more of the provisions hereof were to
|
||||||
|
conflict with a current or future applicable act or legislative text,
|
||||||
|
said act or legislative text shall prevail, and the Parties shall make
|
||||||
|
the necessary amendments so as to comply with said act or legislative
|
||||||
|
text. All other provisions shall remain effective. Similarly, invalidity
|
||||||
|
of a provision of the Agreement, for any reason whatsoever, shall not
|
||||||
|
cause the Agreement as a whole to be invalid.
|
||||||
|
|
||||||
|
|
||||||
|
11.5 LANGUAGE
|
||||||
|
|
||||||
|
The Agreement is drafted in both French and English and both versions
|
||||||
|
are deemed authentic.
|
||||||
|
|
||||||
|
|
||||||
|
Article 12 - NEW VERSIONS OF THE AGREEMENT
|
||||||
|
|
||||||
|
12.1 Any person is authorized to duplicate and distribute copies of this
|
||||||
|
Agreement.
|
||||||
|
|
||||||
|
12.2 So as to ensure coherence, the wording of this Agreement is
|
||||||
|
protected and may only be modified by the authors of the License, who
|
||||||
|
reserve the right to periodically publish updates or new versions of the
|
||||||
|
Agreement, each with a separate number. These subsequent versions may
|
||||||
|
address new issues encountered by Free Software.
|
||||||
|
|
||||||
|
12.3 Any Software distributed under a given version of the Agreement may
|
||||||
|
only be subsequently distributed under the same version of the Agreement
|
||||||
|
or a subsequent version, subject to the provisions of Article 5.3.4.
|
||||||
|
|
||||||
|
|
||||||
|
Article 13 - GOVERNING LAW AND JURISDICTION
|
||||||
|
|
||||||
|
13.1 The Agreement is governed by French law. The Parties agree to
|
||||||
|
endeavor to seek an amicable solution to any disagreements or disputes
|
||||||
|
that may arise during the performance of the Agreement.
|
||||||
|
|
||||||
|
13.2 Failing an amicable solution within two (2) months as from their
|
||||||
|
occurrence, and unless emergency proceedings are necessary, the
|
||||||
|
disagreements or disputes shall be referred to the Paris Courts having
|
||||||
|
jurisdiction, by the more diligent Party.
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.0 dated 2006-07-12.
|
24
README.md
Normal file
24
README.md
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<a href="http://cimg.eu">![Logo](http://cimg.eu/img/CImgLogo2.jpg)</a>
|
||||||
|
##### http://cimg.eu
|
||||||
|
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The **CImg Library** is a **small** and **open-source** **C++ toolkit** for **image processing**, designed with these properties in mind:
|
||||||
|
|
||||||
|
![Usefulness](http://cimg.eu/img/item_usefulness.jpg) **CImg** defines *classes* and *methods* to manage images in your own C++ code. You can use **CImg** to load/save various file formats, access pixel values, display/transform/filter images, draw primitives (text, faces, curves, 3d objects, ...), compute statistics, manage user interactions on images, and so on...
|
||||||
|
|
||||||
|
![Genericity](http://cimg.eu/img/item_genericity.jpg) **CImg** defines a single image class able to represent datasets having up to *4-dimensions* (from 1d scalar signals to 3d hyperspectral volumetric images), with *template pixel types* (`bool,char,int,float,...`). It also handles image *collections* and *sequences*.
|
||||||
|
|
||||||
|
![Portability](http://cimg.eu/img/item_portability.jpg) **CImg** is *self-contained*, *thread-safe* and *highly portable*. It fully works on *different operating systems* (`Unix,Windows,MacOS X,*BSD,...`) and is compatible with *various C++ compilers* (`Visual C++,g++,clang++,icc,...`).
|
||||||
|
|
||||||
|
![Simplicity](http://cimg.eu/img/item_simplicity.jpg) **CImg** is *lightweight*. It is made of a single header file [`CImg.h`](https://github.com/dtschump/CImg/raw/master/CImg.h) that must be included in your C++ source. It defines only *four* different classes, encapsulated in the namespace `cimg_library`. It can be compiled using a minimal set of standard C++ and system libraries only. *No need for exotic or complex dependencies*.
|
||||||
|
|
||||||
|
![Extensibility](http://cimg.eu/img/item_extensibility.jpg) Although not mandatory, **CImg** can use functionalities of external tools/libraries such as [Board](http://libboard.sourceforge.net/), [FFMPEG](http://ffmpeg.mplayerhq.hu/), [FFTW3](http://www.fftw.org/), [GraphicsMagick](http://www.graphicsmagick.org/), [ImageMagick](http://www.imagemagick.org/), [Lapack](http://www.netlib.org/lapack/), [libcurl](http://curl.haxx.se/libcurl/), [libjpeg](http://www.ijg.org/), [libpng](http://www.libpng.org/pub/png/libpng.html), [libtiff](http://www.libtiff.org/), [Magick++](http://www.imagemagick.org/Magick++/), [OpenEXR](http://www.openexr.com/), [OpenCV](http://http://opencv.willowgarage.com/wiki/), [OpenMP](http://www.openmp.org/) or [XMedCon](http://xmedcon.sourceforge.net/). Moreover, a simple *plug-in* mechanism allows any user to directly enhance the library capabilities according to their needs.
|
||||||
|
|
||||||
|
![Freedom](http://cimg.eu/img/item_freedom.jpg) **CImg** is a *free, open-source library* distributed under the [*CeCILL-C*](http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt) (close to the GNU LGPL) or [CeCILL](http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt) (compatible with the GNU GPL) licenses. It can be used in commercial applications.
|
||||||
|
|
||||||
|
------------------
|
||||||
|
|
||||||
|
> **CImg** stands for **Cool Image** : It is _easy to use_, _efficient_ and is intended to be a very pleasant toolbox to design image processing algorithms in C++. Due to its generic conception, it can cover a wide range of image processing applications.
|
||||||
|
|
||||||
|
------------------
|
180
README.txt
Normal file
180
README.txt
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
____ _ _ ____
|
||||||
|
(_ _)( )_( )( ___)
|
||||||
|
)( ) _ ( )__)
|
||||||
|
(__) (_) (_)(____)
|
||||||
|
___ ____ __ __ ___ __ ____ ____ ____ __ ____ _ _
|
||||||
|
/ __)(_ _)( \/ )/ __) ( ) (_ _)( _ \( _ \ /__\ ( _ \( \/ )
|
||||||
|
( (__ _)(_ ) (( (_-. )(__ _)(_ ) _ < ) / /(__)\ ) / \ /
|
||||||
|
\___)(____)(_/\/\_)\___/ (____)(____)(____/(_)\_)(__)(__)(_)\_) (__)
|
||||||
|
|
||||||
|
|
||||||
|
C++ Template Image Processing Toolkit
|
||||||
|
|
||||||
|
( http://cimg.eu )
|
||||||
|
|
||||||
|
_cimg_version
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
#---------
|
||||||
|
|
||||||
|
The CImg Library is a small and open-source C++ toolkit for image processing.
|
||||||
|
It consists in a single header file 'CImg.h' providing a minimal set of C++
|
||||||
|
classes and methods that can be used in your own sources, to load/save,
|
||||||
|
process and display images. Very portable (Unix/X11,Windows, MacOS X, FreeBSD, .. ),
|
||||||
|
efficient, easy to use, it's a pleasant library for developing image processing
|
||||||
|
algorithms in C++.
|
||||||
|
|
||||||
|
# Authors and contributors :
|
||||||
|
#----------------------------
|
||||||
|
|
||||||
|
- David Tschumperlé (project leader) ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
|
||||||
|
- Maksim Aizenshtein
|
||||||
|
- Alberto Albiol
|
||||||
|
- Antonio Albiol
|
||||||
|
- Simon Barthelme
|
||||||
|
- Neil Brown
|
||||||
|
- Haz-Edine Assemlal
|
||||||
|
- Vincent Barra
|
||||||
|
- Wolf Blecher
|
||||||
|
- Romain Blei
|
||||||
|
- Yohan Bentolila
|
||||||
|
- Jerome Boulanger
|
||||||
|
- Pierre Buyssens
|
||||||
|
- Sebastien Coudert
|
||||||
|
- Frederic Devernay
|
||||||
|
- Olivier D'Hondt
|
||||||
|
- Francois-Xavier Dupe
|
||||||
|
- Gerd von Egidy
|
||||||
|
- Eric Fausett
|
||||||
|
- Jean-Marie Favreau
|
||||||
|
- Sebastien Fourey
|
||||||
|
- Alexandre Fournier
|
||||||
|
- Hon-Kwok Fung
|
||||||
|
- Vincent Garcia
|
||||||
|
- David Grimbichler
|
||||||
|
- Jinwei Gu
|
||||||
|
- Jean-Daniel Guyot
|
||||||
|
- Cedric Hammiche
|
||||||
|
- Matt Hanson
|
||||||
|
- Sebastien Hanel
|
||||||
|
- Michael Holroyd
|
||||||
|
- Christoph Hormann
|
||||||
|
- Werner Jainek
|
||||||
|
- Daniel Kondermann
|
||||||
|
- Pierre Kornprobst
|
||||||
|
- Jan W. Krieger
|
||||||
|
- Orges Leka
|
||||||
|
- Francois Lauze
|
||||||
|
- Xie Long
|
||||||
|
- Thomas Martin
|
||||||
|
- Cesar Martinez
|
||||||
|
- Jean Martinot
|
||||||
|
- Arnold Meijster (Center for High Performance Computing and Visualization, University of Groningen/The Netherlands)
|
||||||
|
- Nikita Melnichenko
|
||||||
|
- Julien Morat
|
||||||
|
- Baptiste Mougel
|
||||||
|
- Jovana Milutinovich
|
||||||
|
- Guillaume Nee
|
||||||
|
- Adam Newgas
|
||||||
|
- Francisco Oliveira
|
||||||
|
- Andrea Onofri
|
||||||
|
- Renaud Peteri
|
||||||
|
- Martin Petricek
|
||||||
|
- Paolo Prete
|
||||||
|
- Adrien Reboisson
|
||||||
|
- Klaus Schneider
|
||||||
|
- Jakob Schluttig
|
||||||
|
- Jamie Smith
|
||||||
|
- Veronique Souchaud
|
||||||
|
- Konstantin Spirin
|
||||||
|
- David G. Starkweather
|
||||||
|
- Rainer Steffens
|
||||||
|
- Grzegorz Szwoch
|
||||||
|
- Thierry Thomas
|
||||||
|
- Yu-En-Yun
|
||||||
|
- Vo Duc Khanh
|
||||||
|
- Phillip Wood
|
||||||
|
- Bug Zhao
|
||||||
|
- Haibo Zheng
|
||||||
|
|
||||||
|
# Institution
|
||||||
|
#-------------
|
||||||
|
|
||||||
|
GREYC Image / CNRS UMR 6072 / FRANCE
|
||||||
|
|
||||||
|
The CImg Library project started in 2000, at the INRIA-Sophia
|
||||||
|
Antipolis/France ( http://www-sop.inria.fr/ ), in the ROBOTVIS / ODYSSEE Team.
|
||||||
|
Since October 2004, it is maintained and developed in the Image team of
|
||||||
|
the GREYC Lab (CNRS, UMR 6072), in Caen/France.
|
||||||
|
Team web page : http://www.greyc.fr/image
|
||||||
|
|
||||||
|
# Licenses
|
||||||
|
#----------
|
||||||
|
|
||||||
|
The source code of the CImg Library is distributed under
|
||||||
|
two distinct licenses :
|
||||||
|
|
||||||
|
- The main library file 'CImg.h' is *dual-licensed* :
|
||||||
|
It can be either distributed under the CeCILL-C or CeCILL license.
|
||||||
|
(see files 'Licence_CeCILL-C_V1-en.txt' and 'Licence_CeCILL_V2-en.txt').
|
||||||
|
Both are Free-Software licenses :
|
||||||
|
|
||||||
|
* CeCILL-C is adapted to the distribution of
|
||||||
|
library components, and is close in its terms to the well known GNU LGPL license
|
||||||
|
(the 'CImg.h' file can thus be used in closed-source products under certain
|
||||||
|
conditions, please read carefully the license file).
|
||||||
|
|
||||||
|
* CeCILL is close to (and even compatible with) the GNU GPL license.
|
||||||
|
|
||||||
|
- Most of the other files are distributed under the CeCiLL license
|
||||||
|
(file 'Licence_CeCILL_V2-en.txt'). See each file header to see what license applies.
|
||||||
|
|
||||||
|
These two CeCiLL licenses ( http://www.cecill.info/index.en.html ) have been
|
||||||
|
created under the supervision of the three biggest research institutions on
|
||||||
|
computer sciences in France :
|
||||||
|
|
||||||
|
- CNRS ( http://www.cnrs.fr/ )
|
||||||
|
- CEA ( http://www.cea.fr/ )
|
||||||
|
- INRIA ( http://www.inria.fr/ )
|
||||||
|
|
||||||
|
You have to RESPECT these licenses. More particularly, please carefully read
|
||||||
|
the license terms before using the CImg library in commercial products.
|
||||||
|
|
||||||
|
# Package structure :
|
||||||
|
#--------------------
|
||||||
|
|
||||||
|
The main package directory CImg/ is organized as follows :
|
||||||
|
|
||||||
|
- README.txt : This file.
|
||||||
|
- Licence_CeCILL-C_V1-en.txt : A copy of the CeCiLL-C license file.
|
||||||
|
- Licence_CeCILL_V2-en.txt : A copy of the CeCiLL license.
|
||||||
|
- CImg.h : The single header file that constitutes the library itself.
|
||||||
|
- examples/ : A directory containing a lot of example programs performing
|
||||||
|
various things, using the CImg library.
|
||||||
|
- html/ : A directory containing a copy of the CImg web page in html
|
||||||
|
format. The reference documentation is generated
|
||||||
|
automatically with the tool 'doxygen' (http://www.doxygen.org).
|
||||||
|
- resources/ : A directory containing some resources files for compiling
|
||||||
|
CImg examples or packages with various C++ compilers and OS.
|
||||||
|
- plugins/ : A directory containing CImg plug-ins files that can be used to
|
||||||
|
add specific extra functionalities to the CImg library.
|
||||||
|
|
||||||
|
# Getting started
|
||||||
|
#-----------------
|
||||||
|
|
||||||
|
If you are new to CImg, you should first try to compile the different examples
|
||||||
|
provided in the 'examples/' directory, to see what CImg is capable of
|
||||||
|
(as CImg is a template-based library, no prior compilation of the library is mandatory).
|
||||||
|
Look at the 'resources/' directory to ease this compilation on different platforms.
|
||||||
|
|
||||||
|
Then, you can look at the documentation 'html/reference/' to learn more about CImg
|
||||||
|
functions and classes. Finally, you can participate to the 'Forum' section
|
||||||
|
of the CImg web page and ask for help if needed.
|
||||||
|
|
||||||
|
# End of file
|
||||||
|
#------------
|
1712
examples/CImg_demo.cpp
Normal file
1712
examples/CImg_demo.cpp
Normal file
File diff suppressed because it is too large
Load diff
310
examples/CMakeLists.txt
Normal file
310
examples/CMakeLists.txt
Normal file
|
@ -0,0 +1,310 @@
|
||||||
|
#
|
||||||
|
# File : CMakeLists.txt
|
||||||
|
# ( Configuration file for 'cmake' utility )
|
||||||
|
#
|
||||||
|
# Description : CMakeLists.txt configuration file for compiling CImg-based code.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : Antonio Albiol
|
||||||
|
# ( http://personales.upv.es/~aalbiol/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
|
||||||
|
|
||||||
|
PROJECT(Examples-CIMG)
|
||||||
|
|
||||||
|
# Prevent compilation in-source
|
||||||
|
if( ${CMAKE_BINARY_DIR} STREQUAL ${PROJECT_SOURCE_DIR} )
|
||||||
|
Message( " " )
|
||||||
|
Message( FATAL_ERROR "Source and build directories are the same.
|
||||||
|
Create an empty build directory,
|
||||||
|
change into it and re-invoke cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# To use PKG_CHECK_MODULES to find some optional packages
|
||||||
|
find_package(PkgConfig)
|
||||||
|
|
||||||
|
# Tell CMake where to leave executables
|
||||||
|
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
|
||||||
|
|
||||||
|
#Path of CImg.h file relative to this file path
|
||||||
|
set(CIMG_H_PATH ${PROJECT_SOURCE_DIR}/..)
|
||||||
|
include_directories( ${PROJECT_SOURCE_DIR} )
|
||||||
|
include_directories( ${CIMG_H_PATH} )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ### CIMG related stuff
|
||||||
|
# Flags to enable fast image display, using the XSHM library.
|
||||||
|
SET(CIMG_XSHM_CCFLAGS -Dcimg_use_xshm)
|
||||||
|
|
||||||
|
# Flags to enable screen mode switching, using the XRandr library.
|
||||||
|
SET(CIMG_XRANDR_CCFLAGS -Dcimg_use_xrandr)
|
||||||
|
|
||||||
|
# Flags to enable native support for JPEG image files, using the JPEG library.
|
||||||
|
# ( http://www.ijg.org/ )
|
||||||
|
SET(CIMG_JPEG_CCFLAGS -Dcimg_use_jpeg)
|
||||||
|
|
||||||
|
# Flags to enable native support for TIFF image files, using the TIFF library.
|
||||||
|
# ( http://www.libtiff.org/ )
|
||||||
|
SET(CIMG_TIFF_CCFLAGS -Dcimg_use_tiff)
|
||||||
|
|
||||||
|
# Flags to enable native support for PNG image files, using the PNG library.
|
||||||
|
# ( http://www.libpng.org/ )
|
||||||
|
SET(CIMG_PNG_CCFLAGS -Dcimg_use_png)
|
||||||
|
|
||||||
|
#Flags to enable OPENCV support (Camera)
|
||||||
|
# ( http://www.opencv.org/ )
|
||||||
|
SET(CIMG_OPENCV_CCFLAGS-Dcimg_use_opencv)
|
||||||
|
|
||||||
|
# Flags to enable native support for EXR image files, using the OpenEXR library.
|
||||||
|
# ( http://www.openexr.com/ )
|
||||||
|
SET(CIMG_OPENEXR_CCFLAGS -Dcimg_use_openexr)
|
||||||
|
|
||||||
|
# Flags to enable native support for various video files, using the FFMPEG library.
|
||||||
|
# ( http://www.ffmpeg.org/ )
|
||||||
|
SET(CIMG_FFMPEG_CCFLAGS -Dcimg_use_ffmpeg)
|
||||||
|
|
||||||
|
# Flags to enable native support of most classical image file formats, using the Magick++ library.
|
||||||
|
# ( http://www.imagemagick.org/Magick++/ )
|
||||||
|
SET(CIMG_MAGICK_CCFLAGS -Dcimg_use_magick)
|
||||||
|
|
||||||
|
# Flags to enable faster Discrete Fourier Transform computation, using the FFTW3 library
|
||||||
|
# ( http://www.fftw.org/ )
|
||||||
|
SET(CIMG_FFTW3_CCFLAGS -Dcimg_use_fftw3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ### Search Additional Libraries ##########
|
||||||
|
FIND_PACKAGE(OpenCV)
|
||||||
|
FIND_PACKAGE(JPEG)
|
||||||
|
FIND_PACKAGE(TIFF)
|
||||||
|
FIND_PACKAGE(PNG)
|
||||||
|
FIND_PACKAGE(ZLIB)
|
||||||
|
FIND_PACKAGE(LAPACK)
|
||||||
|
FIND_PACKAGE(BLAS)
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(FFTW3 fftw3)
|
||||||
|
PKG_CHECK_MODULES(OPENEXR OpenEXR)
|
||||||
|
PKG_CHECK_MODULES(MAGICK Magick++)
|
||||||
|
|
||||||
|
# PKG_CHECK_MODULES(LIBAVCODEC libavcodec)
|
||||||
|
# PKG_CHECK_MODULES(LIBAVFORMAT libavformat)
|
||||||
|
# PKG_CHECK_MODULES(LIBSWSCALE libswscale)
|
||||||
|
# PKG_CHECK_MODULES(LIBAVUTIL libavutil)
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
|
FIND_PACKAGE(X11)
|
||||||
|
FIND_PACKAGE(Threads REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# #### End of additional libraries search ##########
|
||||||
|
|
||||||
|
|
||||||
|
### Configure Paths according to detected packages
|
||||||
|
if(TIFF_FOUND)
|
||||||
|
get_filename_component(TIFF_LIB_DIRS ${TIFF_LIBRARIES} PATH)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_TIFF_CCFLAGS}")
|
||||||
|
link_directories(${TIFF_LIB_DIRS})
|
||||||
|
include_directories(${TIFF_INCLUDE_DIR})
|
||||||
|
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${TIFF_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(JPEG_FOUND)
|
||||||
|
get_filename_component(JPEG_LIB_DIRS ${JPEG_LIBRARIES} PATH)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_JPEG_CCFLAGS}")
|
||||||
|
link_directories(${JPEG_LIB_DIRS})
|
||||||
|
include_directories(${JPEG_INCLUDE_DIR})
|
||||||
|
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${JPEG_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (ZLIB_FOUND)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_ZLIB_CCFLAGS}")
|
||||||
|
link_directories(${ZLIB_LIB_DIRS})
|
||||||
|
include_directories(${ZLIB_INCLUDE_DIR})
|
||||||
|
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
|
# PNG requires ZLIB
|
||||||
|
if(PNG_FOUND)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_PNG_CCFLAGS}")
|
||||||
|
link_directories(${PNG_LIB_DIRS})
|
||||||
|
include_directories(${PNG_INCLUDE_DIR} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${PNG_LIBRARIES} )
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(FFTW3_FOUND)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_FFTW3_CCFLAGS}")
|
||||||
|
link_directories( ${FFTW3_LIBRARY_DIRS} )
|
||||||
|
include_directories( ${FFTW3_INCLUDE_DIRS} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${FFTW3_LIBRARIES} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(OPENEXR_FOUND)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_OPENEXR_CCFLAGS}")
|
||||||
|
link_directories( ${OPENEXR_LIBRARY_DIRS} )
|
||||||
|
include_directories( ${OPENEXR_INCLUDE_DIRS} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${OPENEXR_LIBRARIES} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if(MAGICK_FOUND)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_MAGICK_CCFLAGS}")
|
||||||
|
link_directories( ${MAGICK_LIBRARY_DIRS} )
|
||||||
|
include_directories( ${MAGICK_INCLUDE_DIRS} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${MAGICK_LIBRARIES} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if( LIBAVCODEC_FOUND AND LIBAVFORMAT_FOUND AND LIBSWSCALE_FOUND AND LIBAVUTIL_FOUND )
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_FFMPEG_CCFLAGS}")
|
||||||
|
link_directories( ${LIBAVFORMAT_LIBRARY_DIRS} )
|
||||||
|
link_directories( ${LIBAVCODEC_LIBRARY_DIRS} )
|
||||||
|
link_directories( ${LIBSWSCALE_LIBRARY_DIRS} )
|
||||||
|
link_directories( ${LIBAVUTIL_LIBRARY_DIRS} )
|
||||||
|
include_directories( ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS}/libavformat)
|
||||||
|
include_directories( ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVCODEC_INCLUDE_DIRS}/libavcodec )
|
||||||
|
include_directories( ${LIBSWSCALE_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS}/libswscale)
|
||||||
|
include_directories( ${LIBAVUTIL_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS}/libavutil )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBAVFORMAT_LIBRARIES} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBAVCODEC_LIBRARIES} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBSWSCALE_LIBRARIES} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBAVUTIL_LIBRARIES} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if(NOT APPLE)
|
||||||
|
if(NOT WIN32)
|
||||||
|
if(X11_FOUND)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_XSHM_CCFLAGS} ${CIMG_XRANDR_CCFLAGS}")
|
||||||
|
SET(SYSTEM_LIBS ${SYSTEM_LIBS} Xext Xrandr)
|
||||||
|
endif()
|
||||||
|
endif(NOT WIN32)
|
||||||
|
endif(NOT APPLE)
|
||||||
|
|
||||||
|
if(X11_FOUND)
|
||||||
|
link_directories(${X11_LIB_DIRS})
|
||||||
|
include_directories(${X11_INCLUDE_DIR})
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${X11_LIBRARIES} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${CMAKE_THREAD_LIBS_INIT} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if( WIN32)
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} gdi32 )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (OpenCV_FOUND)
|
||||||
|
message("OpenCV Found")
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_OPENCV_CCFLAGS}")
|
||||||
|
include_directories(${OpenCV_INCLUDE_DIRS})
|
||||||
|
link_directories(${OpenCV_LIB_DIRS})
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${OpenCV_LIBS} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(LAPACK_FOUND)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_LAPACK_CCFLAGS}")
|
||||||
|
link_directories( ${LAPACK_LIBRARY_DIRS} )
|
||||||
|
include_directories( ${LAPACK_INCLUDE_DIRS} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${LAPACK_LIBRARIES} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BLAS_FOUND)
|
||||||
|
SET(CIMG_CFLAGS "${CIMG_CFLAGS} ${CIMG_BLAS_CCFLAGS}")
|
||||||
|
link_directories( ${BLAS_LIBRARY_DIRS} )
|
||||||
|
include_directories( ${BLAS_INCLUDE_DIRS} )
|
||||||
|
SET( SYSTEM_LIBS ${SYSTEM_LIBS} ${BLAS_LIBRARIES} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Add CIMG Flags to Compilation Flags
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CIMG_CFLAGS}")
|
||||||
|
|
||||||
|
|
||||||
|
SET(CIMG_FILES CImg_demo
|
||||||
|
captcha
|
||||||
|
curve_editor2d
|
||||||
|
dtmri_view3d
|
||||||
|
edge_explorer2d
|
||||||
|
fade_images
|
||||||
|
gaussian_fit1d
|
||||||
|
generate_loop_macros
|
||||||
|
hough_transform2d
|
||||||
|
image_registration2d
|
||||||
|
image2ascii
|
||||||
|
image_surface3d
|
||||||
|
jawbreaker
|
||||||
|
mcf_levelsets2d
|
||||||
|
mcf_levelsets3d
|
||||||
|
odykill
|
||||||
|
pde_heatflow2d
|
||||||
|
pde_TschumperleDeriche2d
|
||||||
|
plotter1d
|
||||||
|
radon_transform2d
|
||||||
|
scene3d
|
||||||
|
spherical_function3d
|
||||||
|
tetris
|
||||||
|
tron
|
||||||
|
tutorial
|
||||||
|
wavelet_atrous
|
||||||
|
use_draw_gradient
|
||||||
|
use_nlmeans
|
||||||
|
use_skeleton
|
||||||
|
use_RGBclass
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(program ${CIMG_FILES})
|
||||||
|
add_executable(${program} ${program}.cpp)
|
||||||
|
target_link_libraries(${program} ${SYSTEM_LIBS} )
|
||||||
|
endforeach(program)
|
609
examples/Makefile
Normal file
609
examples/Makefile
Normal file
|
@ -0,0 +1,609 @@
|
||||||
|
#
|
||||||
|
# File : Makefile
|
||||||
|
# ( Makefile for GNU 'make' utility )
|
||||||
|
#
|
||||||
|
# Description : Makefile for compiling CImg-based code on Unix.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
|
||||||
|
#-------------------------------------------------------
|
||||||
|
# Define the list of files to be compiled
|
||||||
|
# (name of the source files without the .cpp extension)
|
||||||
|
#-------------------------------------------------------
|
||||||
|
|
||||||
|
# Files which do not necessarily require external libraries to run.
|
||||||
|
FILES = CImg_demo \
|
||||||
|
captcha \
|
||||||
|
curve_editor2d \
|
||||||
|
dtmri_view3d \
|
||||||
|
edge_explorer2d \
|
||||||
|
fade_images \
|
||||||
|
gaussian_fit1d \
|
||||||
|
generate_loop_macros \
|
||||||
|
hough_transform2d \
|
||||||
|
image_registration2d \
|
||||||
|
image2ascii \
|
||||||
|
image_surface3d \
|
||||||
|
jawbreaker \
|
||||||
|
mcf_levelsets2d \
|
||||||
|
mcf_levelsets3d \
|
||||||
|
odykill \
|
||||||
|
pde_heatflow2d \
|
||||||
|
pde_TschumperleDeriche2d \
|
||||||
|
plotter1d \
|
||||||
|
radon_transform2d \
|
||||||
|
scene3d \
|
||||||
|
spherical_function3d \
|
||||||
|
tetris \
|
||||||
|
tron \
|
||||||
|
tutorial \
|
||||||
|
wavelet_atrous \
|
||||||
|
use_chlpca \
|
||||||
|
use_draw_gradient \
|
||||||
|
use_nlmeans \
|
||||||
|
use_skeleton \
|
||||||
|
use_RGBclass \
|
||||||
|
|
||||||
|
# Files which requires external libraries to run.
|
||||||
|
EXTRA_FILES = use_tiff_stream use_jpeg_buffer
|
||||||
|
|
||||||
|
#---------------------------------
|
||||||
|
# Set correct variables and paths
|
||||||
|
#---------------------------------
|
||||||
|
VERSION = $(shell grep 'cimg_version\ ' ../CImg.h | tail -c4 | head -c3)
|
||||||
|
VERSION1 = $(shell grep 'cimg_version\ ' ../CImg.h | tail -c4 | head -c1)
|
||||||
|
VERSION2 = $(shell grep 'cimg_version\ ' ../CImg.h | tail -c3 | head -c1)
|
||||||
|
VERSION3 = $(shell grep 'cimg_version\ ' ../CImg.h | tail -c2 | head -c1)
|
||||||
|
SVERSION = $(VERSION1).$(VERSION2).$(VERSION3)
|
||||||
|
|
||||||
|
X11PATH = /usr/X11R6
|
||||||
|
|
||||||
|
EXE_PRE =
|
||||||
|
EXE_EXT =
|
||||||
|
ifeq ($(MSYSTEM),MINGW32)
|
||||||
|
EXE_EXT = .exe
|
||||||
|
endif
|
||||||
|
ifeq ($(MSYSTEM),MINGW64)
|
||||||
|
EXE_EXT = .exe
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(shell echo $(notdir $(CXX)) | head -c3),g++)
|
||||||
|
IS_GCC = 1
|
||||||
|
endif
|
||||||
|
ifeq ($(shell echo $(notdir $(CXX)) | head -c7),clang++)
|
||||||
|
IS_CLANG = 1
|
||||||
|
endif
|
||||||
|
ifeq ($(shell echo $(notdir $(CXX)) | head -c4),icpc)
|
||||||
|
IS_ICPC = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
CXXVER = $(CXX)
|
||||||
|
CFLAGS = -I.. -Wall -Wextra -Wfatal-errors -Werror=unknown-pragmas -Werror=unused-label
|
||||||
|
LIBS = -lm
|
||||||
|
ifdef IS_GCC
|
||||||
|
CXXVER = $(shell $(CXX) -v 2>&1 | tail -n 1)
|
||||||
|
endif
|
||||||
|
ifdef IS_CLANG
|
||||||
|
CXXVER = $(shell $(CXX) -v 2>&1 | head -n 1)
|
||||||
|
endif
|
||||||
|
ifdef IS_ICPC
|
||||||
|
CXXVER = $(shell $(CXX) -v 2>&1)
|
||||||
|
CFLAGS = -I..
|
||||||
|
LIBS =
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef IS_GCC
|
||||||
|
GCC_VER_GTEQ5 = $(shell expr `$(CXX) -dumpversion | cut -f1 -d.` \>= 5)
|
||||||
|
ifeq ($(GCC_VER_GTEQ5),1)
|
||||||
|
CFLAGS += -Wshadow
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Set compilation flags allowing to customize CImg
|
||||||
|
#--------------------------------------------------
|
||||||
|
|
||||||
|
# Flags to enable strict code standards
|
||||||
|
ifeq ($(notdir $(CXX)),icpc)
|
||||||
|
ANSI_CFLAGS = -std=c++11
|
||||||
|
else
|
||||||
|
ANSI_CFLAGS = -std=c++11 -pedantic
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Flags to enable code debugging.
|
||||||
|
DEBUG_CFLAGS = -Dcimg_verbosity=3 -Dcimg_strict_warnings -g -fsanitize=address
|
||||||
|
|
||||||
|
# Flags to enable color output messages.
|
||||||
|
# (requires a VT100 compatible terminal)
|
||||||
|
VT100_CFLAGS = -Dcimg_use_vt100
|
||||||
|
|
||||||
|
# Flags to enable code optimization by the compiler.
|
||||||
|
OPT_CFLAGS = -Ofast
|
||||||
|
ifdef IS_GCC
|
||||||
|
OPT_CFLAGS = -Ofast -mtune=generic
|
||||||
|
endif
|
||||||
|
ifdef IS_ICPC
|
||||||
|
OPT_CFLAGS = -fast
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Flags to enable OpenMP support.
|
||||||
|
OPENMP_DEFINE = -Dcimg_use_openmp -fopenmp
|
||||||
|
OPENMP_INCDIR =
|
||||||
|
OPENMP_CFLAGS = $(OPENMP_DEFINE) $(OPENMP_INCDIR)
|
||||||
|
ifdef IS_ICPC
|
||||||
|
OPENMP_CFLAGS = #-Dcimg_use_openmp -openmp -i-static # -> Seems to bug the compiler!
|
||||||
|
endif
|
||||||
|
ifdef IS_CLANG
|
||||||
|
OPENMP_CFLAGS =
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Flags to enable OpenCV support.
|
||||||
|
OPENCV_DEFINE = -Dcimg_use_opencv
|
||||||
|
OPENCV_INCDIR = $(shell pkg-config opencv --cflags || echo -I/usr/include/opencv) -I/usr/include/opencv -I/usr/include/opencv4
|
||||||
|
OPENCV_CFLAGS = $(OPENCV_DEFINE) $(OPENCV_INCDIR)
|
||||||
|
OPENCV_LIBS = $(shell pkg-config opencv --libs || echo -lopencv_core -lopencv_highgui)
|
||||||
|
|
||||||
|
# Flags used to disable display capablities of CImg
|
||||||
|
NODISPLAY_CFLAGS = -Dcimg_display=0
|
||||||
|
|
||||||
|
# Flags to enable the use of the X11 library.
|
||||||
|
# (X11 is used by CImg to handle display windows)
|
||||||
|
X11_DEFINE = -Dcimg_display=1
|
||||||
|
X11_INCDIR = $(shell pkg-config --cflags x11 || echo -I/usr/X11R6/include)
|
||||||
|
X11_CFLAGS = $(X11_DEFINE) $(X11_INCDIR)
|
||||||
|
X11_LIBS = $(shell pkg-config --libs x11 || echo -L/usr/X11R6/lib -lX11) -lpthread
|
||||||
|
|
||||||
|
# Flags to enable fast image display, using the XSHM library (when using X11).
|
||||||
|
# !!! Seems to randomly crash when used on MacOS and 64bits systems, so use it only when necessary !!!
|
||||||
|
XSHM_CFLAGS = # -Dcimg_use_xshm $(shell pkg-config --cflags xcb-shm)
|
||||||
|
XSHM_LIBS = # $(shell pkg-config --libs xcb-shm || echo -L$(USR)/X11R6/lib -lXext)
|
||||||
|
|
||||||
|
# Flags to enable GDI32 display (Windows native).
|
||||||
|
GDI32_DEFINE = -mwindows
|
||||||
|
GDI32_INCDIR =
|
||||||
|
GDI32_CFLAGS = $(GDI32_DEFINE) $(GDI32_INCDIR)
|
||||||
|
GDI32_LIBS = -lgdi32
|
||||||
|
|
||||||
|
# Flags to enable screen mode switching, using the XRandr library (when using X11).
|
||||||
|
# ( http://www.x.org/wiki/Projects/XRandR )
|
||||||
|
# !!! Not supported by the X11 server on MacOS, so do not use it on MacOS !!!
|
||||||
|
XRANDR_DEFINE = -Dcimg_use_xrandr
|
||||||
|
XRANDR_INCDIR =
|
||||||
|
XRANDR_CFLAGS = $(XRANDR_DEFINE) $(XRANDR_INCDIR)
|
||||||
|
XRANDR_LIBS = -lXrandr
|
||||||
|
|
||||||
|
# Flags to enable native support for PNG image files, using the PNG library.
|
||||||
|
# ( http://www.libpng.org/ )
|
||||||
|
PNG_DEFINE = -Dcimg_use_png
|
||||||
|
PNG_INCDIR =
|
||||||
|
PNG_CFLAGS = $(PNG_DEFINE) $(PNG_INCDIR)
|
||||||
|
PNG_LIBS = -lpng -lz
|
||||||
|
|
||||||
|
# Flags to enable native support for JPEG image files, using the JPEG library.
|
||||||
|
# ( http://www.ijg.org/ )
|
||||||
|
JPEG_DEFINE = -Dcimg_use_jpeg
|
||||||
|
JPEG_INCDIR =
|
||||||
|
JPEG_CFLAGS = $(JPEG_DEFINE) $(JPEG_INCDIR)
|
||||||
|
JPEG_LIBS = -ljpeg
|
||||||
|
|
||||||
|
# Flags to enable native support for TIFF image files, using the TIFF library.
|
||||||
|
# ( http://www.libtiff.org/ )
|
||||||
|
TIFF_DEFINE = -Dcimg_use_tiff
|
||||||
|
TIFF_INCDIR =
|
||||||
|
TIFF_CFLAGS = $(TIFF_DEFINE) $(TIFF_INCDIR)
|
||||||
|
TIFF_LIBS = -ltiff
|
||||||
|
|
||||||
|
# Flags to enable native support for loading HEIF image files, using the libheif library.
|
||||||
|
# ( https://github.com/strukturag/libheif )
|
||||||
|
HEIF_DEFINE = -Dcimg_use_heif
|
||||||
|
HEIF_INCDIR =
|
||||||
|
HEIF_CFLAGS = $(HEIF_DEFINE) $(HEIF_INCDIR)
|
||||||
|
HEIF_LIBS = -lheif
|
||||||
|
|
||||||
|
# Flags to enable native support for MINC2 image files, using the MINC2 library.
|
||||||
|
# ( http://en.wikibooks.org/wiki/MINC/Reference/MINC2.0_Users_Guide )
|
||||||
|
MINC2_DEFINE = -Dcimg_use_minc2
|
||||||
|
MINC2_INCDIR = -I${HOME}/local/include
|
||||||
|
MINC2_CFLAGS = $(MINC2_DEFINE) $(MINC2_INCDIR)
|
||||||
|
MINC2_LIBS = -lminc_io -lvolume_io2 -lminc2 -lnetcdf -lhdf5 -lz -L${HOME}/local/lib
|
||||||
|
|
||||||
|
# Flags to enable native support for EXR image files, using the OpenEXR library.
|
||||||
|
# ( http://www.openexr.com/ )
|
||||||
|
OPENEXR_DEFINE = -Dcimg_use_openexr
|
||||||
|
OPENEXR_INCDIR = -I/usr/include/OpenEXR
|
||||||
|
OPENEXR_CFLAGS = $(OPENEXR_DEFINE) $(OPENEXR_INCDIR)
|
||||||
|
OPENEXR_LIBS = -lIlmImf -lHalf
|
||||||
|
|
||||||
|
# Flags to enable native support for various video files, using the FFMPEG library.
|
||||||
|
# ( http://www.ffmpeg.org/ )
|
||||||
|
FFMPEG_DEFINE = -Dcimg_use_ffmpeg -D__STDC_CONSTANT_MACROS
|
||||||
|
FFMPEG_INCDIR = -I/usr/include/libavcodec -I/usr/include/libavformat -I/usr/include/libswscale -I/usr/include/ffmpeg
|
||||||
|
FFMPEG_CFLAGS = $(FFMPEG_DEFINE) $(FFMPEG_INCDIR)
|
||||||
|
FFMPEG_LIBS = -lavcodec -lavformat -lswscale
|
||||||
|
|
||||||
|
# Flags to enable native support for compressed .cimgz files, using the Zlib library.
|
||||||
|
# ( http://www.zlib.net/ )
|
||||||
|
ZLIB_DEFINE = -Dcimg_use_zlib
|
||||||
|
ZLIB_INCDIR = $(shell pkg-config --cflags zlib || echo -I$(USR)/$(INCLUDE))
|
||||||
|
ZLIB_CFLAGS = $(ZLIB_DEFINE) $(ZLIB_INCDIR)
|
||||||
|
ZLIB_LIBS = $(shell pkg-config --libs zlib || echo -lz)
|
||||||
|
|
||||||
|
# Flags to enable native support for downloading files from the network.
|
||||||
|
# ( http://curl.haxx.se/libcurl/ )
|
||||||
|
CURL_DEFINE = -Dcimg_use_curl
|
||||||
|
CURL_INCDIR =
|
||||||
|
CURL_CFLAGS = $(CURL_DEFINE)
|
||||||
|
CURL_LIBS = -lcurl
|
||||||
|
|
||||||
|
# Flags to enable native support of most classical image file formats, using the Magick++ library.
|
||||||
|
# ( http://www.imagemagick.org/Magick++/ )
|
||||||
|
MAGICK_DEFINE = -Dcimg_use_magick
|
||||||
|
MAGICK_INCDIR = $(shell pkg-config --cflags GraphicsMagick++ || echo -I$(USR)/$(INCLUDE)/GraphicsMagick)
|
||||||
|
MAGICK_CFLAGS = $(MAGICK_DEFINE) $(MAGICK_INCDIR)
|
||||||
|
MAGICK_LIBS = $(shell pkg-config --libs GraphicsMagick++ || echo -lGraphicsMagick++)
|
||||||
|
|
||||||
|
# Flags to enable faster Discrete Fourier Transform computation, using the FFTW3 library
|
||||||
|
# ( http://www.fftw.org/ )
|
||||||
|
FFTW3_DEFINE = -Dcimg_use_fftw3
|
||||||
|
FFTW3_INCDIR =
|
||||||
|
FFTW3_CFLAGS = $(FFTW3_DEFINE) $(FFTW3_INCDIR)
|
||||||
|
ifeq ($(OSTYPE),msys)
|
||||||
|
FFTW3_LIBS = -lfftw3-3
|
||||||
|
else
|
||||||
|
FFTW3_LIBS = -lfftw3 -lfftw3_threads
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Flags to enable the use of LAPACK routines for matrix computation
|
||||||
|
# ( http://www.netlib.org/lapack/ )
|
||||||
|
LAPACK_DEFINE = -Dcimg_use_lapack
|
||||||
|
LAPACK_INCDIR =
|
||||||
|
LAPACK_CFLAGS = $(LAPACK_DEFINE) $(LAPACK_INCDIR)
|
||||||
|
LAPACK_LIBS = -lblas -llapack
|
||||||
|
|
||||||
|
# Flags to enable the use of the Board library
|
||||||
|
# ( https://github.com/c-koi/libboard )
|
||||||
|
BOARD_DEFINE = -Dcimg_use_board
|
||||||
|
BOARD_INCDIR = -I/usr/include/board
|
||||||
|
BOARD_CFLAGS = $(BOARD_DEFINE) $(BOARD_INCDIR)
|
||||||
|
BOARD_LIBS = -lboard
|
||||||
|
|
||||||
|
# Flags to compile GIMP plug-ins.
|
||||||
|
ifeq ($(MSYSTEM),MINGW32)
|
||||||
|
GIMP_CFLAGS = -mwindows
|
||||||
|
endif
|
||||||
|
|
||||||
|
#-------------------------
|
||||||
|
# Define Makefile entries
|
||||||
|
#-------------------------
|
||||||
|
.cpp:
|
||||||
|
@echo
|
||||||
|
@echo "** Compiling '$* ($(SVERSION))' with '$(CXXVER)'"
|
||||||
|
@echo
|
||||||
|
$(CXX) -o $(EXE_PRE)$*$(EXE_EXT) $< $(CFLAGS) $(CONF_CFLAGS) $(LIBS) $(CONF_LIBS)
|
||||||
|
ifeq ($(STRIP_EXE),true)
|
||||||
|
strip $(EXE_PRE)$*$(EXE_EXT)
|
||||||
|
endif
|
||||||
|
menu:
|
||||||
|
@echo
|
||||||
|
@echo "CImg Library $(SVERSION) : Examples"
|
||||||
|
@echo "-----------------------------"
|
||||||
|
@echo " > linux : Linux/BSD target, X11 display, optimizations disabled."
|
||||||
|
@echo " > dlinux : Linux/BSD target, X11 display, debug mode."
|
||||||
|
@echo " > olinux : Linux/BSD target, X11 display, optimizations enabled."
|
||||||
|
@echo " > mlinux : Linus/BSD target, no display, minimal features, optimizations enabled."
|
||||||
|
@echo " > Mlinux : Linux/BSD target, X11 display, maximal features, optimizations enabled."
|
||||||
|
@echo
|
||||||
|
@echo " > macos : MacOS target, X11 display, optimizations disabled."
|
||||||
|
@echo " > dmacos : MacOS target, X11 display, debug mode."
|
||||||
|
@echo " > omacos : MacOS target, X11 display, optimizations enabled."
|
||||||
|
@echo " > mmacos : MacOS target, no display, minimal features, optimizations enabled."
|
||||||
|
@echo " > Mmacos : MacOS target, X11 display, maximal features, optimizations enabled."
|
||||||
|
@echo
|
||||||
|
@echo " > windows : Windows target, GDI32 display, optimizations disabled."
|
||||||
|
@echo " > dwindows : Windows target, GDI32 display, debug mode."
|
||||||
|
@echo " > owindows : Windows target, GDI32 display, optimizations enabled."
|
||||||
|
@echo " > mwindows : Windows target, no display, minimal features, optimizations enabled."
|
||||||
|
@echo " > Mwindows : Windows target, GDI32 display, maximal features, optimizations enabled."
|
||||||
|
@echo
|
||||||
|
@echo " > clean : Clean generated files."
|
||||||
|
@echo
|
||||||
|
@echo "Choose your option :"
|
||||||
|
@read CHOICE; echo; $(MAKE) $$CHOICE; echo; echo "> Next time, you can bypass the menu by typing directly 'make $$CHOICE'"; echo;
|
||||||
|
|
||||||
|
all: $(FILES)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.exe *.o *.obj *~ \#* $(FILES) $(EXTRA_FILES)
|
||||||
|
ifneq ($(EXE_PRE),)
|
||||||
|
rm -f $(EXE_PRE)*
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Custom user-defined target
|
||||||
|
custom:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(TIFF_CFLAGS) \
|
||||||
|
$(HEIF_CFLAGS) \
|
||||||
|
$(X11_CFLAGS) \
|
||||||
|
$(LAPACK_CFLAGS) \
|
||||||
|
$(XSHM_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS) \
|
||||||
|
$(TIFF_LIBS) \
|
||||||
|
$(HEIF_LIBS) \
|
||||||
|
$(LAPACK_LIBS) \
|
||||||
|
$(XSHM_LIBS)" \
|
||||||
|
all $(EXTRA_FILES)
|
||||||
|
|
||||||
|
# Linux/BSD/Mac OSX targets, with X11 display.
|
||||||
|
|
||||||
|
#A target for Travis-CI
|
||||||
|
travis:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS) \
|
||||||
|
$(FFTW3_CFLAGS) \
|
||||||
|
$(PNG_CFLAGS) \
|
||||||
|
$(JPEG_CFLAGS) \
|
||||||
|
$(ZLIB_CFLAGS) \
|
||||||
|
$(CURL_CFLAGS) \
|
||||||
|
$(XSHM_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS) \
|
||||||
|
$(FFTW3_LIBS) \
|
||||||
|
$(PNG_LIBS) \
|
||||||
|
$(JPEG_LIBS) \
|
||||||
|
$(ZLIB_LIBS) \
|
||||||
|
$(CURL_LIBS) \
|
||||||
|
$(XSHM_LIBS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
linux:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS) \
|
||||||
|
$(XSHM_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS) \
|
||||||
|
$(XSHM_LIBS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
dlinux:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(DEBUG_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS) \
|
||||||
|
$(XSHM_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS) \
|
||||||
|
$(XSHM_LIBS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
olinux:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(OPT_CFLAGS) \
|
||||||
|
$(OPENMP_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS) \
|
||||||
|
$(XSHM_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS) \
|
||||||
|
$(XSHM_LIBS)" \
|
||||||
|
"STRIP_EXE=true" \
|
||||||
|
all
|
||||||
|
|
||||||
|
mlinux:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(NODISPLAY_CFLAGS) \
|
||||||
|
$(OPT_CFLAGS)" \
|
||||||
|
"STRIP_EXE=true" \
|
||||||
|
all
|
||||||
|
|
||||||
|
Mlinux:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(OPT_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS) \
|
||||||
|
$(XSHM_CFLAGS) \
|
||||||
|
$(XRANDR_CFLAGS) \
|
||||||
|
$(TIFF_CFLAGS) \
|
||||||
|
$(HEIF_CFLAGS) \
|
||||||
|
$(OPENEXR_CFLAGS) \
|
||||||
|
$(PNG_CFLAGS) \
|
||||||
|
$(JPEG_CFLAGS) \
|
||||||
|
$(ZLIB_CFLAGS) \
|
||||||
|
$(CURL_CFLAGS) \
|
||||||
|
$(OPENCV_CFLAGS) \
|
||||||
|
$(MAGICK_CFLAGS) \
|
||||||
|
$(FFTW3_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS) \
|
||||||
|
$(XSHM_LIBS) \
|
||||||
|
$(XRANDR_LIBS) \
|
||||||
|
$(TIFF_LIBS) -ltiffxx \
|
||||||
|
$(HEIF_LIBS) \
|
||||||
|
$(OPENEXR_LIBS) \
|
||||||
|
$(PNG_LIBS) \
|
||||||
|
$(JPEG_LIBS) \
|
||||||
|
$(ZLIB_LIBS) \
|
||||||
|
$(CURL_LIBS) \
|
||||||
|
$(OPENCV_LIBS) \
|
||||||
|
$(MAGICK_LIBS) \
|
||||||
|
$(FFTW3_LIBS)" \
|
||||||
|
"STRIP_EXE=true" \
|
||||||
|
all $(EXTRA_FILES)
|
||||||
|
|
||||||
|
# MacOs targets, with X11 display.
|
||||||
|
macos:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
dmacos:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(DEBUG_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
omacos:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(OPT_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
mmacos:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(ANSI_CFLAGS) \
|
||||||
|
$(NODISPLAY_CFLAGS) \
|
||||||
|
$(OPT_CFLAGS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
Mmacos:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(OPT_CFLAGS) \
|
||||||
|
$(VT100_CFLAGS) \
|
||||||
|
$(X11_CFLAGS) \
|
||||||
|
$(TIFF_CFLAGS) \
|
||||||
|
$(HEIF_CFLAGS) \
|
||||||
|
$(MINC2_CFLAGS) \
|
||||||
|
$(OPENEXR_CFLAGS) \
|
||||||
|
$(PNG_CFLAGS) \
|
||||||
|
$(JPEG_CFLAGS) \
|
||||||
|
$(ZLIB_CFLAGS) \
|
||||||
|
$(OPENCV_CFLAGS) \
|
||||||
|
$(MAGICK_CFLAGS) \
|
||||||
|
$(FFTW3_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(X11_LIBS) \
|
||||||
|
$(TIFF_LIBS) \
|
||||||
|
$(HEIF_LIBS) \
|
||||||
|
$(MINC2_LIBS) \
|
||||||
|
$(OPENEXR_LIBS) \
|
||||||
|
$(PNG_LIBS) \
|
||||||
|
$(JPEG_LIBS) \
|
||||||
|
$(ZLIB_LIBS) \
|
||||||
|
$(OPENCV_LIBS) \
|
||||||
|
$(MAGICK_LIBS) \
|
||||||
|
$(FFTW3_LIBS)" \
|
||||||
|
all $(EXTRA_FILES)
|
||||||
|
|
||||||
|
# Windows targets, with GDI32 display.
|
||||||
|
windows:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = " \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(GDI32_LIBS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
dwindows:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(DEBUG_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(GDI32_LIBS)" \
|
||||||
|
all
|
||||||
|
|
||||||
|
owindows:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(OPT_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(GDI32_LIBS)" \
|
||||||
|
"STRIP_EXE=true" \
|
||||||
|
all
|
||||||
|
|
||||||
|
mwindows:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(NODISPLAY_CFLAGS) \
|
||||||
|
$(OPT_CFLAGS)" \
|
||||||
|
"STRIP_EXE=true" \
|
||||||
|
all
|
||||||
|
|
||||||
|
Mwindows:
|
||||||
|
@$(MAKE) \
|
||||||
|
"CONF_CFLAGS = \
|
||||||
|
$(OPT_CFLAGS) \
|
||||||
|
$(TIFF_CFLAGS) \
|
||||||
|
$(HEIF_CFLAGS) \
|
||||||
|
$(PNG_CFLAGS) \
|
||||||
|
$(JPEG_CFLAGS) \
|
||||||
|
$(ZLIB_CFLAGS) \
|
||||||
|
$(OPENCV_CFLAGS) \
|
||||||
|
$(FFTW3_CFLAGS)" \
|
||||||
|
"CONF_LIBS = \
|
||||||
|
$(GDI32_LIBS) \
|
||||||
|
$(TIFF_LIBS) \
|
||||||
|
$(HEIF_LIBS) \
|
||||||
|
$(PNG_LIBS) \
|
||||||
|
$(JPEG_LIBS) \
|
||||||
|
$(ZLIB_LIBS) \
|
||||||
|
$(OPENCV_LIBS) \
|
||||||
|
$(FFTW3_LIBS)" \
|
||||||
|
"STRIP_EXE=true" \
|
||||||
|
all $(EXTRA_FILES)
|
||||||
|
|
||||||
|
# End of makefile
|
163
examples/captcha.cpp
Normal file
163
examples/captcha.cpp
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : captcha.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : Captcha images generator.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef cimg_debug
|
||||||
|
#define cimg_debug 1
|
||||||
|
#endif
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
// Main procedure
|
||||||
|
//----------------
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
|
||||||
|
// Read command line parameters
|
||||||
|
//------------------------------
|
||||||
|
cimg_usage("Simple captcha generator.");
|
||||||
|
const char *file_o = cimg_option("-o",(const char*)0,"Output image file");
|
||||||
|
const bool add_border = cimg_option("-b",true,"Add border to captcha image");
|
||||||
|
const bool visu = cimg_option("-visu",true,"Enable visualization if no output file");
|
||||||
|
|
||||||
|
// Generate captcha text (6 char max).
|
||||||
|
//------------------------------------
|
||||||
|
const char *predef_words[] = {
|
||||||
|
"aarrgh", "abacas", "abacus", "abakas", "abamps", "abased", "abaser", "abases", "abasia", "abated", "abater",
|
||||||
|
"abates", "abatis", "abator", "baobab", "barbal", "barbed", "barbel", "barber", "barbes", "barbet", "barbie",
|
||||||
|
"barbut", "barcas", "barded", "bardes", "bardic", "barege", "cavies", "cavils", "caving", "cavity", "cavort",
|
||||||
|
"cawing", "cayman", "cayuse", "ceased", "ceases", "cebids", "ceboid", "cecity", "cedarn", "dicast", "dicers",
|
||||||
|
"dicier", "dicing", "dicker", "dickey", "dickie", "dicots", "dictum", "didact", "diddle", "diddly", "didies",
|
||||||
|
"didoes", "emails", "embalm", "embank", "embark", "embars", "embays", "embeds", "embers", "emblem", "embody",
|
||||||
|
"emboli", "emboly", "embosk", "emboss", "fluffy", "fluids", "fluish", "fluked", "flukes", "flukey", "flumed",
|
||||||
|
"flumes", "flumps", "flunks", "flunky", "fluors", "flurry", "fluted", "genome", "genoms", "genres", "genros",
|
||||||
|
"gentes", "gentil", "gentle", "gently", "gentry", "geodes", "geodic", "geoids", "gerahs", "gerbil", "hotter",
|
||||||
|
"hottie", "houdah", "hounds", "houris", "hourly", "housed", "housel", "houser", "houses", "hovels", "hovers",
|
||||||
|
"howdah", "howdie", "inland", "inlays", "inlets", "inlier", "inmate", "inmesh", "inmost", "innage", "innate",
|
||||||
|
"inners", "inning", "inpour", "inputs", "inroad", "joypop", "jubbah", "jubhah", "jubile", "judder", "judged",
|
||||||
|
"judger", "judges", "judoka", "jugate", "jugful", "jugged", "juggle", "jugula", "knifer", "knifes", "knight",
|
||||||
|
"knives", "knobby", "knocks", "knolls", "knolly", "knosps", "knotty", "knouts", "knower", "knowns", "knubby",
|
||||||
|
"legate", "legato", "legend", "legers", "legged", "leggin", "legion", "legist", "legits", "legman", "legmen",
|
||||||
|
"legong", "legume", "lehuas", "mammal", "mammas", "mammee", "mammer", "mammet", "mammey", "mammie", "mammon",
|
||||||
|
"mamzer", "manage", "manana", "manats", "manche", "manege", "nihils", "nilgai", "nilgau", "nilled", "nimble",
|
||||||
|
"nimbly", "nimbus", "nimmed", "nimrod", "ninety", "ninjas", "ninons", "ninths", "niobic", "offish", "offkey",
|
||||||
|
"offset", "oftest", "ogdoad", "oghams", "ogival", "ogives", "oglers", "ogling", "ogress", "ogrish", "ogrism",
|
||||||
|
"ohmage", "papaws", "papaya", "papers", "papery", "pappus", "papula", "papule", "papyri", "parade", "paramo",
|
||||||
|
"parang", "paraph", "parcel", "pardah", "quasar", "quatre", "quaver", "qubits", "qubyte", "queans", "queasy",
|
||||||
|
"queazy", "queens", "queers", "quelea", "quells", "quench", "querns", "raised", "raiser", "raises", "raisin",
|
||||||
|
"raitas", "rajahs", "rakees", "rakers", "raking", "rakish", "rallye", "ralphs", "ramada", "ramate", "savory",
|
||||||
|
"savour", "savoys", "sawers", "sawfly", "sawing", "sawlog", "sawney", "sawyer", "saxony", "sayeds", "sayers",
|
||||||
|
"sayest", "sayids", "tondos", "toneme", "toners", "tongas", "tonged", "tonger", "tongue", "tonics", "tonier",
|
||||||
|
"toning", "tonish", "tonlet", "tonner", "tonnes", "uredia", "uredos", "ureide", "uremia", "uremic", "ureter",
|
||||||
|
"uretic", "urgent", "urgers", "urging", "urials", "urinal", "urines", "uropod", "villus", "vimina", "vinals",
|
||||||
|
"vincas", "vineal", "vinery", "vinier", "vinify", "vining", "vinous", "vinyls", "violas", "violet", "violin",
|
||||||
|
"webfed", "weblog", "wechts", "wedded", "wedder", "wedeln", "wedels", "wedged", "wedges", "wedgie", "weeded",
|
||||||
|
"weeder", "weekly", "weened", "xystoi", "xystos", "xystus", "yabber", "yabbie", "yachts", "yacked", "yaffed",
|
||||||
|
"yagers", "yahoos", "yairds", "yakked", "yakker", "yakuza", "zigged", "zigzag", "zillah", "zinced", "zincic",
|
||||||
|
"zincky", "zinebs", "zinged", "zinger", "zinnia", "zipped", "zipper", "zirams", "zircon" };
|
||||||
|
cimg::srand();
|
||||||
|
const char *const captcha_text = predef_words[std::rand()%(sizeof(predef_words)/sizeof(char*))];
|
||||||
|
|
||||||
|
// Create captcha image
|
||||||
|
//----------------------
|
||||||
|
|
||||||
|
// Write colored and distorted text
|
||||||
|
CImg<unsigned char> captcha(256,64,1,3,0), color(3);
|
||||||
|
char letter[2] = { 0 };
|
||||||
|
for (unsigned int k = 0; k<6; ++k) {
|
||||||
|
CImg<unsigned char> tmp;
|
||||||
|
*letter = captcha_text[k];
|
||||||
|
if (*letter) {
|
||||||
|
cimg_forX(color,i) color[i] = (unsigned char)(128 + (std::rand()%127));
|
||||||
|
tmp.draw_text((int)(2 + 8*cimg::rand()),
|
||||||
|
(int)(12*cimg::rand()),
|
||||||
|
letter,color.data(),0,1,std::rand()%2?38:57).resize(-100,-100,1,3);
|
||||||
|
const unsigned int dir = std::rand()%4, wph = tmp.width() + tmp.height();
|
||||||
|
cimg_forXYC(tmp,x,y,v) {
|
||||||
|
const int val = dir==0?x + y:(dir==1?x + tmp.height() - y:(dir==2?y + tmp.width() - x:
|
||||||
|
tmp.width() - x + tmp.height() - y));
|
||||||
|
tmp(x,y,v) = (unsigned char)std::max(0.0f,std::min(255.0f,1.5f*tmp(x,y,v)*val/wph));
|
||||||
|
}
|
||||||
|
if (std::rand()%2) tmp = (tmp.get_dilate(3)-=tmp);
|
||||||
|
tmp.blur((float)cimg::rand()*0.8f).normalize(0,255);
|
||||||
|
const float sin_offset = (float)cimg::rand(-1,1)*3, sin_freq = (float)cimg::rand(-1,1)/7;
|
||||||
|
cimg_forYC(captcha,y,v) captcha.get_shared_row(y,0,v).shift((int)(4*std::cos(y*sin_freq + sin_offset)));
|
||||||
|
captcha.draw_image(6 + 40*k,tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add geometric and random noise
|
||||||
|
CImg<unsigned char> copy = (+captcha).fill(0);
|
||||||
|
for (unsigned int l = 0; l<3; ++l) {
|
||||||
|
if (l) copy.blur(0.5f).normalize(0,148);
|
||||||
|
for (unsigned int k = 0; k<10; ++k) {
|
||||||
|
cimg_forX(color,i) color[i] = (unsigned char)(128 + cimg::rand()*127);
|
||||||
|
if (cimg::rand()<0.5f) copy.draw_circle((int)(cimg::rand()*captcha.width()),
|
||||||
|
(int)(cimg::rand()*captcha.height()),
|
||||||
|
(int)(cimg::rand()*30),
|
||||||
|
color.data(),0.6f,~0U);
|
||||||
|
else copy.draw_line((int)(cimg::rand()*captcha.width()),
|
||||||
|
(int)(cimg::rand()*captcha.height()),
|
||||||
|
(int)(cimg::rand()*captcha.width()),
|
||||||
|
(int)(cimg::rand()*captcha.height()),
|
||||||
|
color.data(),0.6f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
captcha|=copy;
|
||||||
|
captcha.noise(10,2);
|
||||||
|
|
||||||
|
if (add_border)
|
||||||
|
captcha.draw_rectangle(0,0,captcha.width() - 1,captcha.height() - 1,
|
||||||
|
CImg<unsigned char>::vector(255,255,255).data(),1.0f,~0U);
|
||||||
|
captcha = (+captcha).fill(255) - captcha;
|
||||||
|
|
||||||
|
// Write output image and captcha text
|
||||||
|
//-------------------------------------
|
||||||
|
std::printf("%s\n",captcha_text);
|
||||||
|
if (file_o) captcha.save(file_o);
|
||||||
|
else if (visu) {
|
||||||
|
CImgDisplay disp(CImg<unsigned char>(512,128,1,3,180).draw_image(128,32,captcha),captcha_text,0);
|
||||||
|
while (!disp.is_closed() && !disp.key()) { disp.wait(); if (disp.is_resized()) disp.resize(disp).wait(100); }
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
356
examples/curve_editor2d.cpp
Normal file
356
examples/curve_editor2d.cpp
Normal file
|
@ -0,0 +1,356 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : curve_editor2d.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : A simple user interface to construct 2D spline curves.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
# Antonio Albiol Colomer
|
||||||
|
# ( http://personales.upv.es/~aalbiol/index-english.html )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
// Compute distance from a point to a segment.
|
||||||
|
//---------------------------------------------
|
||||||
|
float dist_segment(const float x, const float y, const float x1, const float y1, const float x2, const float y2) {
|
||||||
|
const float
|
||||||
|
dx = x2 - x1,
|
||||||
|
dy = y2 - y1,
|
||||||
|
long_segment = (float)std::sqrt(dx*dx + dy*dy);
|
||||||
|
if (long_segment==0) { const float ddx = x - x1, ddy = y - y1; return (float)std::sqrt(ddx*ddx + ddy*ddy); }
|
||||||
|
const float
|
||||||
|
unitx = dx/long_segment,
|
||||||
|
unity = dy/long_segment,
|
||||||
|
vx = x - x1,
|
||||||
|
vy = y - y1,
|
||||||
|
long_proy = vx*unitx + vy*unity,
|
||||||
|
proyx = x1 + long_proy*unitx,
|
||||||
|
proyy = y1 + long_proy*unity;
|
||||||
|
if (long_proy>long_segment) { const float ddx = x - x2, ddy = y - y2; return std::sqrt(ddx*ddx + ddy*ddy); }
|
||||||
|
else if (long_proy<0) { const float ddx = x - x1, ddy = y - y1; return std::sqrt(ddx*ddx + ddy*ddy); }
|
||||||
|
const float ddx = x - proyx, ddy = y - proyy;
|
||||||
|
return std::sqrt(ddx*ddx + ddy*ddy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main procedure
|
||||||
|
//---------------
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
// Read command line parameters
|
||||||
|
//-----------------------------
|
||||||
|
cimg_usage("2D Spline Curve Editor");
|
||||||
|
const char *file_i = cimg_option("-i",(char*)0,"Input image");
|
||||||
|
const float contrast = cimg_option("-contrast",0.6f,"Image contrast");
|
||||||
|
const char *file_ip = cimg_option("-ip",(char*)0,"Input control points");
|
||||||
|
const char *file_oc = cimg_option("-oc",(char*)0,"Output curve points");
|
||||||
|
const char *file_op = cimg_option("-op",(char*)0,"Output control points");
|
||||||
|
const char *file_od = cimg_option("-od",(char*)0,"Output distance function");
|
||||||
|
bool interp = cimg_option("-poly",true,"Use polynomial interpolation");
|
||||||
|
bool closed = cimg_option("-closed",true,"Closed curve");
|
||||||
|
bool show_tangents = cimg_option("-tangents",false,"Show tangents");
|
||||||
|
bool show_points = cimg_option("-points",true,"Show control points");
|
||||||
|
bool show_outline = cimg_option("-outline",true,"Show polygon outline");
|
||||||
|
bool show_indices = cimg_option("-indices",true,"Show points indices");
|
||||||
|
bool show_coordinates = cimg_option("-coords",false,"Show points coordinates");
|
||||||
|
const float precision = cimg_option("-prec",0.05f,"Precision of curve discretization");
|
||||||
|
|
||||||
|
// Init image data
|
||||||
|
//-----------------
|
||||||
|
const unsigned char yellow[] = { 255,255,0 }, white[] = { 255,255,255 }, green[] = { 0,255,0 },
|
||||||
|
blue[] = { 120,200,255 }, purple[] = { 255,100,255 }, black[] = { 0,0,0 };
|
||||||
|
CImg<unsigned char> img0, img, help_img;
|
||||||
|
if (file_i) {
|
||||||
|
std::fprintf(stderr,"\n - Load input image '%s' : ",cimg::basename(file_i));
|
||||||
|
img0 = CImg<>(file_i).normalize(0,255.0f*contrast);
|
||||||
|
std::fprintf(stderr,"Size = %dx%dx%dx%d \n",img0.width(),img0.height(),img0.depth(),img0.spectrum());
|
||||||
|
img0.resize(-100,-100,1,3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::fprintf(stderr,"\n - No input image specified, use default 512x512 image.\n");
|
||||||
|
img0.assign(512,512,1,3,0).draw_grid(32,32,0,0,false,false,green,0.4f,0xCCCCCCCC,0xCCCCCCCC);
|
||||||
|
}
|
||||||
|
|
||||||
|
help_img.assign(220,210,1,3,0).
|
||||||
|
draw_text(5,5,
|
||||||
|
"------------------------------------------\n"
|
||||||
|
"2D Curve Editor\n"
|
||||||
|
"------------------------------------------\n"
|
||||||
|
"Left button : Create or move control point\n"
|
||||||
|
"Right button : Delete control point\n"
|
||||||
|
"Spacebar : Switch interpolation\n"
|
||||||
|
"Key 'C' : Switch open/closed mode\n"
|
||||||
|
"Key 'T' : Show/hide tangents\n"
|
||||||
|
"Key 'P' : Show/hide control points\n"
|
||||||
|
"Key 'O' : Show/hide polygon outline\n"
|
||||||
|
"Key 'N' : Show/hide points indices\n"
|
||||||
|
"Key 'X' : Show/hide points coordinates\n"
|
||||||
|
"Key 'H' : Show/hide this help\n"
|
||||||
|
"Key 'S' : Save control points\n"
|
||||||
|
"Key 'R' : Reset curve\n",
|
||||||
|
green);
|
||||||
|
CImgDisplay disp(img0,"2D Curve Editor",0);
|
||||||
|
CImgList<float> points, curve;
|
||||||
|
bool moving = false, help = !file_i;
|
||||||
|
|
||||||
|
if (file_ip) {
|
||||||
|
std::fprintf(stderr," - Load input control points '%s' : ",cimg::basename(file_ip));
|
||||||
|
points = CImg<>(file_ip).transpose()<'x';
|
||||||
|
std::fprintf(stderr," %u points\n",points.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter interactive loop
|
||||||
|
//------------------------
|
||||||
|
while (!disp.is_closed() && !disp.is_keyESC() && !disp.is_keyQ()) {
|
||||||
|
|
||||||
|
// Handle mouse manipulation
|
||||||
|
//---------------------------
|
||||||
|
const unsigned int button = disp.button();
|
||||||
|
const float
|
||||||
|
mx = disp.mouse_x()*(float)img0.width()/disp.width(),
|
||||||
|
my = disp.mouse_y()*(float)img0.height()/disp.height();
|
||||||
|
|
||||||
|
if (points && button && mx>=0 && my>=0) {
|
||||||
|
|
||||||
|
// Find nearest point and nearest segment
|
||||||
|
float dmin_pt = cimg::type<float>::max(), dmin_seg = dmin_pt;
|
||||||
|
unsigned int p_pt = 0, p_seg = 0;
|
||||||
|
cimglist_for(points,p) {
|
||||||
|
const unsigned int
|
||||||
|
pnext = closed?(p + 1)%points.size():(p + 1<(int)points.size()?p + 1:p);
|
||||||
|
const float
|
||||||
|
xp = points(p,0),
|
||||||
|
yp = points(p,1);
|
||||||
|
const float
|
||||||
|
d_pt = (xp - mx)*(xp - mx) + (yp - my)*(yp - my),
|
||||||
|
d_seg = dist_segment(mx,my,xp,yp,points(pnext,0),points(pnext,1));
|
||||||
|
if (d_pt<dmin_pt) { dmin_pt = d_pt; p_pt = p; }
|
||||||
|
if (d_seg<dmin_seg) { dmin_seg = d_seg; p_seg = p; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle button
|
||||||
|
if (button&1) {
|
||||||
|
if (dmin_pt<100 || moving) { points(p_pt,0) = mx; points(p_pt,1) = my; }
|
||||||
|
else points.insert(CImg<>::vector(mx,my),p_seg + 1);
|
||||||
|
moving = true;
|
||||||
|
}
|
||||||
|
if (button&2 && dmin_pt<100) {
|
||||||
|
if (points.size()>3) points.remove(p_pt);
|
||||||
|
disp.set_button();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!button) moving = false;
|
||||||
|
|
||||||
|
if (disp.key()) {
|
||||||
|
switch (disp.key()) {
|
||||||
|
case cimg::keySPACE : interp = !interp; break;
|
||||||
|
case cimg::keyC : closed = !closed; break;
|
||||||
|
case cimg::keyT : show_tangents = !show_tangents; break;
|
||||||
|
case cimg::keyP : show_points = !show_points; break;
|
||||||
|
case cimg::keyO : show_outline = !show_outline; break;
|
||||||
|
case cimg::keyN : show_indices = !show_indices; break;
|
||||||
|
case cimg::keyX : show_coordinates = !show_coordinates; break;
|
||||||
|
case cimg::keyR : points.assign(); break;
|
||||||
|
case cimg::keyH : help = !help; break;
|
||||||
|
case cimg::keyS : {
|
||||||
|
const char *filename = file_op?file_op:"curve_points.dlm";
|
||||||
|
std::fprintf(stderr," - Save control points in '%s'\n",filename);
|
||||||
|
(points>'x').transpose().save(filename);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
disp.set_key();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init list of points if empty
|
||||||
|
//------------------------------
|
||||||
|
if (!points) {
|
||||||
|
const float
|
||||||
|
x0 = img0.width()/4.0f,
|
||||||
|
y0 = img0.height()/4.0f,
|
||||||
|
x1 = img0.width() - x0,
|
||||||
|
y1 = img0.height() - y0;
|
||||||
|
points.insert(CImg<>::vector(x0,y0)).
|
||||||
|
insert(CImg<>::vector(x1,y0)).
|
||||||
|
insert(CImg<>::vector(x1,y1)).
|
||||||
|
insert(CImg<>::vector(x0,y1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Estimate curve tangents
|
||||||
|
//-------------------------
|
||||||
|
CImg<> tangents(points.size(),2);
|
||||||
|
cimglist_for(points,p) {
|
||||||
|
const unsigned int
|
||||||
|
p0 = closed?(p + points.size() - 1)%points.size():(p?p - 1:0),
|
||||||
|
p1 = closed?(p + 1)%points.size():(p + 1<(int)points.size()?p + 1:p);
|
||||||
|
const float
|
||||||
|
x = points(p,0),
|
||||||
|
y = points(p,1),
|
||||||
|
x0 = points(p0,0),
|
||||||
|
y0 = points(p0,1),
|
||||||
|
x1 = points(p1,0),
|
||||||
|
y1 = points(p1,1),
|
||||||
|
u0 = x - x0,
|
||||||
|
v0 = y - y0,
|
||||||
|
n0 = 1e-8f + (float)std::sqrt(u0*u0 + v0*v0),
|
||||||
|
u1 = x1 - x,
|
||||||
|
v1 = y1 - y,
|
||||||
|
n1 = 1e-8f + (float)std::sqrt(u1*u1 + v1*v1),
|
||||||
|
u = u0/n0 + u1/n1,
|
||||||
|
v = v0/n0 + v1/n1,
|
||||||
|
n = 1e-8f + (float)std::sqrt(u*u + v*v),
|
||||||
|
fact = 0.5f*(n0 + n1);
|
||||||
|
tangents(p,0) = fact*u/n;
|
||||||
|
tangents(p,1) = fact*v/n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Estimate 3th-order polynomial interpolation
|
||||||
|
//---------------------------------------------
|
||||||
|
curve.assign();
|
||||||
|
const unsigned int pmax = points.size() - (closed?0:1);
|
||||||
|
for (unsigned int p0 = 0; p0<pmax; p0++) {
|
||||||
|
const unsigned int
|
||||||
|
p1 = closed?(p0 + 1)%points.size():(p0 + 1<points.size()?p0 + 1:p0);
|
||||||
|
const float
|
||||||
|
x0 = points(p0,0),
|
||||||
|
y0 = points(p0,1),
|
||||||
|
x1 = points(p1,0),
|
||||||
|
y1 = points(p1,1);
|
||||||
|
float ax = 0, bx = 0, cx = 0, dx = 0, ay = 0, by = 0, cy = 0, dy = 0;
|
||||||
|
if (interp) {
|
||||||
|
const float
|
||||||
|
u0 = tangents(p0,0),
|
||||||
|
v0 = tangents(p0,1),
|
||||||
|
u1 = tangents(p1,0),
|
||||||
|
v1 = tangents(p1,1);
|
||||||
|
ax = 2*(x0 - x1) + u0 + u1;
|
||||||
|
bx = 3*(x1 - x0) - 2*u0 - u1;
|
||||||
|
cx = u0;
|
||||||
|
dx = x0;
|
||||||
|
ay = 2*(y0 - y1) + v0 + v1;
|
||||||
|
by = 3*(y1 - y0) - 2*v0 - v1;
|
||||||
|
cy = v0;
|
||||||
|
dy = y0;
|
||||||
|
} else {
|
||||||
|
ax = ay = bx = by = 0;
|
||||||
|
dx = x0;
|
||||||
|
dy = y0;
|
||||||
|
cx = x1 - x0;
|
||||||
|
cy = y1 - y0;
|
||||||
|
}
|
||||||
|
const float tmax = 1 + precision;
|
||||||
|
for (float t = 0; t<tmax; t+=precision) {
|
||||||
|
const float
|
||||||
|
xt = ax*t*t*t + bx*t*t + cx*t + dx,
|
||||||
|
yt = ay*t*t*t + by*t*t + cy*t + dy;
|
||||||
|
curve.insert(CImg<>::vector(xt,yt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw curve and display image
|
||||||
|
//-------------------------------
|
||||||
|
const float
|
||||||
|
factx = (float)disp.width()/img0.width(),
|
||||||
|
facty = (float)disp.height()/img0.height();
|
||||||
|
img = img0.get_resize(disp.width(),disp.height());
|
||||||
|
if (help) img.draw_image(help_img,0.6f);
|
||||||
|
if (interp && show_outline) {
|
||||||
|
CImg<> npoints = points>'x';
|
||||||
|
npoints.get_shared_row(0)*=factx;
|
||||||
|
npoints.get_shared_row(1)*=facty;
|
||||||
|
img.draw_polygon(npoints,blue,0.4f);
|
||||||
|
if (closed) img.draw_polygon(npoints,yellow,0.8f,0x11111111);
|
||||||
|
else img.draw_line(npoints,yellow,0.8f,0x11111111);
|
||||||
|
}
|
||||||
|
CImg<> ncurve = curve>'x';
|
||||||
|
ncurve.get_shared_row(0)*=factx;
|
||||||
|
ncurve.get_shared_row(1)*=facty;
|
||||||
|
if (closed) img.draw_polygon(ncurve,white,1.0f,~0U);
|
||||||
|
else img.draw_line(ncurve,white);
|
||||||
|
|
||||||
|
if (show_points) cimglist_for(points,p) {
|
||||||
|
const float
|
||||||
|
x = points(p,0)*factx,
|
||||||
|
y = points(p,1)*facty;
|
||||||
|
if (show_tangents) {
|
||||||
|
const float
|
||||||
|
u = tangents(p,0),
|
||||||
|
v = tangents(p,1),
|
||||||
|
n = 1e-8f + (float)std::sqrt(u*u + v*v),
|
||||||
|
nu = u/n,
|
||||||
|
nv = v/n;
|
||||||
|
img.draw_arrow((int)(x - 15*nu),(int)(y - 15*nv),(int)(x + 15*nu),(int)(y + 15*nv),green);
|
||||||
|
}
|
||||||
|
if (show_indices) img.draw_text((int)x,(int)(y - 16),"%d",purple,black,1,13,p);
|
||||||
|
if (show_coordinates)
|
||||||
|
img.draw_text((int)(x - 24),(int)(y + 8),"(%d,%d)",yellow,black,0.5f,13,(int)points(p,0),(int)points(p,1));
|
||||||
|
img.draw_circle((int)x,(int)y,3,blue,0.7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
img.display(disp);
|
||||||
|
disp.wait();
|
||||||
|
|
||||||
|
if (disp.is_resized()) disp.resize(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save output result and exit
|
||||||
|
//-----------------------------
|
||||||
|
if (file_op) {
|
||||||
|
std::fprintf(stderr," - Save control points in '%s'\n",cimg::basename(file_op));
|
||||||
|
(points>'x').transpose().save(file_op);
|
||||||
|
}
|
||||||
|
if (file_oc) {
|
||||||
|
std::fprintf(stderr," - Save curve points in '%s'\n",cimg::basename(file_oc));
|
||||||
|
(curve>'x').transpose().save(file_oc);
|
||||||
|
}
|
||||||
|
if (file_od) {
|
||||||
|
std::fprintf(stderr," - Computing distance function, please wait...."); std::fflush(stderr);
|
||||||
|
CImg<> ncurve = (closed?(+curve).insert(curve[0]):curve)>'x';
|
||||||
|
const float zero = 0.0f, one = 1.0f;
|
||||||
|
CImg<> distance =
|
||||||
|
CImg<>(img0.width(),img0.height(),1,1,-1.0f).draw_line(ncurve,&zero).draw_fill(0,0,&one).
|
||||||
|
distance(0);
|
||||||
|
std::fprintf(stderr,"\n - Save distance function in '%s'\n",cimg::basename(file_od));
|
||||||
|
distance.save(file_od);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fprintf(stderr," - Exit.\n");
|
||||||
|
std::exit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
563
examples/dtmri_view3d.cpp
Normal file
563
examples/dtmri_view3d.cpp
Normal file
|
@ -0,0 +1,563 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : dtmri_view3d.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : A viewer of Diffusion-Tensor MRI volumes (medical imaging).
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
// Compute fractional anisotropy (FA) of a tensor
|
||||||
|
//-------------------------------------------
|
||||||
|
template<typename T> float get_FA(const T& val1, const T& val2, const T& val3) {
|
||||||
|
const float
|
||||||
|
l1 = val1>0?val1:0, l2 = val2>0?val2:0, l3 = val3>0?val3:0,
|
||||||
|
lm = (l1 + l2 + l3)/3,
|
||||||
|
tr2 = 2*(l1*l1 + l2*l2 + l3*l3),
|
||||||
|
ll1 = l1 - lm,
|
||||||
|
ll2 = l2 - lm,
|
||||||
|
ll3 = l3 - lm;
|
||||||
|
if (tr2>0) return (float)std::sqrt(3*(ll1*ll1 + ll2*ll2 + ll3*ll3)/tr2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert an ellipsoid in a CImg 3D scene
|
||||||
|
//----------------------------------------
|
||||||
|
template<typename t, typename tp, typename tf, typename tc>
|
||||||
|
void insert_ellipsoid(const CImg<t>& tensor, const float X, const float Y, const float Z, const float tfact,
|
||||||
|
const float vx, const float vy, const float vz,
|
||||||
|
CImgList<tp>& points, CImgList<tf>& faces, CImgList<tc>& colors,
|
||||||
|
const unsigned int res1=20, const unsigned int res2=20) {
|
||||||
|
|
||||||
|
// Compute eigen elements
|
||||||
|
float l1 = tensor[0], l2 = tensor[1], l3 = tensor[2], fa = get_FA(l1,l2,l3);
|
||||||
|
CImg<> vec = CImg<>::matrix(tensor[3],tensor[6],tensor[9],
|
||||||
|
tensor[4],tensor[7],tensor[10],
|
||||||
|
tensor[5],tensor[8],tensor[11]);
|
||||||
|
const int
|
||||||
|
r = (int)std::min(30 + 1.5f*cimg::abs(255*fa*tensor[3]),255.0f),
|
||||||
|
g = (int)std::min(30 + 1.5f*cimg::abs(255*fa*tensor[4]),255.0f),
|
||||||
|
b = (int)std::min(30 + 1.5f*cimg::abs(255*fa*tensor[5]),255.0f);
|
||||||
|
|
||||||
|
// Define mesh points
|
||||||
|
const unsigned int N0 = points.size();
|
||||||
|
for (unsigned int v = 1; v<res2; v++)
|
||||||
|
for (unsigned int u = 0; u<res1; u++) {
|
||||||
|
const float
|
||||||
|
alpha = (float)(u*2*cimg::PI/res1),
|
||||||
|
beta = (float)(-cimg::PI/2 + v*cimg::PI/res2),
|
||||||
|
x = (float)(tfact*l1*std::cos(beta)*std::cos(alpha)),
|
||||||
|
y = (float)(tfact*l2*std::cos(beta)*std::sin(alpha)),
|
||||||
|
z = (float)(tfact*l3*std::sin(beta));
|
||||||
|
points.insert((CImg<tp>::vector(X,Y,Z) + vec*CImg<tp>::vector(x,y,z)).mul(CImg<tp>::vector(vx,vy,vz)));
|
||||||
|
}
|
||||||
|
const unsigned int N1 = points.size();
|
||||||
|
points.insert((CImg<tp>::vector(X,Y,Z) - vec*CImg<tp>::vector(0,0,l3*tfact)));
|
||||||
|
points.insert((CImg<tp>::vector(X,Y,Z) + vec*CImg<tp>::vector(0,0,l3*tfact)));
|
||||||
|
points[points.size() - 2](0)*=vx; points[points.size() - 2](1)*=vy; points[points.size() - 2](2)*=vz;
|
||||||
|
points[points.size() - 1](0)*=vx; points[points.size() - 1](1)*=vy; points[points.size() - 1](2)*=vz;
|
||||||
|
|
||||||
|
// Define mesh triangles
|
||||||
|
for (unsigned int vv = 0; vv<res2 - 2; ++vv)
|
||||||
|
for (unsigned int uu = 0; uu<res1; ++uu) {
|
||||||
|
const int nv = (vv + 1)%(res2 - 1), nu = (uu + 1)%res1;
|
||||||
|
faces.insert(CImg<tf>::vector(N0 + res1*vv + nu,N0 + res1*nv + uu,N0 + res1*vv + uu));
|
||||||
|
faces.insert(CImg<tf>::vector(N0 + res1*vv + nu,N0 + res1*nv + nu,N0 + res1*nv + uu));
|
||||||
|
colors.insert(CImg<tc>::vector((tc)r,(tc)g,(tc)b));
|
||||||
|
colors.insert(CImg<tc>::vector((tc)r,(tc)g,(tc)b));
|
||||||
|
}
|
||||||
|
for (unsigned int uu = 0; uu<res1; ++uu) {
|
||||||
|
const int nu = (uu + 1)%res1;
|
||||||
|
faces.insert(CImg<tf>::vector(N0 + nu,N0 + uu,N1));
|
||||||
|
faces.insert(CImg<tf>::vector(N0 + res1*(res2 - 2) + nu, N1 + 1,N0 + res1*(res2 - 2) + uu));
|
||||||
|
colors.insert(CImg<tc>::vector((tc)r,(tc)g,(tc)b));
|
||||||
|
colors.insert(CImg<tc>::vector((tc)r,(tc)g,(tc)b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert a fiber in a CImg 3D scene
|
||||||
|
//-----------------------------------
|
||||||
|
template<typename T,typename te,typename tp, typename tf, typename tc>
|
||||||
|
void insert_fiber(const CImg<T>& fiber, const CImg<te>& eigen, const CImg<tc>& palette,
|
||||||
|
const int xm, const int ym, const int zm,
|
||||||
|
const float vx, const float vy, const float vz,
|
||||||
|
CImgList<tp>& points, CImgList<tf>& primitives, CImgList<tc>& colors) {
|
||||||
|
const int N0 = points.size();
|
||||||
|
float x0 = fiber(0,0), y0 = fiber(0,1), z0 = fiber(0,2), fa0 = eigen.linear_atXYZ(x0,y0,z0,12);
|
||||||
|
points.insert(CImg<>::vector(vx*(x0 -xm),vy*(y0 - ym),vz*(z0 - zm)));
|
||||||
|
for (int l = 1; l<fiber.width(); ++l) {
|
||||||
|
float x1 = fiber(l,0), y1 = fiber(l,1), z1 = fiber(l,2), fa1 = eigen.linear_atXYZ(x1,y1,z1,12);
|
||||||
|
points.insert(CImg<tp>::vector(vx*(x1 - xm),vy*(y1 - ym),vz*(z1 - zm)));
|
||||||
|
primitives.insert(CImg<tf>::vector(N0 + l - 1,N0 + l));
|
||||||
|
const unsigned char
|
||||||
|
icol = (unsigned char)(fa0*255),
|
||||||
|
r = palette(icol,0),
|
||||||
|
g = palette(icol,1),
|
||||||
|
b = palette(icol,2);
|
||||||
|
colors.insert(CImg<unsigned char>::vector(r,g,b));
|
||||||
|
x0 = x1; y0 = y1; z0 = z1; fa0 = fa1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute fiber tracking using 4th-order Runge Kutta integration
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
template<typename T>
|
||||||
|
CImg<> get_fibertrack(CImg<T>& eigen,
|
||||||
|
const int X0, const int Y0, const int Z0, const float lmax=100,
|
||||||
|
const float dl=0.1f, const float FAmin=0.7f, const float cmin=0.5f) {
|
||||||
|
#define align_eigen(i,j,k) \
|
||||||
|
{ T &u = eigen(i,j,k,3), &v = eigen(i,j,k,4), &w = eigen(i,j,k,5); \
|
||||||
|
if (u*cu + v*cv + w*cw<0) { u=-u; v=-v; w=-w; }}
|
||||||
|
|
||||||
|
CImgList<> resf;
|
||||||
|
|
||||||
|
// Forward tracking
|
||||||
|
float normU = 0, normpU = 0, l = 0, X = (float)X0, Y = (float)Y0, Z = (float)Z0;
|
||||||
|
T
|
||||||
|
pu = eigen(X0,Y0,Z0,3),
|
||||||
|
pv = eigen(X0,Y0,Z0,4),
|
||||||
|
pw = eigen(X0,Y0,Z0,5);
|
||||||
|
normpU = (float)std::sqrt(pu*pu + pv*pv + pw*pw);
|
||||||
|
bool stopflag = false;
|
||||||
|
|
||||||
|
while (!stopflag) {
|
||||||
|
if (X<0 || X>eigen.width() - 1 || Y<0 || Y>eigen.height() - 1 || Z<0 || Z>eigen.depth() - 1 ||
|
||||||
|
eigen((int)X,(int)Y,(int)Z,12)<FAmin || l>lmax) stopflag = true;
|
||||||
|
else {
|
||||||
|
resf.insert(CImg<>::vector(X,Y,Z));
|
||||||
|
|
||||||
|
const int
|
||||||
|
cx = (int)X, px = (cx - 1<0)?0:cx - 1, nx = (cx + 1>=eigen.width())?eigen.width() - 1:cx + 1,
|
||||||
|
cy = (int)Y, py = (cy - 1<0)?0:cy - 1, ny = (cy + 1>=eigen.height())?eigen.height() - 1:cy + 1,
|
||||||
|
cz = (int)Z, pz = (cz - 1<0)?0:cz - 1, nz = (cz + 1>=eigen.depth())?eigen.depth() - 1:cz + 1;
|
||||||
|
const T cu = eigen(cx,cy,cz,3), cv = eigen(cx,cy,cz,4), cw = eigen(cx,cy,cz,5);
|
||||||
|
|
||||||
|
align_eigen(px,py,pz); align_eigen(cx,py,pz); align_eigen(nx,py,pz);
|
||||||
|
align_eigen(px,cy,pz); align_eigen(cx,cy,pz); align_eigen(nx,cy,pz);
|
||||||
|
align_eigen(px,ny,pz); align_eigen(cx,ny,pz); align_eigen(nx,ny,pz);
|
||||||
|
align_eigen(px,py,cz); align_eigen(cx,py,cz); align_eigen(nx,py,cz);
|
||||||
|
align_eigen(px,cy,cz); align_eigen(nx,cy,cz);
|
||||||
|
align_eigen(px,ny,cz); align_eigen(cx,ny,cz); align_eigen(nx,ny,cz);
|
||||||
|
align_eigen(px,py,nz); align_eigen(cx,py,nz); align_eigen(nx,py,nz);
|
||||||
|
align_eigen(px,cy,nz); align_eigen(cx,cy,nz); align_eigen(nx,cy,nz);
|
||||||
|
align_eigen(px,ny,nz); align_eigen(cx,ny,nz); align_eigen(nx,ny,nz);
|
||||||
|
|
||||||
|
const T
|
||||||
|
u0 = 0.5f*dl*eigen.linear_atXYZ(X,Y,Z,3),
|
||||||
|
v0 = 0.5f*dl*eigen.linear_atXYZ(X,Y,Z,4),
|
||||||
|
w0 = 0.5f*dl*eigen.linear_atXYZ(X,Y,Z,5),
|
||||||
|
u1 = 0.5f*dl*eigen.linear_atXYZ(X + u0,Y + v0,Z + w0,3),
|
||||||
|
v1 = 0.5f*dl*eigen.linear_atXYZ(X + u0,Y + v0,Z + w0,4),
|
||||||
|
w1 = 0.5f*dl*eigen.linear_atXYZ(X + u0,Y + v0,Z + w0,5),
|
||||||
|
u2 = 0.5f*dl*eigen.linear_atXYZ(X + u1,Y + v1,Z + w1,3),
|
||||||
|
v2 = 0.5f*dl*eigen.linear_atXYZ(X + u1,Y + v1,Z + w1,4),
|
||||||
|
w2 = 0.5f*dl*eigen.linear_atXYZ(X + u1,Y + v1,Z + w1,5),
|
||||||
|
u3 = 0.5f*dl*eigen.linear_atXYZ(X + u2,Y + v2,Z + w2,3),
|
||||||
|
v3 = 0.5f*dl*eigen.linear_atXYZ(X + u2,Y + v2,Z + w2,4),
|
||||||
|
w3 = 0.5f*dl*eigen.linear_atXYZ(X + u2,Y + v2,Z + w2,5);
|
||||||
|
T
|
||||||
|
u = u0/3 + 2*u1/3 + 2*u2/3 + u3/3,
|
||||||
|
v = v0/3 + 2*v1/3 + 2*v2/3 + v3/3,
|
||||||
|
w = w0/3 + 2*w1/3 + 2*w2/3 + w3/3;
|
||||||
|
if (u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; }
|
||||||
|
normU = (float)std::sqrt(u*u + v*v + w*w);
|
||||||
|
const float scal = (u*pu + v*pv + w*pw)/(normU*normpU);
|
||||||
|
if (scal<cmin) stopflag=true;
|
||||||
|
|
||||||
|
X+=(pu=u); Y+=(pv=v); Z+=(pw=w);
|
||||||
|
normpU = normU;
|
||||||
|
l+=dl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backward tracking
|
||||||
|
l = dl; X = (float)X0; Y = (float)Y0; Z = (float)Z0;
|
||||||
|
pu = eigen(X0,Y0,Z0,3);
|
||||||
|
pv = eigen(X0,Y0,Z0,4);
|
||||||
|
pw = eigen(X0,Y0,Z0,5);
|
||||||
|
normpU = (float)std::sqrt(pu*pu + pv*pv + pw*pw);
|
||||||
|
stopflag = false;
|
||||||
|
|
||||||
|
while (!stopflag) {
|
||||||
|
if (X<0 || X>eigen.width() - 1 || Y<0 || Y>eigen.height() - 1 || Z<0 || Z>eigen.depth() - 1 ||
|
||||||
|
eigen((int)X,(int)Y,(int)Z,12)<FAmin || l>lmax) stopflag = true;
|
||||||
|
else {
|
||||||
|
|
||||||
|
const int
|
||||||
|
cx = (int)X, px = (cx - 1<0)?0:cx - 1, nx = (cx + 1>=eigen.width())?eigen.width() - 1:cx + 1,
|
||||||
|
cy = (int)Y, py = (cy - 1<0)?0:cy - 1, ny = (cy + 1>=eigen.height())?eigen.height() - 1:cy + 1,
|
||||||
|
cz = (int)Z, pz = (cz - 1<0)?0:cz - 1, nz = (cz + 1>=eigen.depth())?eigen.depth() - 1:cz + 1;
|
||||||
|
const T cu = eigen(cx,cy,cz,3), cv = eigen(cx,cy,cz,4), cw = eigen(cx,cy,cz,5);
|
||||||
|
|
||||||
|
align_eigen(px,py,pz); align_eigen(cx,py,pz); align_eigen(nx,py,pz);
|
||||||
|
align_eigen(px,cy,pz); align_eigen(cx,cy,pz); align_eigen(nx,cy,pz);
|
||||||
|
align_eigen(px,ny,pz); align_eigen(cx,ny,pz); align_eigen(nx,ny,pz);
|
||||||
|
align_eigen(px,py,cz); align_eigen(cx,py,cz); align_eigen(nx,py,cz);
|
||||||
|
align_eigen(px,cy,cz); align_eigen(nx,cy,cz);
|
||||||
|
align_eigen(px,ny,cz); align_eigen(cx,ny,cz); align_eigen(nx,ny,cz);
|
||||||
|
align_eigen(px,py,nz); align_eigen(cx,py,nz); align_eigen(nx,py,nz);
|
||||||
|
align_eigen(px,cy,nz); align_eigen(cx,cy,nz); align_eigen(nx,cy,nz);
|
||||||
|
align_eigen(px,ny,nz); align_eigen(cx,ny,nz); align_eigen(nx,ny,nz);
|
||||||
|
|
||||||
|
const T
|
||||||
|
u0 = 0.5f*dl*eigen.linear_atXYZ(X,Y,Z,3),
|
||||||
|
v0 = 0.5f*dl*eigen.linear_atXYZ(X,Y,Z,4),
|
||||||
|
w0 = 0.5f*dl*eigen.linear_atXYZ(X,Y,Z,5),
|
||||||
|
u1 = 0.5f*dl*eigen.linear_atXYZ(X + u0,Y + v0,Z + w0,3),
|
||||||
|
v1 = 0.5f*dl*eigen.linear_atXYZ(X + u0,Y + v0,Z + w0,4),
|
||||||
|
w1 = 0.5f*dl*eigen.linear_atXYZ(X + u0,Y + v0,Z + w0,5),
|
||||||
|
u2 = 0.5f*dl*eigen.linear_atXYZ(X + u1,Y + v1,Z + w1,3),
|
||||||
|
v2 = 0.5f*dl*eigen.linear_atXYZ(X + u1,Y + v1,Z + w1,4),
|
||||||
|
w2 = 0.5f*dl*eigen.linear_atXYZ(X + u1,Y + v1,Z + w1,5),
|
||||||
|
u3 = 0.5f*dl*eigen.linear_atXYZ(X + u2,Y + v2,Z + w2,3),
|
||||||
|
v3 = 0.5f*dl*eigen.linear_atXYZ(X + u2,Y + v2,Z + w2,4),
|
||||||
|
w3 = 0.5f*dl*eigen.linear_atXYZ(X + u2,Y + v2,Z + w2,5);
|
||||||
|
T
|
||||||
|
u = u0/3 + 2*u1/3 + 2*u2/3 + u3/3,
|
||||||
|
v = v0/3 + 2*v1/3 + 2*v2/3 + v3/3,
|
||||||
|
w = w0/3 + 2*w1/3 + 2*w2/3 + w3/3;
|
||||||
|
if (u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; }
|
||||||
|
normU = (float)std::sqrt(u*u + v*v + w*w);
|
||||||
|
const float scal = (u*pu + v*pv + w*pw)/(normU*normpU);
|
||||||
|
if (scal<cmin) stopflag=true;
|
||||||
|
|
||||||
|
X-=(pu=u); Y-=(pv=v); Z-=(pw=w);
|
||||||
|
normpU=normU;
|
||||||
|
l+=dl;
|
||||||
|
|
||||||
|
resf.insert(CImg<>::vector(X,Y,Z),0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resf>'x';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main procedure
|
||||||
|
//----------------
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
|
||||||
|
// Read and init data
|
||||||
|
//--------------------
|
||||||
|
cimg_usage("A viewer of Diffusion-Tensor MRI volumes.");
|
||||||
|
const char *file_i = cimg_option("-i",(char*)0,"Input : Filename of tensor field (volume wxhxdx6)");
|
||||||
|
const char* vsize = cimg_option("-vsize","1x1x1","Input : Voxel aspect");
|
||||||
|
const bool normalize = cimg_option("-normalize",true,"Input : Enable tensor normalization");
|
||||||
|
const char *file_f = cimg_option("-f",(char*)0,"Input : Input fibers\n");
|
||||||
|
const float dl = cimg_option("-dl",0.5f,"Fiber computation : Integration step");
|
||||||
|
const float famin = cimg_option("-famin",0.3f,"Fiber computation : Fractional Anisotropy threshold");
|
||||||
|
const float cmin = cimg_option("-cmin",0.2f,"Fiber computation : Curvature threshold");
|
||||||
|
const float lmin = cimg_option("-lmin",10.0f,"Fiber computation : Minimum length\n");
|
||||||
|
const float lmax = cimg_option("-lmax",1000.0f,"Fiber computation : Maximum length\n");
|
||||||
|
const float tfact = cimg_option("-tfact",1.2f,"Display : Tensor size factor");
|
||||||
|
const char *bgcolor = cimg_option("-bg","0,0,0","Display : Background color");
|
||||||
|
unsigned int bgr = 0, bgg = 0, bgb = 0;
|
||||||
|
std::sscanf(bgcolor,"%u%*c%u%*c%u",&bgr,&bgg,&bgb);
|
||||||
|
|
||||||
|
CImg<> tensors;
|
||||||
|
if (file_i) {
|
||||||
|
std::fprintf(stderr,"\n- Loading tensors '%s'",cimg::basename(file_i));
|
||||||
|
tensors.load(file_i);
|
||||||
|
} else {
|
||||||
|
// Create a synthetic tensor field here
|
||||||
|
std::fprintf(stderr,"\n- No input files : Creating a synthetic tensor field");
|
||||||
|
tensors.assign(32,32,32,6);
|
||||||
|
cimg_forXYZ(tensors,x,y,z) {
|
||||||
|
const float
|
||||||
|
u = x - tensors.width()/2.0f,
|
||||||
|
v = y - tensors.height()/2.0f,
|
||||||
|
w = z - tensors.depth()/2.0f,
|
||||||
|
norm = (float)std::sqrt(1e-5f + u*u + v*v + w*w),
|
||||||
|
nu = u/norm, nv = v/norm, nw = w/norm;
|
||||||
|
const CImg<>
|
||||||
|
dir1 = CImg<>::vector(nu,nv,nw),
|
||||||
|
dir2 = CImg<>::vector(-nv,nu,nw),
|
||||||
|
dir3 = CImg<>::vector(nw*(nv - nu),-nw*(nu + nv),nu*nu + nv*nv);
|
||||||
|
tensors.set_tensor_at(2.0*dir1*dir1.get_transpose() +
|
||||||
|
1.0*dir2*dir2.get_transpose() +
|
||||||
|
0.7*dir3*dir3.get_transpose(),
|
||||||
|
x,y,z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float voxw = 1, voxh = 1, voxd = 1;
|
||||||
|
std::sscanf(vsize,"%f%*c%f%*c%f",&voxw,&voxh,&voxd);
|
||||||
|
|
||||||
|
std::fprintf(stderr," : %ux%ux%u image, voxsize=%gx%gx%g.",
|
||||||
|
tensors.width(),tensors.height(),tensors.depth(),
|
||||||
|
voxw,voxh,voxd);
|
||||||
|
|
||||||
|
CImgList<> fibers;
|
||||||
|
if (file_f) {
|
||||||
|
std::fprintf(stderr,"\n- Loading fibers '%s'.",cimg::basename(file_f));
|
||||||
|
fibers.load(file_f);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CImg<unsigned char> fiber_palette =
|
||||||
|
CImg<>(2,1,1,3).fill(200,255,0,255,0,200).RGBtoHSV().resize(256,1,1,3,3).HSVtoRGB();
|
||||||
|
|
||||||
|
// Compute eigen elements
|
||||||
|
//------------------------
|
||||||
|
std::fprintf(stderr,"\n- Compute eigen elements.");
|
||||||
|
CImg<unsigned char> coloredFA(tensors.width(),tensors.height(),tensors.depth(),3);
|
||||||
|
CImg<> eigen(tensors.width(),tensors.height(),tensors.depth(),13);
|
||||||
|
CImg<> val,vec;
|
||||||
|
float eigmax = 0;
|
||||||
|
cimg_forXYZ(tensors,x,y,z) {
|
||||||
|
tensors.get_tensor_at(x,y,z).symmetric_eigen(val,vec);
|
||||||
|
eigen(x,y,z,0) = val[0]; eigen(x,y,z,1) = val[1]; eigen(x,y,z,2) = val[2];
|
||||||
|
if (val[0]<0) val[0] = 0;
|
||||||
|
if (val[1]<0) val[1] = 0;
|
||||||
|
if (val[2]<0) val[2] = 0;
|
||||||
|
if (val[0]>eigmax) eigmax = val[0];
|
||||||
|
eigen(x,y,z,3) = vec(0,0); eigen(x,y,z,4) = vec(0,1); eigen(x,y,z,5) = vec(0,2);
|
||||||
|
eigen(x,y,z,6) = vec(1,0); eigen(x,y,z,7) = vec(1,1); eigen(x,y,z,8) = vec(1,2);
|
||||||
|
eigen(x,y,z,9) = vec(2,0); eigen(x,y,z,10) = vec(2,1); eigen(x,y,z,11) = vec(2,2);
|
||||||
|
const float fa = get_FA(val[0],val[1],val[2]);
|
||||||
|
eigen(x,y,z,12) = fa;
|
||||||
|
const int
|
||||||
|
r = (int)std::min(255.0f,1.5f*cimg::abs(255*fa*vec(0,0))),
|
||||||
|
g = (int)std::min(255.0f,1.5f*cimg::abs(255*fa*vec(0,1))),
|
||||||
|
b = (int)std::min(255.0f,1.5f*cimg::abs(255*fa*vec(0,2)));
|
||||||
|
coloredFA(x,y,z,0) = (unsigned char)r;
|
||||||
|
coloredFA(x,y,z,1) = (unsigned char)g;
|
||||||
|
coloredFA(x,y,z,2) = (unsigned char)b;
|
||||||
|
}
|
||||||
|
tensors.assign();
|
||||||
|
std::fprintf(stderr,"\n- Maximum diffusivity = %g, Maximum FA = %g",eigmax,eigen.get_shared_channel(12).max());
|
||||||
|
if (normalize) {
|
||||||
|
std::fprintf(stderr,"\n- Normalize tensors.");
|
||||||
|
eigen.get_shared_channels(0,2)/=eigmax;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init display and begin user interaction
|
||||||
|
//-----------------------------------------
|
||||||
|
std::fprintf(stderr,"\n- Open user window.");
|
||||||
|
CImgDisplay disp(256,256,"DTMRI Viewer",0);
|
||||||
|
CImgDisplay disp3d(800,600,"3D Local View",0,false,true);
|
||||||
|
unsigned int XYZ[3];
|
||||||
|
XYZ[0] = eigen.width()/2; XYZ[1] = eigen.height()/2; XYZ[2] = eigen.depth()/2;
|
||||||
|
|
||||||
|
while (!disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {
|
||||||
|
const CImg<int> s = coloredFA.get_select(disp,2,XYZ);
|
||||||
|
if (!disp.is_closed()) switch (disp.key()) {
|
||||||
|
|
||||||
|
// Open 3D visualization window
|
||||||
|
//-----------------------------
|
||||||
|
case cimg::keyA :
|
||||||
|
case 0 : {
|
||||||
|
const unsigned char white[] = { 255 };
|
||||||
|
disp3d.display(CImg<unsigned char>(disp3d.width(),disp3d.height(),1,1,0).
|
||||||
|
draw_text(10,10,"Please wait...",white)).show();
|
||||||
|
|
||||||
|
int xm, ym, zm, xM, yM, zM;
|
||||||
|
if (!disp.key()) { xm = s[0]; ym = s[1]; zm = s[2]; xM = s[3]; yM = s[4]; zM = s[5]; }
|
||||||
|
else { xm = ym = zm = 0; xM = eigen.width() - 1; yM = eigen.height() - 1; zM = eigen.height() - 1; }
|
||||||
|
const CImg<> img = eigen.get_crop(xm,ym,zm,xM,yM,zM);
|
||||||
|
CImgList<> points;
|
||||||
|
CImgList<unsigned int> primitives;
|
||||||
|
CImgList<unsigned char> colors;
|
||||||
|
|
||||||
|
// Add ellipsoids to the 3D scene
|
||||||
|
int X = img.width()/2, Y = img.height()/2, Z = img.depth()/2;
|
||||||
|
cimg_forXY(img,x,y)
|
||||||
|
insert_ellipsoid(img.get_vector_at(x,y,Z),(float)x,(float)y,(float)Z,
|
||||||
|
tfact,voxw,voxh,voxd,points,primitives,colors,10,6);
|
||||||
|
cimg_forXZ(img,x,z)
|
||||||
|
insert_ellipsoid(img.get_vector_at(x,Y,z),(float)x,(float)Y,(float)z,
|
||||||
|
tfact,voxw,voxh,voxd,points,primitives,colors,10,6);
|
||||||
|
cimg_forYZ(img,y,z)
|
||||||
|
insert_ellipsoid(img.get_vector_at(X,y,z),(float)X,(float)y,(float)z,
|
||||||
|
tfact,voxw,voxh,voxd,points,primitives,colors,10,6);
|
||||||
|
|
||||||
|
// Add computed fibers to the 3D scene
|
||||||
|
const CImg<> veigen = eigen.get_crop(xm,ym,zm,xM,yM,zM);
|
||||||
|
cimglist_for(fibers,l) {
|
||||||
|
const CImg<>& fiber = fibers[l];
|
||||||
|
if (fiber.width()) insert_fiber(fiber,eigen,fiber_palette,
|
||||||
|
xm,ym,zm,voxw,voxh,voxd,
|
||||||
|
points,primitives,colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display 3D object
|
||||||
|
CImg<unsigned char> visu = CImg<unsigned char>(3,disp3d.width(),disp3d.height(),1,0).
|
||||||
|
fill((unsigned char)bgr,(unsigned char)bgg,(unsigned char)bgb).
|
||||||
|
permute_axes("yzcx");
|
||||||
|
bool stopflag = false;
|
||||||
|
while (!disp3d.is_closed() && !stopflag) {
|
||||||
|
const CImg<> pts = points>'x';
|
||||||
|
visu.display_object3d(disp3d,pts,primitives,colors,true,4,-1,false,800,0.05f,1.0f);
|
||||||
|
disp3d.close();
|
||||||
|
switch (disp3d.key()) {
|
||||||
|
case cimg::keyM : { // Create movie
|
||||||
|
std::fprintf(stderr,"\n- Movie mode.\n");
|
||||||
|
const unsigned int N = 256;
|
||||||
|
CImg<> cpts(pts);
|
||||||
|
const CImg<> x = pts.get_shared_row(0), y = pts.get_shared_row(1), z = pts.get_shared_row(2);
|
||||||
|
float
|
||||||
|
_xm, _xM = x.max_min(_xm),
|
||||||
|
_ym, _yM = y.max_min(_ym),
|
||||||
|
_zm, _zM = z.max_min(_zm),
|
||||||
|
ratio = 2.0f*std::min(visu.width(),visu.height())/(3.0f*cimg::max(_xM - _xm,_yM - _ym,_zM - _zm)),
|
||||||
|
dx = 0.5f*(_xM + _xm), dy = 0.5f*(_yM + _ym), dz = 0.5f*(_zM + _zm);
|
||||||
|
cimg_forX(pts,l) {
|
||||||
|
cpts(l,0) = (pts(l,0) - dx)*ratio;
|
||||||
|
cpts(l,1) = (pts(l,1) - dy)*ratio;
|
||||||
|
cpts(l,2) = (pts(l,2) - dz)*ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<N; i++) {
|
||||||
|
std::fprintf(stderr,"\r- Frame %u/%u.",i,N);
|
||||||
|
const float alpha = (float)(i*360/N);
|
||||||
|
const CImg<> rpts = CImg<>::rotation_matrix(0,1,0,alpha)*CImg<>::rotation_matrix(1,0,0,75)*cpts;
|
||||||
|
visu.fill(0).draw_object3d(visu.width()/2.0f,visu.height()/2.0f,-500.0f,rpts,primitives,colors,
|
||||||
|
4,false,800.0f,visu.width()/2.0f,visu.height()/2.0f,-800.0f,0.05f,1.0f).
|
||||||
|
display(disp3d);
|
||||||
|
visu.save("frame.png",i);
|
||||||
|
}
|
||||||
|
visu.fill(0);
|
||||||
|
} break;
|
||||||
|
default: stopflag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (disp3d.is_fullscreen()) disp3d.toggle_fullscreen().resize(800,600).close();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// Compute region statistics
|
||||||
|
//---------------------------
|
||||||
|
case cimg::keyR : {
|
||||||
|
std::fprintf(stderr,"\n- Statistics computation. Select region."); std::fflush(stderr);
|
||||||
|
const CImg<int> sel = coloredFA.get_select(disp,2,XYZ);
|
||||||
|
int xm, ym, zm, xM, yM, zM;
|
||||||
|
if (!disp.key()) { xm = sel[0]; ym = sel[1]; zm = sel[2]; xM = sel[3]; yM = sel[4]; zM = sel[5]; }
|
||||||
|
else { xm = ym = zm = 0; xM = eigen.width() - 1; yM = eigen.height() - 1; zM = eigen.height() - 1; }
|
||||||
|
const CImg<> img = eigen.get_crop(xm,ym,zm,xM,yM,zM);
|
||||||
|
std::fprintf(stderr,"\n- Mean diffusivity = %g, Mean FA = %g\n",
|
||||||
|
eigen.get_shared_channel(0).mean(),
|
||||||
|
eigen.get_shared_channel(12).mean());
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// Track fiber bundle (single region)
|
||||||
|
//----------------------------------
|
||||||
|
case cimg::keyF : {
|
||||||
|
std::fprintf(stderr,"\n- Tracking mode (single region). Select starting region.\n"); std::fflush(stderr);
|
||||||
|
const CImg<int> sel = coloredFA.get_select(disp,2,XYZ);
|
||||||
|
const unsigned int N = fibers.size();
|
||||||
|
for (int z = sel[2]; z<=sel[5]; ++z)
|
||||||
|
for (int y = sel[1]; y<=sel[4]; ++y)
|
||||||
|
for (int x = sel[0]; x<=sel[3]; ++x) {
|
||||||
|
const CImg<> fiber = get_fibertrack(eigen,x,y,z,lmax,dl,famin,cmin);
|
||||||
|
if (fiber.width()>lmin) {
|
||||||
|
std::fprintf(stderr,"\rFiber %u : Starting from (%d,%d,%d)\t\t",fibers.size(),x,y,z);
|
||||||
|
fibers.insert(fiber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::fprintf(stderr,"\n- %u fiber(s) added (total %u).",fibers.size() - N,fibers.size());
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// Track fiber bundle (double regions)
|
||||||
|
//------------------------------------
|
||||||
|
case cimg::keyG : {
|
||||||
|
std::fprintf(stderr,"\n- Tracking mode (double region). Select starting region."); std::fflush(stderr);
|
||||||
|
const CImg<int> sel = coloredFA.get_select(disp,2,XYZ);
|
||||||
|
std::fprintf(stderr," Select ending region."); std::fflush(stderr);
|
||||||
|
const CImg<int> nsel = coloredFA.get_select(disp,2,XYZ);
|
||||||
|
const unsigned int N = fibers.size();
|
||||||
|
|
||||||
|
// Track from start to end
|
||||||
|
for (int z = sel[2]; z<=sel[5]; ++z)
|
||||||
|
for (int y = sel[1]; y<=sel[4]; ++y)
|
||||||
|
for (int x = sel[0]; x<=sel[3]; ++x) {
|
||||||
|
const CImg<> fiber = get_fibertrack(eigen,x,y,z,lmax,dl,famin,cmin);
|
||||||
|
if (fiber.width()>lmin) {
|
||||||
|
bool valid_fiber = false;
|
||||||
|
cimg_forX(fiber,k) {
|
||||||
|
const int fx = (int)fiber(k,0), fy = (int)fiber(k,1), fz = (int)fiber(k,2);
|
||||||
|
if (fx>=nsel[0] && fx<=nsel[3] &&
|
||||||
|
fy>=nsel[1] && fy<=nsel[4] &&
|
||||||
|
fz>=nsel[2] && fz<=nsel[5]) valid_fiber = true;
|
||||||
|
}
|
||||||
|
if (valid_fiber) fibers.insert(fiber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track from end to start
|
||||||
|
for (int z = nsel[2]; z<=nsel[5]; ++z)
|
||||||
|
for (int y = nsel[1]; y<=nsel[4]; ++y)
|
||||||
|
for (int x = nsel[0]; x<=nsel[3]; ++x) {
|
||||||
|
const CImg<> fiber = get_fibertrack(eigen,x,y,z,lmax,dl,famin,cmin);
|
||||||
|
if (fiber.width()>lmin) {
|
||||||
|
bool valid_fiber = false;
|
||||||
|
cimg_forX(fiber,k) {
|
||||||
|
const int fx = (int)fiber(k,0), fy = (int)fiber(k,1), fz = (int)fiber(k,2);
|
||||||
|
if (fx>=sel[0] && fx<=sel[3] &&
|
||||||
|
fy>=sel[1] && fy<=sel[4] &&
|
||||||
|
fz>=sel[2] && fz<=sel[5]) valid_fiber = true;
|
||||||
|
}
|
||||||
|
if (valid_fiber) {
|
||||||
|
std::fprintf(stderr,"\rFiber %u : Starting from (%d,%d,%d)\t\t",fibers.size(),x,y,z);
|
||||||
|
fibers.insert(fiber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fprintf(stderr," %u fiber(s) added (total %u).",fibers.size() - N,fibers.size());
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// Clear fiber bundle
|
||||||
|
//-------------------
|
||||||
|
case cimg::keyC : {
|
||||||
|
std::fprintf(stderr,"\n- Fibers removed.");
|
||||||
|
fibers.assign();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// Save fibers
|
||||||
|
//-------------
|
||||||
|
case cimg::keyS : {
|
||||||
|
fibers.save("fibers.cimg");
|
||||||
|
std::fprintf(stderr,"\n- Fibers saved.");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fprintf(stderr,"\n- Exit.\n\n\n");
|
||||||
|
return 0;
|
||||||
|
}
|
218
examples/edge_explorer2d.cpp
Normal file
218
examples/edge_explorer2d.cpp
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : edge_explorer2d.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : Real time edge detection while moving a ROI
|
||||||
|
# (rectangle of interest) over the original image.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : Orges Leka
|
||||||
|
# ( oleka(at)students.uni-mainz.de )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
#ifndef cimg_imagepath
|
||||||
|
#define cimg_imagepath "img/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Main procedure
|
||||||
|
//----------------
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
// Usage of the program displayed at the command line
|
||||||
|
cimg_usage("Real time edge detection with CImg. (c) Orges Leka");
|
||||||
|
|
||||||
|
// Read command line arguments
|
||||||
|
// With cimg_option we can get a new name for the image which is to be loaded from the command line.
|
||||||
|
const char* img_name = cimg_option("-i", cimg_imagepath "parrot.ppm","Input image.");
|
||||||
|
double
|
||||||
|
alpha = cimg_option("-a",1.0,"Blurring the gradient image."),
|
||||||
|
thresL = cimg_option("-tl",13.5,"Lower thresholding used in Hysteresis."),
|
||||||
|
thresH = cimg_option("-th",13.6,"Higher thresholding used in Hysteresis.");
|
||||||
|
const unsigned int
|
||||||
|
mode = cimg_option("-m",1,"Detection mode: 1 = Hysteresis, 2 = Gradient angle."),
|
||||||
|
factor = cimg_option("-s",80,"Half-size of edge-explorer window.");
|
||||||
|
|
||||||
|
cimg_help("\nAdditional notes : user can press following keys on main display window :\n"
|
||||||
|
" - Left arrow : Decrease alpha.\n"
|
||||||
|
" - Right arrow : Increase alpha.\n");
|
||||||
|
|
||||||
|
// Construct a new image called 'edge' of size (2*factor,2*factor)
|
||||||
|
// and of type 'unsigned char'.
|
||||||
|
CImg<unsigned char> edge(2*factor,2*factor);
|
||||||
|
CImgDisplay disp_edge(512,512,"Edge Explorer");
|
||||||
|
|
||||||
|
// Load the image with the name 'img_name' into the CImg 'img'.
|
||||||
|
// and create a display window 'disp' for the image 'img'.
|
||||||
|
const CImg<unsigned char> img = CImg<float>::get_load(img_name).norm().normalize(0,255);
|
||||||
|
CImgDisplay disp(img,"Original Image");
|
||||||
|
|
||||||
|
// Begin main interaction loop.
|
||||||
|
int x = 0, y = 0;
|
||||||
|
bool redraw = false;
|
||||||
|
while (!disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {
|
||||||
|
disp.wait(100);
|
||||||
|
if (disp.button()&1) { alpha+=0.05; redraw = true; }
|
||||||
|
if (disp.button()&2) { alpha-=0.05; redraw = true; }
|
||||||
|
if (disp.wheel()) { alpha+=0.05*disp.wheel(); disp.set_wheel(); redraw = true; }
|
||||||
|
if (alpha<0) alpha = 0;
|
||||||
|
if (disp_edge.is_resized()) { disp_edge.resize(); redraw = true; }
|
||||||
|
if (disp_edge.is_closed()) disp_edge.show();
|
||||||
|
if (disp.is_resized()) disp.resize(disp);
|
||||||
|
if (disp.mouse_x()>=0) {
|
||||||
|
x = disp.mouse_x(); // Getting the current position of the mouse
|
||||||
|
y = disp.mouse_y(); //
|
||||||
|
redraw = true; // The image should be redrawn
|
||||||
|
}
|
||||||
|
if (redraw) {
|
||||||
|
disp_edge.set_title("Edge explorer (alpha=%g)",alpha);
|
||||||
|
const int
|
||||||
|
x0 = x - factor, y0 = y - factor, // These are the coordinates for the red rectangle
|
||||||
|
x1 = x + factor, y1 = y + factor; // to be drawn on the original image
|
||||||
|
const unsigned char
|
||||||
|
red[3] = { 255,0,0 }, //
|
||||||
|
black[3] = { 0,0,0 }; // Defining the colors we need for drawing
|
||||||
|
|
||||||
|
(+img).draw_rectangle(x0,y0,x1,y1,red,1.0f,0x55555555U).display(disp);
|
||||||
|
//^ We draw the red rectangle on the original window using 'draw_line'.
|
||||||
|
// Then we display the result via '.display(disp)' .
|
||||||
|
// Observe, that the color 'red' has to be of type 'const unsigned char',
|
||||||
|
// since the image 'img' is of type 'const CImg<unsigned char>'.
|
||||||
|
|
||||||
|
//'normalize' is used to get a greyscaled image.
|
||||||
|
CImg<> visu_bw = CImg<>(img).get_crop(x0,y0,x1,y1).get_norm().normalize(0,255).resize(-100,-100,1,2,2);
|
||||||
|
// get_crop(x0,y0,x1,y1) gets the rectangle we are interested in.
|
||||||
|
|
||||||
|
edge.fill(255); // Background color in the edge-detection window is white
|
||||||
|
|
||||||
|
// grad[0] is the gradient image of 'visu_bw' in x-direction.
|
||||||
|
// grad[1] is the gradient image of 'visu_bw' in y-direction.
|
||||||
|
CImgList<> grad(visu_bw.blur((float)alpha).normalize(0,255).get_gradient());
|
||||||
|
|
||||||
|
// To avoid unnecessary calculations in the image loops:
|
||||||
|
const double
|
||||||
|
pi = cimg::PI,
|
||||||
|
p8 = pi/8.0, p38 = 3.0*p8,
|
||||||
|
p58 = 5.0*p8, p78 = 7.0*p8;
|
||||||
|
|
||||||
|
cimg_forXY(visu_bw,s,t) {
|
||||||
|
// We take s,t instead of x,y, since x,y are already used.
|
||||||
|
// s corresponds to the x-ordinate of the pixel while t corresponds to the y-ordinate.
|
||||||
|
if ( 1 <= s && s <= visu_bw.width() - 1 && 1 <= t && t <=visu_bw.height() - 1) { // if - good points
|
||||||
|
double
|
||||||
|
Gs = grad[0](s,t), //
|
||||||
|
Gt = grad[1](s,t), // The actual pixel is (s,t)
|
||||||
|
Gst = cimg::abs(Gs) + cimg::abs(Gt), //
|
||||||
|
// ^-- For efficient computation we observe that |Gs|+ |Gt| ~=~ sqrt( Gs^2 + Gt^2)
|
||||||
|
Gr, Gur, Gu, Gul, Gl, Gdl, Gd, Gdr;
|
||||||
|
// ^-- right, up right, up, up left, left, down left, down, down right.
|
||||||
|
double theta = std::atan2(std::max(1e-8,Gt),Gs) + pi; // theta is from the interval [0,Pi]
|
||||||
|
switch(mode) {
|
||||||
|
case 1: // Hysterese is applied
|
||||||
|
if (Gst>=thresH) { edge.draw_point(s,t,black); }
|
||||||
|
else if (thresL <= Gst && Gst < thresH) {
|
||||||
|
// Neighbourhood of the actual pixel:
|
||||||
|
Gr = cimg::abs(grad[0](s + 1,t)) + cimg::abs(grad[1](s + 1,t)); // right
|
||||||
|
Gl = cimg::abs(grad[0](s - 1,t)) + cimg::abs(grad[1](s - 1,t)); // left
|
||||||
|
Gur = cimg::abs(grad[0](s + 1,t + 1)) + cimg::abs(grad[1](s + 1,t + 1)); // up right
|
||||||
|
Gdl = cimg::abs(grad[0](s - 1,t - 1)) + cimg::abs(grad[1](s - 1,t - 1)); // down left
|
||||||
|
Gu = cimg::abs(grad[0](s,t + 1)) + cimg::abs(grad[1](s,t + 1)); // up
|
||||||
|
Gd = cimg::abs(grad[0](s,t - 1)) + cimg::abs(grad[1](s,t - 1)); // down
|
||||||
|
Gul = cimg::abs(grad[0](s - 1,t + 1)) + cimg::abs(grad[1](s - 1,t + 1)); // up left
|
||||||
|
Gdr = cimg::abs(grad[0](s + 1,t - 1)) + cimg::abs(grad[1](s + 1,t - 1)); // down right
|
||||||
|
if (Gr>=thresH || Gur>=thresH || Gu>=thresH || Gul>=thresH
|
||||||
|
|| Gl>=thresH || Gdl >=thresH || Gu >=thresH || Gdr >=thresH) {
|
||||||
|
edge.draw_point(s,t,black);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 2: // Angle 'theta' of the gradient (Gs,Gt) at the point (s,t)
|
||||||
|
if(theta >= pi)theta-=pi;
|
||||||
|
//rounding theta:
|
||||||
|
if ((p8 < theta && theta <= p38 ) || (p78 < theta && theta <= pi)) {
|
||||||
|
// See (*) below for explanation of the vocabulary used.
|
||||||
|
// Direction-pixel is (s + 1,t) with corresponding gradient value Gr.
|
||||||
|
Gr = cimg::abs(grad[0](s + 1,t)) + cimg::abs(grad[1](s + 1,t)); // right
|
||||||
|
// Contra-direction-pixel is (s - 1,t) with corresponding gradient value Gl.
|
||||||
|
Gl = cimg::abs(grad[0](s - 1,t)) + cimg::abs(grad[1](s - 1,t)); // left
|
||||||
|
if (Gr < Gst && Gl < Gst) {
|
||||||
|
edge.draw_point(s,t,black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( p8 < theta && theta <= p38) {
|
||||||
|
// Direction-pixel is (s + 1,t + 1) with corresponding gradient value Gur.
|
||||||
|
Gur = cimg::abs(grad[0](s + 1,t + 1)) + cimg::abs(grad[1](s + 1,t + 1)); // up right
|
||||||
|
// Contra-direction-pixel is (s-1,t-1) with corresponding gradient value Gdl.
|
||||||
|
Gdl = cimg::abs(grad[0](s - 1,t - 1)) + cimg::abs(grad[1](s - 1,t - 1)); // down left
|
||||||
|
if (Gur < Gst && Gdl < Gst) {
|
||||||
|
edge.draw_point(s,t,black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( p38 < theta && theta <= p58) {
|
||||||
|
// Direction-pixel is (s,t + 1) with corresponding gradient value Gu.
|
||||||
|
Gu = cimg::abs(grad[0](s,t + 1)) + cimg::abs(grad[1](s,t + 1)); // up
|
||||||
|
// Contra-direction-pixel is (s,t - 1) with corresponding gradient value Gd.
|
||||||
|
Gd = cimg::abs(grad[0](s,t - 1)) + cimg::abs(grad[1](s,t - 1)); // down
|
||||||
|
if (Gu < Gst && Gd < Gst) {
|
||||||
|
edge.draw_point(s,t,black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p58 < theta && theta <= p78) {
|
||||||
|
// Direction-pixel is (s - 1,t + 1) with corresponding gradient value Gul.
|
||||||
|
Gul = cimg::abs(grad[0](s - 1,t + 1)) + cimg::abs(grad[1](s - 1,t + 1)); // up left
|
||||||
|
// Contra-direction-pixel is (s + 1,t - 1) with corresponding gradient value Gdr.
|
||||||
|
Gdr = cimg::abs(grad[0](s + 1,t - 1)) + cimg::abs(grad[1](s + 1,t - 1)); // down right
|
||||||
|
if (Gul < Gst && Gdr < Gst) {
|
||||||
|
edge.draw_point(s,t,black);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
} // if good-points
|
||||||
|
} // cimg_forXY */
|
||||||
|
edge.display(disp_edge);
|
||||||
|
}// if redraw
|
||||||
|
} // while
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (*) Comments to the vocabulary used:
|
||||||
|
// If (s,t) is the current pixel, and G=(Gs,Gt) is the gradient at (s,t),
|
||||||
|
// then the _direction_pixel_ of (s,t) shall be the one of the eight neighbour pixels
|
||||||
|
// of (s,t) in whose direction the gradient G shows.
|
||||||
|
// The _contra_direction_pixel is the pixel in the opposite direction in which the gradient G shows.
|
||||||
|
// The _corresponding_gradient_value_ of the pixel (x,y) with gradient G = (Gx,Gy)
|
||||||
|
// shall be |Gx| + |Gy| ~=~ sqrt(Gx^2 + Gy^2).
|
94
examples/fade_images.cpp
Normal file
94
examples/fade_images.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : fade_images.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : Compute a linear fading between two images.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CImg.h"
|
||||||
|
#ifndef cimg_imagepath
|
||||||
|
#define cimg_imagepath "img/"
|
||||||
|
#endif
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
// Main procedure
|
||||||
|
//---------------
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
|
||||||
|
// Read and check command line parameters.
|
||||||
|
cimg_usage("Compute a linear fading between two 2D images");
|
||||||
|
const char *file_i1 = cimg_option("-i1",cimg_imagepath "sh0r.pgm","Input Image 1");
|
||||||
|
const char *file_i2 = cimg_option("-i2",cimg_imagepath "milla.bmp","Input Image 2");
|
||||||
|
const char *file_o = cimg_option("-o",(char*)0,"Output Image");
|
||||||
|
const bool visu = cimg_option("-visu",true,"Visualization mode");
|
||||||
|
const double pmin = cimg_option("-min",40.0,"Begin of the fade (in %)")/100.0;
|
||||||
|
const double pmax = cimg_option("-max",60.0,"End of the fade (in %)")/100.0;
|
||||||
|
const double angle = cimg_option("-angle",0.0,"Fade angle")*cil::cimg::PI/180;
|
||||||
|
|
||||||
|
// Init images.
|
||||||
|
cil::CImg<unsigned char> img1(file_i1), img2(file_i2);
|
||||||
|
if (!img2.is_sameXYZC(img1)) {
|
||||||
|
int
|
||||||
|
dx = std::max(img1.width(),img2.width()),
|
||||||
|
dy = std::max(img1.height(),img2.height()),
|
||||||
|
dz = std::max(img1.depth(),img2.depth()),
|
||||||
|
dv = std::max(img1.spectrum(),img2.spectrum());
|
||||||
|
img1.resize(dx,dy,dz,dv,3);
|
||||||
|
img2.resize(dx,dy,dz,dv,3);
|
||||||
|
}
|
||||||
|
cil::CImg<unsigned char> dest(img1);
|
||||||
|
|
||||||
|
// Compute the faded image.
|
||||||
|
const double ca = std::cos(angle), sa = std::sin(angle);
|
||||||
|
double alpha;
|
||||||
|
cimg_forXYZC(dest,x,y,z,k) {
|
||||||
|
const double X = ((double)x/img1.width() - 0.5)*ca + ((double)y/img1.height() - 0.5)*sa;
|
||||||
|
if (X + 0.5<pmin) alpha = 0; else {
|
||||||
|
if (X + 0.5>pmax) alpha = 1; else
|
||||||
|
alpha = (X + 0.5 - pmin)/(pmax - pmin);
|
||||||
|
}
|
||||||
|
dest(x,y,z,k) = (unsigned char)((1 - alpha)*img1(x,y,z,k) + alpha*img2(x,y,z,k));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save and exit
|
||||||
|
if (file_o) dest.save(file_o);
|
||||||
|
if (visu) dest.display("Image fading");
|
||||||
|
return 0;
|
||||||
|
}
|
172
examples/gaussian_fit1d.cpp
Normal file
172
examples/gaussian_fit1d.cpp
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : gaussian_fit1d.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : Fit a gaussian function on a set of sample points,
|
||||||
|
# using the Levenberg-Marquardt algorithm.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef cimg_plugin
|
||||||
|
#define cimg_plugin "examples/gaussian_fit1d.cpp"
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
// Main procedure
|
||||||
|
//----------------
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
cimg_usage("Fit gaussian function on sample points, using Levenberg-Marquardt algorithm.");
|
||||||
|
|
||||||
|
// Read command line arguments.
|
||||||
|
const char *s_params = cimg_option("-p","10,3,4","Amplitude, Mean and Std of the ground truth");
|
||||||
|
const unsigned int s_nb = cimg_option("-N",40,"Number of sample points");
|
||||||
|
const float s_noise = cimg_option("-n",10.0f,"Pourcentage of noise on the samples points");
|
||||||
|
const char *s_xrange = cimg_option("-x","-10,10","X-range allowed for the sample points");
|
||||||
|
const char *f_params = cimg_option("-p0",(char*)0,"Amplitude, Mean and Std of the first estimate");
|
||||||
|
const float f_lambda0 = cimg_option("-l",100.0f,"Initial damping factor");
|
||||||
|
const float f_dlambda = cimg_option("-dl",0.9f,"Damping attenuation");
|
||||||
|
float s_xmin = -10, s_xmax = 10, s_amp = 1, s_mean = 1, s_std = 1;
|
||||||
|
std::sscanf(s_xrange,"%f%*c%f",&s_xmin,&s_xmax);
|
||||||
|
std::sscanf(s_params,"%f%*c%f%*c%f",&s_amp,&s_mean,&s_std);
|
||||||
|
|
||||||
|
// Create noisy samples of a Gaussian function.
|
||||||
|
const float s_std2 = 2*s_std*s_std, s_fact = s_amp/((float)std::sqrt(2*cimg::PI)*s_std);
|
||||||
|
CImg<> samples(s_nb,2);
|
||||||
|
cimg_forX(samples,i) {
|
||||||
|
const float
|
||||||
|
x = (float)(s_xmin + (s_xmax - s_xmin)*cimg::rand()),
|
||||||
|
y = s_fact*(float)(1 + s_noise*cimg::grand()/100)*std::exp(-cimg::sqr(x - s_mean)/s_std2);
|
||||||
|
samples(i,0) = x;
|
||||||
|
samples(i,1) = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fit Gaussian function on the sample points and display curve iterations.
|
||||||
|
CImgDisplay disp(640,480,"Levenberg-Marquardt Gaussian Fitting",0);
|
||||||
|
float f_amp = 1, f_mean = 1, f_std = 1, f_lambda = f_lambda0;
|
||||||
|
if (f_params) std::sscanf(f_params,"%f%*c%f%*c%f",&f_amp,&f_mean,&f_std);
|
||||||
|
else {
|
||||||
|
const float& vmax = samples.get_shared_row(1).max();
|
||||||
|
float cmax = 0; samples.contains(vmax,cmax);
|
||||||
|
f_mean = samples((int)cmax,0);
|
||||||
|
f_std = (s_xmax - s_xmin)/10;
|
||||||
|
f_amp = vmax*(float)std::sqrt(2*cimg::PI)*f_std;
|
||||||
|
}
|
||||||
|
CImg<> beta = CImg<>::vector(f_amp,f_mean,f_std);
|
||||||
|
for (unsigned int iter = 0; !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC(); ++iter) {
|
||||||
|
|
||||||
|
// Do one iteration of the Levenberg-Marquardt algorithm.
|
||||||
|
CImg<> YmF(1,s_nb), J(beta.height(),s_nb);
|
||||||
|
const float
|
||||||
|
_f_amp = beta(0), _f_mean = beta(1), _f_std = beta(2),
|
||||||
|
_f_std2 = 2*_f_std*_f_std, _f_fact = (float)std::sqrt(2*cimg::PI)*_f_std;
|
||||||
|
float _f_error = 0;
|
||||||
|
cimg_forY(J,i) {
|
||||||
|
const float
|
||||||
|
x = samples(i,0),
|
||||||
|
_f_exp = std::exp(-cimg::sqr(x - _f_mean)/_f_std2),
|
||||||
|
delta = samples(i,1) - _f_amp*_f_exp/_f_fact;
|
||||||
|
YmF(i) = delta;
|
||||||
|
J(0,i) = _f_exp/_f_fact;
|
||||||
|
J(1,i) = _f_amp*_f_exp/_f_fact*(x - _f_mean)*2/_f_std2;
|
||||||
|
J(2,i) = _f_amp*_f_exp/_f_fact*(cimg::sqr(x - _f_mean)/(_f_std*_f_std*_f_std));
|
||||||
|
_f_error+=cimg::sqr(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
CImg<> Jt = J.get_transpose(), M = Jt*J;
|
||||||
|
cimg_forX(M,x) M(x,x)*=1 + f_lambda;
|
||||||
|
beta+=M.get_invert()*Jt*YmF;
|
||||||
|
if (beta(0)<=0) beta(0) = 0.1f;
|
||||||
|
if (beta(2)<=0) beta(2) = 0.1f;
|
||||||
|
f_lambda*=f_dlambda;
|
||||||
|
|
||||||
|
// Display fitting curves.
|
||||||
|
const unsigned char black[] = { 0,0,0 }, gray[] = { 228,228,228 };
|
||||||
|
CImg<unsigned char>(disp.width(),disp.height(),1,3,255).
|
||||||
|
draw_gaussfit(samples,beta(0),beta(1),beta(2),s_amp,s_mean,s_std).
|
||||||
|
draw_rectangle(5,7,150,100,gray,0.9f).draw_rectangle(5,7,150,100,black,1,~0U).
|
||||||
|
draw_text(10,10,"Iteration : %d",black,0,1,13,iter).
|
||||||
|
draw_text(10,25,"Amplitude : %.4g (%.4g)",black,0,1,13,beta(0),s_amp).
|
||||||
|
draw_text(10,40,"Mean : %.4g (%.4g)",black,0,1,13,beta(1),s_mean).
|
||||||
|
draw_text(10,55,"Std : %.4g (%.4g)",black,0,1,13,beta(2),s_std).
|
||||||
|
draw_text(10,70,"Error : %.4g",black,0,1,13,std::sqrt(_f_error)).
|
||||||
|
draw_text(10,85,"Lambda : %.4g",black,0,1,13,f_lambda).
|
||||||
|
display(disp.resize(false).wait(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Draw sample points, ideal and fitted gaussian curves on the instance image.
|
||||||
|
// (defined as a CImg plug-in function).
|
||||||
|
template<typename t>
|
||||||
|
CImg<T>& draw_gaussfit(const CImg<t>& samples,
|
||||||
|
const float f_amp, const float f_mean, const float f_std,
|
||||||
|
const float i_amp, const float i_mean, const float i_std) {
|
||||||
|
if (is_empty()) return *this;
|
||||||
|
const unsigned char black[] = { 0,0,0 }, green[] = { 10,155,20 }, orange[] = { 155,20,0 }, purple[] = { 200,10,200 };
|
||||||
|
float
|
||||||
|
xmin, xmax = samples.get_shared_row(0).max_min(xmin), deltax = xmax - xmin,
|
||||||
|
ymin, ymax = samples.get_shared_row(1).max_min(ymin), deltay = ymax - ymin;
|
||||||
|
xmin-=0.2f*deltax; xmax+=0.2f*deltax; ymin-=0.2f*deltay; ymax+=0.2f*deltay;
|
||||||
|
deltax = xmax - xmin; deltay = ymax - ymin;
|
||||||
|
draw_grid(64,64,0,0,false,false,black,0.3f,0x55555555,0x55555555).draw_axes(xmin,xmax,ymax,ymin,black,0.8f);
|
||||||
|
CImg<> nsamples(samples);
|
||||||
|
(nsamples.get_shared_row(0)-=xmin)*=width()/deltax;
|
||||||
|
(nsamples.get_shared_row(1)-=ymax)*=-height()/deltay;
|
||||||
|
cimg_forX(nsamples,i) draw_circle((int)nsamples(i,0),(int)nsamples(i,1),3,orange,1,~0U);
|
||||||
|
CImg<int> truth(width(),2), fit(width(),2);
|
||||||
|
const float
|
||||||
|
i_std2 = 2*i_std*i_std, i_fact = i_amp/((float)std::sqrt(2*cimg::PI)*i_std),
|
||||||
|
f_std2 = 2*f_std*f_std, f_fact = f_amp/((float)std::sqrt(2*cimg::PI)*f_std);
|
||||||
|
cimg_forX(*this,x) {
|
||||||
|
const float
|
||||||
|
x0 = xmin + x*deltax/width(),
|
||||||
|
ys0 = i_fact*std::exp(-cimg::sqr(x0 - i_mean)/i_std2),
|
||||||
|
yf0 = f_fact*std::exp(-cimg::sqr(x0 - f_mean)/f_std2);
|
||||||
|
fit(x,0) = truth(x,0) = x;
|
||||||
|
truth(x,1) = (int)((ymax - ys0)*height()/deltay);
|
||||||
|
fit(x,1) = (int)((ymax - yf0)*height()/deltay);
|
||||||
|
}
|
||||||
|
return draw_line(truth,green,0.7f,0xCCCCCCCC).draw_line(fit,purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
353
examples/generate_loop_macros.cpp
Normal file
353
examples/generate_loop_macros.cpp
Normal file
|
@ -0,0 +1,353 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : generate_loop_macros.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : Generate C++ macros to deal with MxN[xP] neighborhood
|
||||||
|
# loops within the CImg Library.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
|
||||||
|
// Generate macro(s) 'cimg_forN(i,bound)'
|
||||||
|
//----------------------------------------
|
||||||
|
void generate_forN(const unsigned int N) {
|
||||||
|
if (N>=2) {
|
||||||
|
const unsigned int Nn = N/2, Np = Nn - ((N + 1)%2);
|
||||||
|
std::printf("#define cimg_for%u(bound,i) for (int i = 0, \\\n",N);
|
||||||
|
for (unsigned int k = 0; k<Np; ++k) std::printf(" _p%u##i = 0,",Np - k);
|
||||||
|
std::printf(" \\\n");
|
||||||
|
for (unsigned int k = 1; k<=Nn; ++k)
|
||||||
|
std::printf(" _n%u##i = %u>=(int)(bound)?(int)(bound) - 1:%u%c \\\n",k,k,k,k==Nn?';':',');
|
||||||
|
std::printf(" _n%u##i<(int)(bound) || ",Nn);
|
||||||
|
for (unsigned int k = Nn - 1; k>=1; --k) std::printf("_n%u##i==--_n%u##i || ",k,k + 1);
|
||||||
|
std::printf("\\\n i==(");
|
||||||
|
for (unsigned int k = Nn; k>=2; --k) std::printf("_n%u##i = ",k);
|
||||||
|
std::printf("--_n1##i); \\\n ");
|
||||||
|
for (unsigned int k = Np; k>=2; --k) std::printf("_p%u##i = _p%u##i, ",k,k - 1);
|
||||||
|
if (Np) std::printf("_p1##i = i++, \\\n ");
|
||||||
|
else std::printf(" ++i, ");
|
||||||
|
for (unsigned int k = 1; k<Nn; ++k) std::printf("++_n%u##i, ",k);
|
||||||
|
std::printf("++_n%u##i)\n\n",Nn);
|
||||||
|
|
||||||
|
std::printf("#define cimg_for%uX(img,x) cimg_for%u((img)._width,x)\n",N,N);
|
||||||
|
std::printf("#define cimg_for%uY(img,y) cimg_for%u((img)._height,y)\n",N,N);
|
||||||
|
std::printf("#define cimg_for%uZ(img,z) cimg_for%u((img)._depth,z)\n",N,N);
|
||||||
|
std::printf("#define cimg_for%uC(img,c) cimg_for%u((img)._spectrum,c)\n",N,N);
|
||||||
|
std::printf("#define cimg_for%uXY(img,x,y) cimg_for%uY(img,y) cimg_for%uX(img,x)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uXZ(img,x,z) cimg_for%uZ(img,z) cimg_for%uX(img,x)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uXC(img,x,c) cimg_for%uC(img,c) cimg_for%uX(img,x)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uYZ(img,y,z) cimg_for%uZ(img,z) cimg_for%uY(img,y)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uYC(img,y,c) cimg_for%uC(img,c) cimg_for%uY(img,y)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uZC(img,z,c) cimg_for%uC(img,c) cimg_for%uZ(img,z)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uXYZ(img,x,y,z) cimg_for%uZ(img,z) cimg_for%uXY(img,x,y)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uXZC(img,x,z,c) cimg_for%uC(img,c) cimg_for%uXZ(img,x,z)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uYZC(img,y,z,c) cimg_for%uC(img,c) cimg_for%uYZ(img,y,z)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for%uXYZC(img,x,y,z,c) cimg_for%uC(img,c) cimg_for%uXYZ(img,x,y,z)\n\n",N,N,N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate macro(s) 'cimg_for_inN(i,bound)'
|
||||||
|
//------------------------------------------
|
||||||
|
void generate_for_inN(const unsigned int N) {
|
||||||
|
if (N>=2) {
|
||||||
|
const unsigned int Nn = N/2, Np = Nn - ((N + 1)%2);
|
||||||
|
std::printf("#define cimg_for_in%u(bound,i0,i1,i) for (int i = (int)(i0)<0?0:(int)(i0), \\\n",N);
|
||||||
|
for (unsigned int k = 0; k<Np; ++k)
|
||||||
|
std::printf(" _p%u##i = i - %u<0?0:i-%u, \\\n",Np - k,Np - k,Np - k);
|
||||||
|
for (unsigned int k = 1; k<=Nn; ++k)
|
||||||
|
std::printf(" _n%u##i = i + %u>=(int)(bound)?(int)(bound) - 1:i + %u%c \\\n",k,k,k,k==Nn?';':',');
|
||||||
|
std::printf(" i<=(int)(i1) && (_n%u##i<(int)(bound) || ",Nn);
|
||||||
|
for (unsigned int k = Nn - 1; k>=1; --k) std::printf("_n%u##i==--_n%u##i || ",k,k + 1);
|
||||||
|
std::printf("\\\n i==(");
|
||||||
|
for (unsigned int k = Nn; k>=2; --k) std::printf("_n%u##i = ",k);
|
||||||
|
std::printf("--_n1##i)); \\\n ");
|
||||||
|
for (unsigned int k = Np; k>=2; --k) std::printf("_p%u##i = _p%u##i, ",k,k - 1);
|
||||||
|
if (Np) std::printf("_p1##i = i++, \\\n ");
|
||||||
|
else std::printf(" ++i, ");
|
||||||
|
for (unsigned int k = 1; k<Nn; ++k) std::printf("++_n%u##i, ",k);
|
||||||
|
std::printf("++_n%u##i)\n\n",Nn);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::printf("#define cimg_for_in%uX(img,x0,x1,x) cimg_for_in%u((img)._width,x0,x1,x)\n",N,N);
|
||||||
|
std::printf("#define cimg_for_in%uY(img,y0,y1,y) cimg_for_in%u((img)._height,y0,y1,y)\n",N,N);
|
||||||
|
std::printf("#define cimg_for_in%uZ(img,z0,z1,z) cimg_for_in%u((img)._depth,z0,z1,z)\n",N,N);
|
||||||
|
std::printf("#define cimg_for_in%uC(img,c0,c1,c) cimg_for_in%u((img)._spectrum,c0,c1,c)\n",N,N);
|
||||||
|
std::printf("#define cimg_for_in%uXY(img,x0,y0,x1,y1,x,y) cimg_for_in%uY(img,y0,y1,y) "
|
||||||
|
"cimg_for_in%uX(img,x0,x1,x)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uXZ(img,x0,z0,x1,z1,x,z) cimg_for_in%uZ(img,z0,z1,z) "
|
||||||
|
"cimg_for_in%uX(img,x0,x1,x)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uXC(img,x0,c0,x1,c1,x,c) cimg_for_in%uC(img,c0,c1,c) "
|
||||||
|
"cimg_for_in%uX(img,x0,x1,x)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uYZ(img,y0,z0,y1,z1,y,z) cimg_for_in%uZ(img,z0,z1,z) "
|
||||||
|
"cimg_for_in%uY(img,y0,y1,y)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uYC(img,y0,c0,y1,c1,y,c) cimg_for_in%uC(img,c0,c1,c) "
|
||||||
|
"cimg_for_in%uY(img,y0,y1,y)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uZC(img,z0,c0,z1,c1,z,c) cimg_for_in%uC(img,c0,c1,c) "
|
||||||
|
"cimg_for_in%uZ(img,z0,z1,z)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in%uZ(img,z0,z1,z) "
|
||||||
|
"cimg_for_in%uXY(img,x0,y0,x1,y1,x,y)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uXZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in%uC(img,c0,c1,c) "
|
||||||
|
"cimg_for_in%uXZ(img,x0,y0,x1,y1,x,z)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in%uC(img,c0,c1,c) "
|
||||||
|
"cimg_for_in%uYZ(img,y0,z0,y1,z1,y,z)\n",N,N,N);
|
||||||
|
std::printf("#define cimg_for_in%uXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) cimg_for_in%uC(img,c0,c1,c) "
|
||||||
|
"cimg_for_in%uXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)\n\n",N,N,N);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate macro 'cimg_forMxN[xP](img,x,y,z,c,I,T)'
|
||||||
|
//--------------------------------------------------
|
||||||
|
void generate_forMxNxP(const unsigned int M, const unsigned int N, const unsigned int P) {
|
||||||
|
char indx[16], indy[16], indz[16];
|
||||||
|
const int
|
||||||
|
Mn = (int)(M/2), Mp = (int)(Mn - ((M + 1)%2)),
|
||||||
|
Nn = (int)(N/2), Np = (int)(Nn - ((N + 1)%2)),
|
||||||
|
Pn = (int)(P/2), Pp = (int)(Pn - ((P + 1)%2)),
|
||||||
|
last = (int)(M*N*P);
|
||||||
|
|
||||||
|
if (P>1) std::printf("#define cimg_for%ux%ux%u(img,x,y,z,c,I,T) \\\n cimg_for%u((img)._depth,z)",M,N,P,P);
|
||||||
|
else std::printf("#define cimg_for%ux%u(img,x,y,z,c,I,T) \\\n",M,N);
|
||||||
|
if (N>1) std::printf(" cimg_for%u((img)._height,y) ",N);
|
||||||
|
else std::printf(" cimg_forY(img,y) ");
|
||||||
|
|
||||||
|
std::printf("for (int x = 0%c \\\n",M>1?',':';');
|
||||||
|
for (int k = Mp; k>=1; --k) std::printf(" _p%u##x = 0%s",k,k==1?", \\\n":",");
|
||||||
|
for (int k = 1; k<Mn; ++k) std::printf(" _n%u##x = %u>=((img)._width)?(img).width() - 1:%u, \\\n",k,k,k);
|
||||||
|
|
||||||
|
if (M>1) {
|
||||||
|
std::printf(" _n%u##x = (int)( \\\n ",Mn);
|
||||||
|
for (int k = 0, z = -Pp; z<=Pn; ++z)
|
||||||
|
for (int y = -Np; y<=Nn; ++y) {
|
||||||
|
for (int x = -Mp; x<=0; ++x) { std::printf("%sI[%d] =",k && x==-Mp?" (":(x==-Mp?"(":" "),k); ++k; }
|
||||||
|
k+=Mn;
|
||||||
|
if (y<0) std::sprintf(indy,"_p%d##",-y); else if (y>0) std::sprintf(indy,"_n%d##",y); else indy[0]='\0';
|
||||||
|
if (z<0) std::sprintf(indz,"_p%d##",-z); else if (z>0) std::sprintf(indz,"_n%d##",z); else indz[0]='\0';
|
||||||
|
std::printf(" (T)(img)(0,%sy,%sz,c))%s",indy,indz,k>=last?",":", \\\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::printf(" \\\n");
|
||||||
|
for (int x = 1; x<Mn; ++x)
|
||||||
|
for (int z = -Pp; z<=Pn; ++z)
|
||||||
|
for (int y = -Np; y<=Nn; ++y) {
|
||||||
|
if (y<0) std::sprintf(indy,"_p%d##",-y); else if (y>0) std::sprintf(indy,"_n%d##",y); else indy[0]='\0';
|
||||||
|
if (z<0) std::sprintf(indz,"_p%d##",-z); else if (z>0) std::sprintf(indz,"_n%d##",z); else indz[0]='\0';
|
||||||
|
std::printf(" (I[%d] = (T)(img)(_n%d##x,%sy,%sz,c)), \\\n",(Mp + x) + (y + Np)*M + (z + Pp)*M*N,x,indy,indz);
|
||||||
|
}
|
||||||
|
std::printf(" %u>=((img)._width)?(img).width() - 1:%u); \\\n",Mn,Mn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (M>1) std::printf(" (_n%u##x",Mn); else std::printf(" (x");
|
||||||
|
std::printf("<(img).width() && ( \\\n");
|
||||||
|
|
||||||
|
for (int z = -Pp; z<=Pn; ++z)
|
||||||
|
for (int y = -Np; y<=Nn; ++y) {
|
||||||
|
if (M>1) std::sprintf(indx,"_n%d##",Mn); else indx[0]='\0';
|
||||||
|
if (y<0) std::sprintf(indy,"_p%d##",-y); else if (y>0) std::sprintf(indy,"_n%d##",y); else indy[0]='\0';
|
||||||
|
if (z<0) std::sprintf(indz,"_p%d##",-z); else if (z>0) std::sprintf(indz,"_n%d##",z); else indz[0]='\0';
|
||||||
|
std::printf(" (I[%d] = (T)(img)(%sx,%sy,%sz,c))%s",M - 1 + (y + Np)*M + (z + Pp)*M*N,indx,indy,indz,
|
||||||
|
z==Pn && y==Nn?",1))":", \\\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (M>1) {
|
||||||
|
std::printf(" || \\\n ");
|
||||||
|
for (int k = Mn - 1; k>=1; --k) std::printf("_n%d##x==--_n%u##x || ",k,k + 1);
|
||||||
|
std::printf("x==(");
|
||||||
|
for (int k = Mn; k>=2; --k) std::printf("_n%d##x = ",k);
|
||||||
|
std::printf("--_n1##x); \\\n");
|
||||||
|
} else std::printf("; \\\n");
|
||||||
|
|
||||||
|
if (M>1) {
|
||||||
|
for (unsigned int k = 0, z = 0; z<P; ++z)
|
||||||
|
for (unsigned int y = 0; y<N; ++y) {
|
||||||
|
for (unsigned int x = 0; x<M - 1; ++x) {
|
||||||
|
std::printf(" I[%d] = I[%d],",k,k + 1);
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
std::printf(" \\\n");
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
std::printf(" ");
|
||||||
|
for (int k = Mp; k>=2; --k) std::printf("_p%d##x = _p%d##x, ",k,k - 1);
|
||||||
|
if (M>2) std::printf("_p1##x = x++, "); else std::printf("++x, ");
|
||||||
|
for (int k = 1; k<=Mn - 1; ++k) std::printf("++_n%d##x, ",k);
|
||||||
|
std::printf("++_n%d##x)\n\n",Mn);
|
||||||
|
} else std::printf(" ++x)\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate macro 'cimg_for_inMxN[xP](img,x,y,z,c,I,T)'
|
||||||
|
//-----------------------------------------------------
|
||||||
|
void generate_for_inMxNxP(const unsigned int M, const unsigned int N, const unsigned int P) {
|
||||||
|
char indx[16], indy[16], indz[16];
|
||||||
|
const int
|
||||||
|
Mn = (int)(M/2), Mp = (int)(Mn - ((M + 1)%2)),
|
||||||
|
Nn = (int)(N/2), Np = (int)(Nn - ((N + 1)%2)),
|
||||||
|
Pn = (int)(P/2), Pp = (int)(Pn - ((P + 1)%2));
|
||||||
|
|
||||||
|
if (P>1)
|
||||||
|
std::printf("#define cimg_for_in%ux%ux%u(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \\\n "
|
||||||
|
"cimg_for_in%u((img)._depth,z0,z1,z)",M,N,P,P);
|
||||||
|
else std::printf("#define cimg_for_in%ux%u(img,x0,y0,x1,y1,x,y,z,c,I,T) \\\n",M,N);
|
||||||
|
if (N>1) std::printf(" cimg_for_in%u((img)._height,y0,y1,y) ",N);
|
||||||
|
else std::printf(" cimg_for_inY(img,y0,y1,y) ");
|
||||||
|
|
||||||
|
std::printf("for (int x = (int)(x0)<0?0:(int)(x0)%c \\\n",M>1?',':';');
|
||||||
|
for (int k = Mp; k>=1; --k) std::printf(" _p%u##x = x - %u<0?0:x - %u, \\\n",k,k,k);
|
||||||
|
for (int k = 1; k<Mn; ++k) std::printf(" _n%u##x = x + %u>=(img).width()?(img).width() - 1:x + %u, \\\n",k,k,k);
|
||||||
|
|
||||||
|
if (M>1) {
|
||||||
|
std::printf(" _n%u##x = (int)( \\\n",Mn);
|
||||||
|
for (int x = -Mp; x<Mn; ++x)
|
||||||
|
for (int z = -Pp; z<=Pn; ++z)
|
||||||
|
for (int y = -Np; y<=Nn; ++y) {
|
||||||
|
if (x<0) std::sprintf(indx,"_p%d##",-x); else if (x>0) std::sprintf(indx,"_n%d##",x); else indx[0]='\0';
|
||||||
|
if (y<0) std::sprintf(indy,"_p%d##",-y); else if (y>0) std::sprintf(indy,"_n%d##",y); else indy[0]='\0';
|
||||||
|
if (z<0) std::sprintf(indz,"_p%d##",-z); else if (z>0) std::sprintf(indz,"_n%d##",z); else indz[0]='\0';
|
||||||
|
std::printf(" (I[%d] = (T)(img)(%sx,%sy,%sz,c)), \\\n",(Mp + x) + (y + Np)*M + (z + Pp)*M*N,indx,indy,indz);
|
||||||
|
}
|
||||||
|
std::printf(" x + %u>=(img).width()?(img).width() - 1:x + %u); \\\n",Mn,Mn);
|
||||||
|
}
|
||||||
|
std::printf(" x<=(int)(x1) && (");
|
||||||
|
if (M>1) std::printf("(_n%u##x",Mn); else std::printf("(x");
|
||||||
|
std::printf("<(img).width() && ( \\\n");
|
||||||
|
|
||||||
|
for (int z = -Pp; z<=Pn; ++z)
|
||||||
|
for (int y = -Np; y<=Nn; ++y) {
|
||||||
|
if (M>1) std::sprintf(indx,"_n%d##",Mn); else indx[0]='\0';
|
||||||
|
if (y<0) std::sprintf(indy,"_p%d##",-y); else if (y>0) std::sprintf(indy,"_n%d##",y); else indy[0]='\0';
|
||||||
|
if (z<0) std::sprintf(indz,"_p%d##",-z); else if (z>0) std::sprintf(indz,"_n%d##",z); else indz[0]='\0';
|
||||||
|
std::printf(" (I[%d] = (T)(img)(%sx,%sy,%sz,c))%s",M - 1 + (y + Np)*M + (z + Pp)*M*N,indx,indy,indz,
|
||||||
|
z==Pn && y==Nn?",1))":", \\\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (M>1) {
|
||||||
|
std::printf(" || \\\n ");
|
||||||
|
for (int k = Mn - 1; k>=1; --k) std::printf("_n%d##x==--_n%u##x || ",k,k + 1);
|
||||||
|
std::printf("x==(");
|
||||||
|
for (int k = Mn; k>=2; --k) std::printf("_n%d##x = ",k);
|
||||||
|
std::printf("--_n1##x)); \\\n");
|
||||||
|
} else std::printf("); \\\n");
|
||||||
|
|
||||||
|
if (M>1) {
|
||||||
|
for (unsigned int k = 0, z = 0; z<P; ++z)
|
||||||
|
for (unsigned int y = 0; y<N; ++y) {
|
||||||
|
for (unsigned int x = 0; x<M - 1; ++x) {
|
||||||
|
std::printf(" I[%d] = I[%d],",k,k + 1);
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
std::printf(" \\\n");
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
std::printf(" ");
|
||||||
|
for (int k = Mp; k>=2; --k) std::printf("_p%d##x = _p%d##x, ",k,k - 1);
|
||||||
|
if (M>2) std::printf("_p1##x = x++, "); else std::printf("++x, ");
|
||||||
|
for (int k = 1; k<=Mn - 1; ++k) std::printf("++_n%d##x, ",k);
|
||||||
|
std::printf("++_n%d##x)\n\n",Mn);
|
||||||
|
} else std::printf(" ++x)\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate macro 'cimg_getMxN[xP](img,x,y,z,c,I,T)'
|
||||||
|
//--------------------------------------------------
|
||||||
|
void generate_getMxNxP(const unsigned int M, const unsigned int N, const unsigned int P) {
|
||||||
|
const int
|
||||||
|
Mn = (int)(M/2), Mp = (int)(Mn - ((M + 1)%2)),
|
||||||
|
Nn = (int)(N/2), Np = (int)(Nn - ((N + 1)%2)),
|
||||||
|
Pn = (int)(P/2), Pp = (int)(Pn - ((P + 1)%2)),
|
||||||
|
last = M*N*P - 1;
|
||||||
|
if (P>1) std::printf("#define cimg_get%ux%ux%u(img,x,y,z,c,I,T) \\\n",M,N,P);
|
||||||
|
else std::printf("#define cimg_get%ux%u(img,x,y,z,c,I,T) \\\n",M,N);
|
||||||
|
char indx[16], indy[16], indz[16];
|
||||||
|
for (int k = 0, z = -Pp; z<=Pn; ++z)
|
||||||
|
for (int y = -Np; y<=Nn; ++y)
|
||||||
|
for (int x = -Mp; x<=Mn; ++x) {
|
||||||
|
if (x<0) std::sprintf(indx,"_p%d##",-x); else if (x>0) std::sprintf(indx,"_n%d##",x); else indx[0]='\0';
|
||||||
|
if (y<0) std::sprintf(indy,"_p%d##",-y); else if (y>0) std::sprintf(indy,"_n%d##",y); else indy[0]='\0';
|
||||||
|
if (z<0) std::sprintf(indz,"_p%d##",-z); else if (z>0) std::sprintf(indz,"_n%d##",z); else indz[0]='\0';
|
||||||
|
std::printf(" I[%u] = (T)(img)(%sx,%sy,%sz,c)%s",k,indx,indy,indz,
|
||||||
|
k==last?";\n\n":(x==Mn?", \\\n":","));
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------
|
||||||
|
// Main Procedure
|
||||||
|
//-----------------
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
cimg_usage("Generate C++ macros to deal with MxN[xP] neighborhood loops within the CImg Library");
|
||||||
|
|
||||||
|
// Read command line arguments
|
||||||
|
//----------------------------
|
||||||
|
const char *const size = cimg_option("-s","5x4","Size of the neighborhood");
|
||||||
|
const bool do_forN = cimg_option("-forN",true,"Generate 'cimg_forN()'");
|
||||||
|
const bool do_for_inN = cimg_option("-for_inN",true,"Generate 'cimg_for_inN()'");
|
||||||
|
const bool do_for = cimg_option("-for",true,"Generate 'cimg_forMxNxP()'");
|
||||||
|
const bool do_for_in = cimg_option("-for_in",true,"Generate 'cimg_for_inMxNxP()'");
|
||||||
|
const bool do_get = cimg_option("-get",true,"Generate 'cimg_getMxNxP()'");
|
||||||
|
if (cimg_option("-h",false,0)) std::exit(0);
|
||||||
|
|
||||||
|
unsigned int M = 1, N = 1 , P = 1;
|
||||||
|
std::sscanf(size,"%u%*c%u%*c%u",&M,&N,&P);
|
||||||
|
if (!M || !N || !P || (M==1 && N==1 && P==1)) {
|
||||||
|
std::fprintf(stderr,"\n%s : Error, bad neighborhood size '%s'\n",argv[0],size);
|
||||||
|
std::exit(0);
|
||||||
|
}
|
||||||
|
if (!do_forN && !do_get && !do_for) return 0;
|
||||||
|
|
||||||
|
if (P>1)
|
||||||
|
std::printf("// Define %ux%ux%u loop macros\n"
|
||||||
|
"//----------------------------\n",M,N,P);
|
||||||
|
else
|
||||||
|
std::printf("// Define %ux%u loop macros\n"
|
||||||
|
"//-------------------------\n",M,N);
|
||||||
|
|
||||||
|
if (do_forN) {
|
||||||
|
if (N>1) generate_forN(N);
|
||||||
|
if (P>1 && P!=N) generate_forN(P);
|
||||||
|
}
|
||||||
|
if (do_for_inN) {
|
||||||
|
if (N>1) generate_for_inN(N);
|
||||||
|
if (P>1 && P!=N) generate_for_inN(P);
|
||||||
|
}
|
||||||
|
if (do_for) generate_forMxNxP(M,N,P);
|
||||||
|
if (do_for_in) generate_for_inMxNxP(M,N,P);
|
||||||
|
if (do_get) generate_getMxNxP(M,N,P);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
146
examples/hough_transform2d.cpp
Normal file
146
examples/hough_transform2d.cpp
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : hough_transform2d.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : Implementation of the Hough transform.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
#ifndef cimg_imagepath
|
||||||
|
#define cimg_imagepath "img/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Main procedure
|
||||||
|
//----------------
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
cimg_usage("Illustration of the Hough transform");
|
||||||
|
CImg<unsigned char> src(cimg_option("-i",cimg_imagepath "parrot.ppm","Input image"));
|
||||||
|
CImg<> vote(500,400,1,1,0), img = src.get_norm().normalize(0,255).resize(-100,-100,1,2,2);
|
||||||
|
|
||||||
|
CImgDisplay disp(src,"Image"), dispvote(vote,"Hough Transform");
|
||||||
|
const unsigned char col1[3]={255,255,255}, col2[3]={0,0,0};
|
||||||
|
const double
|
||||||
|
alpha = cimg_option("-a",1.5,"Gradient smoothing"),
|
||||||
|
sigma = cimg_option("-s",0.5,"Hough Transform smoothing"),
|
||||||
|
rhomax = std::sqrt((double)(img.width()*img.width() + img.height()*img.height()))/2,
|
||||||
|
thetamax = 2*cimg::PI;
|
||||||
|
|
||||||
|
if (cimg::dialog(cimg::basename(argv[0]),
|
||||||
|
"Instructions : \n"
|
||||||
|
"----------------\n\n"
|
||||||
|
"(1) When clicking on the color image, all lines crossing the selected point\n"
|
||||||
|
"will be voted in the Hough buffer.\n\n"
|
||||||
|
"(2) When clicking on the Hough buffer, the corresponding line is drawn\n"
|
||||||
|
"on the color image.\n\n"
|
||||||
|
"(3) When pressing the space bar, lines in the color image are detected from the\n"
|
||||||
|
"image gradients through votes in the Hough buffer.\n\n"
|
||||||
|
"Note that a logarithmic scaling is performed for displayin the vote image.\n"
|
||||||
|
"See also the available options (option '-h')\n","Start !","Quit",0,0,0,0,
|
||||||
|
src.get_resize(100,100,1,3),true)) std::exit(0);
|
||||||
|
|
||||||
|
while (!disp.is_closed() && !dispvote.is_closed() &&
|
||||||
|
!disp.is_keyQ() && !dispvote.is_keyQ() && !disp.is_keyESC() && !dispvote.is_keyESC()) {
|
||||||
|
|
||||||
|
CImgDisplay::wait(disp,dispvote);
|
||||||
|
|
||||||
|
// When pressing space bar, the vote is performed from the image gradients.
|
||||||
|
if (dispvote.is_keySPACE() || disp.is_keySPACE()) {
|
||||||
|
CImgList<> grad = img.get_gradient();
|
||||||
|
cimglist_for(grad,l) grad[l].blur((float)alpha);
|
||||||
|
vote.fill(0);
|
||||||
|
cimg_forXY(img,x,y) {
|
||||||
|
const double
|
||||||
|
X = (double)x - img.width()/2,
|
||||||
|
Y = (double)y - img.height()/2,
|
||||||
|
gx = grad[0](x,y),
|
||||||
|
gy = grad[1](x,y);
|
||||||
|
double
|
||||||
|
theta = std::atan2(gy,gx),
|
||||||
|
rho = std::sqrt(X*X + Y*Y)*std::cos(std::atan2(Y,X) - theta);
|
||||||
|
if (rho<0) { rho=-rho; theta+=cimg::PI; }
|
||||||
|
theta = cimg::mod(theta,thetamax);
|
||||||
|
vote((int)(theta*dispvote.width()/thetamax),(int)(rho*dispvote.height()/rhomax))+=
|
||||||
|
(float)std::sqrt(gx*gx + gy*gy);
|
||||||
|
}
|
||||||
|
vote.blur((float)sigma);
|
||||||
|
CImg<> vote2(vote); cimg_forXY(vote2,x,y) vote2(x,y) = (float)std::log(1 + vote(x,y)); vote2.display(dispvote);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When clicking on the vote window.
|
||||||
|
if (dispvote.button()) {
|
||||||
|
const double
|
||||||
|
rho = dispvote.mouse_y()*rhomax/dispvote.height(),
|
||||||
|
theta = dispvote.mouse_x()*thetamax/dispvote.width(),
|
||||||
|
x = img.width()/2 + rho*std::cos(theta),
|
||||||
|
y = img.height()/2 + rho*std::sin(theta);
|
||||||
|
const int
|
||||||
|
x0 = (int)(x + 1000*std::sin(theta)),
|
||||||
|
y0 = (int)(y - 1000*std::cos(theta)),
|
||||||
|
x1 = (int)(x - 1000*std::sin(theta)),
|
||||||
|
y1 = (int)(y + 1000*std::cos(theta));
|
||||||
|
CImg<unsigned char>(src).
|
||||||
|
draw_line(x0,y0,x1,y1,col1,1.0f,0xF0F0F0F0).draw_line(x0,y0,x1,y1,col2,1.0f,0x0F0F0F0F).
|
||||||
|
draw_line(x0 + 1,y0,x1 + 1,y1,col1,1.0f,0xF0F0F0F0).draw_line(x0 + 1,y0,x1 + 1,y1,col2,1.0f,0x0F0F0F0F).
|
||||||
|
draw_line(x0,y0 + 1,x1,y1 + 1,col1,1.0f,0xF0F0F0F0).draw_line(x0,y0 + 1,x1,y1 + 1,col2,1.0f,0x0F0F0F0F).
|
||||||
|
display(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When clicking on the image.
|
||||||
|
if (disp.button() && disp.mouse_x()>=0) {
|
||||||
|
const double
|
||||||
|
x0 = (double)disp.mouse_x() - disp.width()/2,
|
||||||
|
y0 = (double)disp.mouse_y() - disp.height()/2,
|
||||||
|
rho0 = std::sqrt(x0*x0 + y0*y0),
|
||||||
|
theta0 = std::atan2(y0,x0);
|
||||||
|
|
||||||
|
for (double t=0; t<thetamax; t+=0.001) {
|
||||||
|
double theta = t, rho = rho0*std::cos(theta0 - t);
|
||||||
|
if (rho<0) { rho=-rho; theta=cimg::mod(theta + cimg::PI,thetamax); }
|
||||||
|
vote((int)(theta*vote.width()/thetamax),(int)(rho*vote.height()/rhomax))+=1;
|
||||||
|
}
|
||||||
|
CImg<> vote2(vote); cimg_forXY(vote2,x,y) vote2(x,y) = (float)std::log(1 + vote(x,y)); vote2.display(dispvote);
|
||||||
|
}
|
||||||
|
dispvote.resize(dispvote);
|
||||||
|
disp.resize(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::exit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
157
examples/image2ascii.cpp
Normal file
157
examples/image2ascii.cpp
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : image2ascii.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : A basic image to ASCII-art converter.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Tell CImg not to use display capabilities.
|
||||||
|
#undef cimg_display
|
||||||
|
#define cimg_display 0
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
|
||||||
|
/*---------------------------
|
||||||
|
|
||||||
|
Main procedure
|
||||||
|
|
||||||
|
--------------------------*/
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
cimg_usage("A simple image to ASCII-art converter.\n\nUsage : image2ascii [options] image");
|
||||||
|
|
||||||
|
// Read command line parameters
|
||||||
|
const char *const file_i = cimg_option("-i",(char*)0,"Input image");
|
||||||
|
const char *const geom = cimg_option("-g","79x40","Output size");
|
||||||
|
const int alphabet = cimg_option("-a",0,"Alphabet type (0=full, 1=numbers, 2=letters, 3=signs, 4=minimal");
|
||||||
|
const bool invert = cimg_option("-invert",false,"Invert image intensities");
|
||||||
|
const float contour = (float)cimg_option("-contour",0.0f,"Use image contours higher than specified threshold");
|
||||||
|
const float blur = (float)cimg_option("-blur",0.8f,"Image pre-blur");
|
||||||
|
const float sigma = (float)cimg_option("-sigma",10.0f,"Font pre-blur");
|
||||||
|
|
||||||
|
int w = 79, h = 40;
|
||||||
|
std::sscanf(geom,"%d%*c%d",&w,&h);
|
||||||
|
if (cimg_option("-h",false,0)) std::exit(0);
|
||||||
|
|
||||||
|
// Init fonts
|
||||||
|
CImgList<> font_full = CImgList<>::font(13,false);
|
||||||
|
font_full.remove(0,255);
|
||||||
|
const int fw = font_full[(int)'A'].width(), fh = font_full[(int)'A'].height();
|
||||||
|
CImgList<> font, font_blur;
|
||||||
|
CImgList<unsigned char> font_code;
|
||||||
|
|
||||||
|
switch (alphabet) {
|
||||||
|
case 1: {
|
||||||
|
font_code.insert(CImg<>::vector(' '));
|
||||||
|
for (unsigned char l='0'; l<='9'; l++) font_code.insert(CImg<>::vector(l));
|
||||||
|
} break;
|
||||||
|
case 2: {
|
||||||
|
font_code.insert(CImg<>::vector(' '));
|
||||||
|
for (unsigned char l='A'; l<='Z'; l++) font_code.insert(CImg<>::vector(l));
|
||||||
|
} break;
|
||||||
|
case 3: {
|
||||||
|
font_code.insert(CImg<>::vector(' '));
|
||||||
|
font_code.insert(CImg<>::vector('-'));
|
||||||
|
font_code.insert(CImg<>::vector('_'));
|
||||||
|
font_code.insert(CImg<>::vector('|'));
|
||||||
|
font_code.insert(CImg<>::vector('/'));
|
||||||
|
font_code.insert(CImg<>::vector('\\'));
|
||||||
|
font_code.insert(CImg<>::vector('+'));
|
||||||
|
font_code.insert(CImg<>::vector('.'));
|
||||||
|
font_code.insert(CImg<>::vector('*'));
|
||||||
|
font_code.insert(CImg<>::vector('='));
|
||||||
|
font_code.insert(CImg<>::vector(']'));
|
||||||
|
font_code.insert(CImg<>::vector('['));
|
||||||
|
font_code.insert(CImg<>::vector('('));
|
||||||
|
font_code.insert(CImg<>::vector(')'));
|
||||||
|
font_code.insert(CImg<>::vector('{'));
|
||||||
|
font_code.insert(CImg<>::vector('}'));
|
||||||
|
font_code.insert(CImg<>::vector('"'));
|
||||||
|
font_code.insert(CImg<>::vector('!'));
|
||||||
|
font_code.insert(CImg<>::vector('$'));
|
||||||
|
} break;
|
||||||
|
case 4: {
|
||||||
|
font_code.insert(CImg<>::vector(' '));
|
||||||
|
font_code.insert(CImg<>::vector('.'));
|
||||||
|
font_code.insert(CImg<>::vector('/'));
|
||||||
|
font_code.insert(CImg<>::vector('\\'));
|
||||||
|
font_code.insert(CImg<>::vector('_'));
|
||||||
|
font_code.insert(CImg<>::vector('_'));
|
||||||
|
font_code.insert(CImg<>::vector('|'));
|
||||||
|
} break;
|
||||||
|
default: { for (unsigned char l=' '; l<='~'; l++) font_code.insert(CImg<>::vector(l)); } break;
|
||||||
|
}
|
||||||
|
cimglist_for(font_code,l) {
|
||||||
|
font.insert(font_full(font_code[l](0)));
|
||||||
|
font_blur.insert(font[l].get_resize(fw,fh,1,1).blur(sigma).normalize(0,255));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init images
|
||||||
|
CImg<> img;
|
||||||
|
if (!file_i) { float white[3] = { 255,255,255 }; img.assign().draw_text(0,0," CImg\nRocks !",white); }
|
||||||
|
else img.assign(file_i);
|
||||||
|
img.norm().resize(fw*w,fh*h);
|
||||||
|
if (blur) img.blur(blur);
|
||||||
|
if (contour>0) {
|
||||||
|
CImgList<> grad = img.get_gradient("xy",4);
|
||||||
|
img = (grad[0].pow(2) + grad[1].pow(2)).sqrt().normalize(0,100).threshold(contour);
|
||||||
|
}
|
||||||
|
img.normalize(0,255);
|
||||||
|
if (invert) img = 255.0f - img;
|
||||||
|
CImg<unsigned char> dest(w,h,1,1,0);
|
||||||
|
|
||||||
|
// Render ASCII-art image, using a simple correlation method.
|
||||||
|
CImg<> neigh;
|
||||||
|
cimg_forY(dest,y) { cimg_forX(dest,x) {
|
||||||
|
neigh = img.get_crop(x*fw,y*fh,(x + 1)*fw,(y + 1)*fh);
|
||||||
|
float scoremin = 2e28f;
|
||||||
|
unsigned int best = 0;
|
||||||
|
cimglist_for(font_code,l) {
|
||||||
|
const CImg<>& letter = font_blur[l];
|
||||||
|
const float score = (float)((letter - neigh).pow(2).sum());
|
||||||
|
if (score<scoremin) { scoremin = score; best = l; }
|
||||||
|
}
|
||||||
|
dest(x,y) = (unsigned char)best;
|
||||||
|
std::fprintf(stdout,"%c",font_code[dest(x,y)](0));
|
||||||
|
}
|
||||||
|
std::fprintf(stdout,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::exit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
216
examples/image_registration2d.cpp
Normal file
216
examples/image_registration2d.cpp
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : image_registration2d.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : Compute a motion field between two images,
|
||||||
|
# with a multiscale and variational algorithm.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
#ifndef cimg_imagepath
|
||||||
|
#define cimg_imagepath "img/"
|
||||||
|
#endif
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
// animate_warp() : Create warping animation from two images and a motion field
|
||||||
|
//----------------
|
||||||
|
void animate_warp(const CImg<unsigned char>& src, const CImg<unsigned char>& dest, const CImg<>& U,
|
||||||
|
const bool morph, const bool imode, const char *filename,int nb, CImgDisplay& disp) {
|
||||||
|
CImg<unsigned char> visu = (src,dest,src)>'x', warp(src);
|
||||||
|
float t = 0;
|
||||||
|
for (unsigned int iteration = 0; !disp || (!disp.is_closed() && !disp.is_keyQ()); ++iteration) {
|
||||||
|
if (morph) cimg_forXYC(warp,x,y,k) {
|
||||||
|
const float dx = U(x,y,0), dy = U(x,y,1),
|
||||||
|
I1 = (float)src.linear_atXY(x - t*dx, y - t*dy, k),
|
||||||
|
I2 = (float)dest.linear_atXY(x + (1 - t)*dx,y + (1 - t)*dy,k);
|
||||||
|
warp(x,y,k) = (unsigned char)((1 - t)*I1 + t*I2);
|
||||||
|
} else cimg_forXYC(warp,x,y,k) {
|
||||||
|
const float dx = U(x,y,0), dy = U(x,y,1), I1 = (float)src.linear_atXY(x - t*dx, y - t*dy, 0,k);
|
||||||
|
warp(x,y,k) = (unsigned char)I1;
|
||||||
|
}
|
||||||
|
if (disp) visu.draw_image(2*src.width(),warp).display(disp.resize().wait(30));
|
||||||
|
if (filename && *filename && (imode || (int)iteration<nb)) {
|
||||||
|
std::fprintf(stderr,"\r > frame %d ",iteration);
|
||||||
|
warp.save(filename,iteration);
|
||||||
|
}
|
||||||
|
t+=1.0f/nb;
|
||||||
|
if (t<0) { t = 0; nb = -nb; }
|
||||||
|
if (t>1) { t = 1; nb = -nb; if (filename && *filename) std::exit(0); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// optflow() : multiscale version of the image registration algorithm
|
||||||
|
//-----------
|
||||||
|
CImg<> optflow(const CImg<>& source, const CImg<>& target,
|
||||||
|
const float smoothness, const float precision, const unsigned int nb_scales, CImgDisplay& disp) {
|
||||||
|
const unsigned int iteration_max = 100000;
|
||||||
|
const float _precision = (float)std::pow(10.0,-(double)precision);
|
||||||
|
const CImg<>
|
||||||
|
src = source.get_resize(target,3).normalize(0,1),
|
||||||
|
dest = target.get_normalize(0,1);
|
||||||
|
CImg<> U;
|
||||||
|
|
||||||
|
const unsigned int _nb_scales = nb_scales>0?nb_scales:
|
||||||
|
(unsigned int)(2*std::log((double)(std::max(src.width(),src.height()))));
|
||||||
|
for (int scale = _nb_scales - 1; scale>=0; --scale) {
|
||||||
|
const float factor = (float)std::pow(1.5,(double)scale);
|
||||||
|
const unsigned int
|
||||||
|
_sw = (unsigned int)(src.width()/factor), sw = _sw?_sw:1,
|
||||||
|
_sh = (unsigned int)(src.height()/factor), sh = _sh?_sh:1;
|
||||||
|
const CImg<>
|
||||||
|
I1 = src.get_resize(sw,sh,1,-100,2),
|
||||||
|
I2 = dest.get_resize(I1,2);
|
||||||
|
std::fprintf(stderr," * Scale %d\n",scale);
|
||||||
|
if (U) (U*=1.5f).resize(I2.width(),I2.height(),1,-100,3);
|
||||||
|
else U.assign(I2.width(),I2.height(),1,2,0);
|
||||||
|
|
||||||
|
float dt = 2, energy = cimg::type<float>::max();
|
||||||
|
const CImgList<> dI = I2.get_gradient();
|
||||||
|
|
||||||
|
for (unsigned int iteration = 0; iteration<iteration_max; ++iteration) {
|
||||||
|
std::fprintf(stderr,"\r- Iteration %d - E = %g",iteration,energy); std::fflush(stderr);
|
||||||
|
float _energy = 0;
|
||||||
|
cimg_for3XY(U,x,y) {
|
||||||
|
const float
|
||||||
|
X = x + U(x,y,0),
|
||||||
|
Y = y + U(x,y,1);
|
||||||
|
|
||||||
|
float deltaI = 0;
|
||||||
|
cimg_forC(I2,c) deltaI+=(float)(I1(x,y,c) - I2.linear_atXY(X,Y,c));
|
||||||
|
|
||||||
|
float _energy_regul = 0;
|
||||||
|
cimg_forC(U,c) {
|
||||||
|
const float
|
||||||
|
Ux = 0.5f*(U(_n1x,y,c) - U(_p1x,y,c)),
|
||||||
|
Uy = 0.5f*(U(x,_n1y,c) - U(x,_p1y,c)),
|
||||||
|
Uxx = U(_n1x,y,c) + U(_p1x,y,c),
|
||||||
|
Uyy = U(x,_n1y,c) + U(x,_p1y,c);
|
||||||
|
U(x,y,c) = (float)( U(x,y,c) + dt*(deltaI*dI[c].linear_atXY(X,Y) +
|
||||||
|
smoothness* ( Uxx + Uyy )))/(1 + 4*smoothness*dt);
|
||||||
|
_energy_regul+=Ux*Ux + Uy*Uy;
|
||||||
|
}
|
||||||
|
_energy+=deltaI*deltaI + smoothness*_energy_regul;
|
||||||
|
}
|
||||||
|
const float d_energy = (_energy - energy)/(sw*sh);
|
||||||
|
if (d_energy<=0 && -d_energy<_precision) break;
|
||||||
|
if (d_energy>0) dt*=0.5f;
|
||||||
|
energy = _energy;
|
||||||
|
if (disp) disp.resize();
|
||||||
|
if (disp && disp.is_closed()) std::exit(0);
|
||||||
|
if (disp && !(iteration%300)) {
|
||||||
|
const unsigned char white[] = { 255,255,255 };
|
||||||
|
CImg<unsigned char> tmp = I1.get_warp(U,true,true,1).normalize(0,200);
|
||||||
|
tmp.resize(disp.width(),disp.height()).draw_quiver(U,white,0.7f,15,-14,true).display(disp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::fprintf(stderr,"\n");
|
||||||
|
}
|
||||||
|
return U;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------
|
||||||
|
|
||||||
|
Main function
|
||||||
|
|
||||||
|
------------------------*/
|
||||||
|
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
|
||||||
|
// Read command line parameters
|
||||||
|
cimg_usage("Compute an optical flow between two 2D images, and create a warped animation");
|
||||||
|
const char
|
||||||
|
*name_i1 = cimg_option("-i",cimg_imagepath "sh0r.pgm","Input Image 1 (Destination)"),
|
||||||
|
*name_i2 = cimg_option("-i2",cimg_imagepath "sh1r.pgm","Input Image 2 (Source)"),
|
||||||
|
*name_o = cimg_option("-o",(const char*)NULL,"Output 2D flow (inrimage)"),
|
||||||
|
*name_seq = cimg_option("-o2",(const char*)NULL,"Output Warping Sequence");
|
||||||
|
const float
|
||||||
|
smoothness = cimg_option("-s",0.1f,"Flow Smoothness"),
|
||||||
|
precision = cimg_option("-p",6.0f,"Convergence precision");
|
||||||
|
const unsigned int
|
||||||
|
nb = cimg_option("-n",40,"Number of warped frames"),
|
||||||
|
nb_scales = cimg_option("-scale",0,"Number of scales (0=auto)");
|
||||||
|
const bool
|
||||||
|
normalize = cimg_option("-equalize",true,"Histogram normalization of the images"),
|
||||||
|
morph = cimg_option("-m",true,"Morphing mode"),
|
||||||
|
imode = cimg_option("-c",true,"Complete interpolation (or last frame is missing)"),
|
||||||
|
dispflag = !cimg_option("-novisu",false,"Visualization");
|
||||||
|
|
||||||
|
// Init images and display
|
||||||
|
std::fprintf(stderr," - Init images.\n");
|
||||||
|
const CImg<>
|
||||||
|
src(name_i1),
|
||||||
|
dest(CImg<>(name_i2).resize(src,3)),
|
||||||
|
src_blur = normalize?src.get_blur(0.5f).equalize(256):src.get_blur(0.5f),
|
||||||
|
dest_blur = normalize?dest.get_blur(0.5f).equalize(256):dest.get_blur(0.5f);
|
||||||
|
|
||||||
|
CImgDisplay disp;
|
||||||
|
if (dispflag) {
|
||||||
|
unsigned int w = src.width(), h = src.height();
|
||||||
|
const unsigned int dmin = std::min(w,h), minsiz = 512;
|
||||||
|
if (dmin<minsiz) { w=w*minsiz/dmin; h=h*minsiz/dmin; }
|
||||||
|
const unsigned int dmax = std::max(w,h), maxsiz = 1024;
|
||||||
|
if (dmax>maxsiz) { w=w*maxsiz/dmax; h=h*maxsiz/dmax; }
|
||||||
|
disp.assign(w,h,"Estimated Motion",0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run Motion estimation algorithm
|
||||||
|
std::fprintf(stderr," - Compute optical flow.\n");
|
||||||
|
const CImg<> U = optflow(src_blur,dest_blur,smoothness,precision,nb_scales,disp);
|
||||||
|
if (name_o) U.save(name_o);
|
||||||
|
U.print("Computed flow");
|
||||||
|
|
||||||
|
// Do morphing animation
|
||||||
|
std::fprintf(stderr," - Create warped animation.\n");
|
||||||
|
CImgDisplay disp2;
|
||||||
|
if (dispflag) {
|
||||||
|
unsigned int w = src.width(), h = src.height();
|
||||||
|
const unsigned int dmin = std::min(w,h), minsiz = 100;
|
||||||
|
if (dmin<minsiz) { w = w*minsiz/dmin; h=h*minsiz/dmin; }
|
||||||
|
const unsigned int dmax = std::max(w,h), maxsiz = 1024/3;
|
||||||
|
if (dmax>maxsiz) { w = w*maxsiz/dmax; h=h*maxsiz/dmax; }
|
||||||
|
disp2.assign(3*w,h,"Source/Destination images and Motion animation",0);
|
||||||
|
}
|
||||||
|
|
||||||
|
animate_warp(src.get_normalize(0,255),dest.get_normalize(0,255),U,morph,imode,name_seq,nb,disp2);
|
||||||
|
|
||||||
|
std::exit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
140
examples/image_surface3d.cpp
Normal file
140
examples/image_surface3d.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
#
|
||||||
|
# File : image_surface3d.cpp
|
||||||
|
# ( C++ source file )
|
||||||
|
#
|
||||||
|
# Description : This tool allows to show an image as a 3D surface.
|
||||||
|
# This file is a part of the CImg Library project.
|
||||||
|
# ( http://cimg.eu )
|
||||||
|
#
|
||||||
|
# Copyright : David Tschumperlé
|
||||||
|
# ( http://tschumperle.users.greyc.fr/ )
|
||||||
|
#
|
||||||
|
# License : CeCILL v2.0
|
||||||
|
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
||||||
|
#
|
||||||
|
# This software is governed by the CeCILL license under French law and
|
||||||
|
# abiding by the rules of distribution of free software. You can use,
|
||||||
|
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||||
|
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
|
# "http://www.cecill.info".
|
||||||
|
#
|
||||||
|
# As a counterpart to the access to the source code and rights to copy,
|
||||||
|
# modify and redistribute granted by the license, users are provided only
|
||||||
|
# with a limited warranty and the software's author, the holder of the
|
||||||
|
# economic rights, and the successive licensors have only limited
|
||||||
|
# liability.
|
||||||
|
#
|
||||||
|
# In this respect, the user's attention is drawn to the risks associated
|
||||||
|
# with loading, using, modifying and/or developing or reproducing the
|
||||||
|
# software by the user in light of its specific status of free software,
|
||||||
|
# that may mean that it is complicated to manipulate, and that also
|
||||||
|
# therefore means that it is reserved for developers and experienced
|
||||||
|
# professionals having in-depth computer knowledge. Users are therefore
|
||||||
|
# encouraged to load and test the software's suitability as regards their
|
||||||
|
# requirements in conditions enabling the security of their systems and/or
|
||||||
|
# data to be ensured and, more generally, to use and operate it in the
|
||||||
|
# same conditions as regards security.
|
||||||
|
#
|
||||||
|
# The fact that you are presently reading this means that you have had
|
||||||
|
# knowledge of the CeCILL license and that you accept its terms.
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CImg.h"
|
||||||
|
using namespace cimg_library;
|
||||||
|
#ifndef cimg_imagepath
|
||||||
|
#define cimg_imagepath "img/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Main procedure
|
||||||
|
//----------------
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
|
||||||
|
// Read command line arguments.
|
||||||
|
cimg_usage("Render an image as a surface");
|
||||||
|
const char *file_i = cimg_option("-i",cimg_imagepath "logo.bmp","Input image");
|
||||||
|
const char *file_o = cimg_option("-o",(char*)0,"Output 3D object");
|
||||||
|
const float sigma = cimg_option("-smooth",1.0f,"Amount of image smoothing");
|
||||||
|
const float ratioz = cimg_option("-z",0.25f,"Aspect ratio along z-axis");
|
||||||
|
const unsigned int di = cimg_option("-di",10,"Step for isophote skipping");
|
||||||
|
|
||||||
|
// Load 2D image file.
|
||||||
|
std::fprintf(stderr,"\n- Load file '%s'",cimg::basename(file_i)); std::fflush(stderr);
|
||||||
|
const CImg<unsigned char>
|
||||||
|
img = CImg<>(file_i).blur(sigma).resize(-100,-100,1,3),
|
||||||
|
norm = img.get_norm().normalize(0,255);
|
||||||
|
|
||||||
|
// Compute surface with triangles.
|
||||||
|
std::fprintf(stderr,"\n- Create image surface"); std::fflush(stderr);
|
||||||
|
CImgList<unsigned int> primitives;
|
||||||
|
CImgList<unsigned char> colors;
|
||||||
|
const CImg<> points = img.get_elevation3d(primitives,colors,norm*-ratioz);
|
||||||
|
|
||||||
|
// Compute image isophotes.
|
||||||
|
std::fprintf(stderr,"\n- Compute image isophotes"); std::fflush(stderr);
|
||||||
|
CImgList<unsigned int> isoprimitives;
|
||||||
|
CImgList<unsigned char> isocolors;
|
||||||
|
CImg<> isopoints;
|
||||||
|
for (unsigned int i = 0; i<255; i+=di) {
|
||||||
|
CImgList<> prims;
|
||||||
|
const CImg<> pts = norm.get_isoline3d(prims,(float)i);
|
||||||
|
isopoints.append_object3d(isoprimitives,pts,prims);
|
||||||
|
}
|
||||||
|
cimglist_for(isoprimitives,l) {
|
||||||
|
const unsigned int i0 = isoprimitives(l,0);
|
||||||
|
const float x0 = isopoints(i0,0), y0 = isopoints(i0,1);
|
||||||
|
const unsigned char
|
||||||
|
r = (unsigned char)img.linear_atXY(x0,y0,0),
|
||||||
|
g = (unsigned char)img.linear_atXY(x0,y0,1),
|
||||||
|
b = (unsigned char)img.linear_atXY(x0,y0,2);
|
||||||
|
isocolors.insert(CImg<unsigned char>::vector(r,g,b));
|
||||||
|
}
|
||||||
|
cimg_forX(isopoints,ll) isopoints(ll,2) = -ratioz*norm.linear_atXY(isopoints(ll,0),isopoints(ll,1));
|
||||||
|
|
||||||
|
// Save object if necessary
|
||||||
|
if (file_o) {
|
||||||
|
std::fprintf(stderr,"\n- Save 3d object as '%s'",cimg::basename(file_o)); std::fflush(stderr);
|
||||||
|
points.save_off(primitives,colors,file_o);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter event loop
|
||||||
|
std::fprintf(stderr,
|
||||||
|
"\n- Enter interactive loop.\n\n"
|
||||||
|
"Reminder : \n"
|
||||||
|
" + Use mouse to rotate and zoom object\n"
|
||||||
|
" + key 'F' : Toggle fullscreen\n"
|
||||||
|
" + key 'Q' or 'ESC' : Quit\n"
|
||||||
|
" + Any other key : Change rendering type\n\n"); std::fflush(stderr);
|
||||||
|
const char *const title = "Image viewed as a surface";
|
||||||
|
CImgDisplay disp(800,600,title,0);
|
||||||
|
unsigned int rtype = 2;
|
||||||
|
CImg<float> pose = CImg<float>::identity_matrix(4);
|
||||||
|
|
||||||
|
while (!disp.is_closed()) {
|
||||||
|
const unsigned char white[3]={ 255, 255, 255 };
|
||||||
|
CImg<unsigned char> visu(disp.width(),disp.height(),1,3,0);
|
||||||
|
visu.draw_text(10,10,"%s",white,0,1,24,
|
||||||
|
rtype==0?"Points":(rtype==1?"Lines":(rtype==2?"Faces":(rtype==3?"Flat-shaded faces":
|
||||||
|
(rtype==4?"Gouraud-shaded faces":(rtype==5?"Phong-shaded faces":"Isophotes"))))));
|
||||||
|
static bool first_time = true;
|
||||||
|
if (rtype==6) visu.display_object3d(disp,isopoints,isoprimitives,isocolors,first_time,1,-1,true,
|
||||||
|
500.0f,0.0f,0.0f,-5000.0f,0.0f,0.0f,true,pose.data());
|
||||||
|
else visu.display_object3d(disp,points,primitives,colors,first_time,rtype,-1,true,
|
||||||
|
500.0f,0.0f,0.0f,-5000.0f,0.0f,0.0f,true,pose.data());
|
||||||
|
first_time = false;
|
||||||
|
switch (disp.key()) {
|
||||||
|
case 0: break;
|
||||||
|
case cimg::keyBACKSPACE: rtype = (7 + rtype - 1)%7; break;
|
||||||
|
case cimg::keyQ:
|
||||||
|
case cimg::keyESC: disp.close(); break;
|
||||||
|
case cimg::keyF:
|
||||||
|
if (disp.is_fullscreen()) disp.resize(800,600); else disp.resize(disp.screen_width(),disp.screen_height());
|
||||||
|
disp.toggle_fullscreen();
|
||||||
|
break;
|
||||||
|
default: rtype = (rtype + 1)%7; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
27810
examples/img/CImg_demo.h
Normal file
27810
examples/img/CImg_demo.h
Normal file
File diff suppressed because it is too large
Load diff
BIN
examples/img/logo.bmp
Normal file
BIN
examples/img/logo.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 88 KiB |
BIN
examples/img/milla.bmp
Normal file
BIN
examples/img/milla.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
79162
examples/img/odykill.h
Normal file
79162
examples/img/odykill.h
Normal file
File diff suppressed because it is too large
Load diff
BIN
examples/img/parrot.ppm
Normal file
BIN
examples/img/parrot.ppm
Normal file
Binary file not shown.
BIN
examples/img/parrot_mask.pgm
Normal file
BIN
examples/img/parrot_mask.pgm
Normal file
Binary file not shown.
256
examples/img/sh0r.pgm
Normal file
256
examples/img/sh0r.pgm
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
P5
|
||||||
|
# CREATOR: CImg : Original size=180x180x1x1
|
||||||
|
180 180
|
||||||
|
255
|
||||||
|
窘拷揪揪烤烤靠靠靠靠靠究究澜纠窘两铰济宦纠纠两览两揽览嚼祭伎究靠靠靠郊换汉垢贩贩犯够骄窘己狗抖抖斗贩父阜付范范贩贩父垢汗还缓还换换换浇杭亢涣菇炯豢换拷患窘伎季浇拷窘窘炯郊冀己竞交技嚼祭娇究究究究靠纠靠烤靠谰祭阑柯姑凉殴藕戮辆铰量慌靠炕霉霉两究靠坷揽交付兜创闯膊扯购技窘己阜兜刀斗犯父父犯蹈蹈倒倒逗坊坊富讣讣购换蓟航郊读看没航碌辆妇究患亢兰窘娇伎伎伎痪蓟焕防妇患烤烤揪烤烤烤烤靠烤靠谰拷坷纠宦炯暮矫涣靠纠究驴娇偶铰寄鼓毫骄揪靠坷谰欢背富钩<EFBFBD><EFBFBD>櫅灐Μ掣汗洞吵吹斗腹垢父范返复傅沟狗构汗汗桓几缓缓换靖豢拷孤咕烤镀犊亢炕揪焕豪涣豢炯炕炕炕炯靖练拦净考澜烤烤靠究嚼究纠靠纠嚼窘潞暮览毫禄辆铰究苛究磕孤禄姆藕澜揪揪究靠胶副┄ⅱう<EFBFBD><EFBFBD>ぇ<EFBFBD><EFBFBD><EFBFBD>卑<EFBFBD><EFBFBD>泊捣腹构垢范抖刀捣斗犯构购汉夯够夯杭换蓟扛礁粱烤辜么鸥烤豢郊拦赂母禄究涣毫豪壕嚎噶妨附搅涣嚼娇究拷澜谰烤烤拷澜坷荒改冀晾孤玖骄揽澜澜霉沤韭浩豪揪揪揪揪揪沟副┉<EFBFBD>枎妸妺敜┃Η!ぇЁ┈<EFBFBD>捣构腹阜兜档档抖贩父构构汉汗汉汉缓换航孤杜独焦陆钙茨估郊究郝放杜估郊凉鹿梁考交抗练梁阑潞粱澜揽纠嚼究靠靠究纠究梁墓览交每毫谰辆韭侥郝搅拷禄谰揪揪浇蓟患狗矝倄kc]]aipv}墠寪殺灆洖·ǐ<C2B7>刀潮车档创吹档抖贩父构构构购汉汉换患痪该的杭霉矫彩称咐窘嚼郝改孤伎考粱阑拷伎唤竞篮窘潞潞禄澜靠嚼究靠靠靠究究娇阑两伎良济冀禄晾寄宦靠两澜谰揪究郊己覆<E5B7B1>杸_C8=96:AIS^ckt||z€唹崟潱Ι<E6BDB1><CE99>ァН吵膊吵吹刀斗贩构阜饭汉购汉夯换蓟竞粮揽箍练拾瞬乒究骄考粱录谰嚼嚼娇浇拦鹿拷浇嚼宦宦涣嚼揪澜靠靠靠靠靠究拷靠炯陆毫烤搅济季两辆久沽靠靠究靠汗浇顶塳N5(&*52/036<HT`hkhhqyyy}崪イⅴà晱槯捶床辈吵车抖抖贩返捶汗构构汉换技浇祭唤两浩呈采睹窘澜烤纠嚼究澜澜澜靠幻纺沽嚎冀良兰良澜靠祭究靠靠烤烤究嚼娇娇冀煤两澜烤坷拷揽粱驴靠靠靠烤附罋qUC3+-4<CFEB>;744:FY`YRT^kupz尃<7A>殈kpz€帰<E282AC><E5B8B0><EFBFBD><EFBFBD>渤嘲垂纠冬备阜犯构汉换冀骄娇考苛蛊非杜痪粱禄谰靠靠谰两录两纠蛊杜访壕骄烤窘粱谰纠娇靠靠烤靠玖耗孤伎拷篮澜究嚼嚼娇揽靠靠靠靠靠考郊磶TM>720--/15789::999=HRRNKMVisz}崡峺\R`ry|嚑ǐィⅲぇ<E285B2>煕オ鲍<E382AA>串<EFBFBD>陡腹购患浇揪烤两苛悸幻娇兰煤没辆揽揽辆两两谰铰鼓改沽嚼伎嚼炯粱揽嚼究靠靠烤玖耗盖访涣季谰嚼涣涣祭嚼搅嚼靠靠靠窘孤膹WNT<2*$!"%),03689:;<<>ABA@>>BUkr€哣7--1569Di儥槗悗憳潚ziccagy敚ⅲ<E6959A>刀刀腹患骄靠靠辆揽靠靠谰良录戮量晾量量揽揽览搅剂剂娇揪悸壕澜靠嚼娇揪烤烤靠幻豢古嚎剂季嚼宦郝涣涣宦剂究靠靠郊捞橇S"Z8%$$%&'*,0479:;;<==;:75540)1H^k`%&,.,***,<b寲湝<E5AFB2>z{oeegjcSPg姎灒┅ДΛ钡够娇坷览量量揽靠靠谰揽览览亮亮晾晾揽坷靠靠靠拷纠沽娇伎娇骄烤烤烤靠济嚎揽估窘骄娇郝该姑孤好郝娇靠靠净够号t"-. %)-1369<>?=<;::9741/.-+()1>>2#($=r崢梽z|xb`^[TONIKaw€垟潰いЛ捕辜纠懒亮亮晾揽靠靠靠坷亮亮亮亮亮亮览揽靠靠靠娇涣焕涣豪娇考靠揪究悸姑豢悸技兰拷祭孤孤孤孤毫伎靠靠拷复炊c+&#*057:;=??=:6310/+)&%$#!# #((Abg[SXTJBIPPKFEFFJT[`k亼洝お安锤娇亮亮亮亮览靠靠靠懒亮侣侣铝亮亮晾览览靠靠净篮潞赂煤拷娇窘考梁鹿霉禄禄坷毫痪净阑阑炕阑兰烤究靠炯阜瓅,!(/577777641-)&#! $'$$7>;8<97<BHIFB?ADIMOMReu儘槫<E58498>安附苛侣侣亮晾靠靠靠览亮侣侣侣侣铝亮亮览览靠伎郝纺放仿季骄剂郝孤孤毫焕豢郊阑考骄季冀季骄骄骄揪究拷几i&-231/..-+'# "&(")2/+-39<=<;878:=@@==>AFO`w寽<77>埠铰媚寐亮亮览靠靠坷亮侣旅寐侣侣亮亮晾靠靠净抗粮赂梁考窘考炕阑考拷窘窘骄骄浇浇郊郊浇浇浇浇揪揪娇精(#*-,)&$$$#!!%((%" "&&'(*-.0//./0379:;;:9756>Nk<4E>不豪呐穆晾亮览谅铝靠靠纠旅吕懒揽究揽窘娇撩冀痪痪痪季浇浇浇浇浇浇浇浇揪窘浇浇郊技技郊冀浇浇揪焦富旿 '*($ $(++($"!!"#$%&&&'(),.134554226==42x棷瓶究聊寐旅拿晾旅揽钠拍呐镁构季窘究拷祭门萍技技技技冀冀浇浇浇浇浇浇揪揪浇浇郊技技患技技技揪净箍<E58780>&"&$ #'+--)$!$&),0368::8669<91>[尵钠巧坡靠亮拷汉坏到坷还壕缆剖木缓换狗父构技技技技技技技技冀浇浇浇浇骄浇浇郊蓟患换换技技浇烤浇矑W"!!!&*./-(! $'+/25789:;<=;78@g煼焊姑辆坷窘咳侨考美侣窘坷揪谅竟贩返镀扇苹换换换换换换换换换换患浇浇浇技技蓟换蓟换患技技季郊瓇K,#&%"#)-00-%!$(+.02357:;9441K{⒉汗<E29289>殯洍敃妱唥z}uskedffb^]WPKHHGD@;986换换夯换换汉汉汉夯缓夯换患骄郊杭蓟夯技缓汉夯蓟傅夯瘎I' $/:?:1)" %+/0.)
#&(*,.146752.6?@2310+)-,''+'!&"#& #"$),*)+1.+*++)(7:::换缓构购汗构汗父够垢负浇换纠净夯桓陡换汉垢犯阜刀懦奞%#-7>>80)#"(,..*
|
||||||
|
!"$'*.1332052* "$%!#)' $$(/-0-)((&!!%*)(+010,'(*+购焊档捣贩饭垢档够苟豆浇抖航坏捶沟扯汗购父反脖掣綁K"$)*)'%#!#(++'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"&+/00.-($*%#'$(38044<EEMPPSZ`epy||~剨帋崣潯さ吹阜炒贩斗狗脖撤冻<E692A4>蹈烦澈富彻侥颈妇狡破睦壕<E79DA6>渾X.
###"!!%&$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%*.0//32f垥洓<E59EA5>牗<EFBFBD>富浇韭撬侍杏兴绦栽淹弦匝瓮趟夯环闯炒阜附谰唤绕敬<E7BB95><E695AC>洆攪乶onj_KE:'$$%/-6,!
|
||||||
|
|
||||||
|
|
||||||
|
&+/0278嫟犊颗哪趴揪靠揪滥评滥汕粕怂松乔颂送吞坍斗<E59D8D>鞍<EFBFBD>槏垈ug]PLD90-'"!!"#*'$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"',0557暀┋案九赡门破拿钠木娇侣履热缮壬适适噬蒟ZTF:4.&"" /155-#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$).46;墮<>坷懒晾缕乔排魄瞧排拿媚迫仕烫屯趟适<E8B69F> )/2:@V`qny}倠嫊湡<E5AB8A><E6B9A1><EFBFBD>焑B+
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"&*/26j挕不旅侣旅媚寐履破乔瞧哪钠侨墒颂烫颂趟"%498>IDGP[cjs€憶牎,撤犯寐玫创焕付床侗<E5BA8A>犊∣.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#'))&@q寽Ч苛亮侣亮谅妹呐排哪哪魄热墒仕怂怂烁贩复安睹量拷焊构骄焊铰酶毒究负换嫉脖隘<E88496><E99A98>畕(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#''",Nw灓醇坷览览览缆侣妹媚哪呐破侨壬缮适适<E98082>赋彻还捍背父斗搅粱负苛炯郊旱蹈汉洞巢<E6B49E><E5B7A2><EFBFBD>V
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#&"&4`湥惫娇揪究靠坷览亮侣旅媚呐破乔热壬缮驳巢卑捶狗斗杭冀棵辆换蓟汉患悍陡父兜荡潮<E88DA1>棁;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
!!(A墷<41>菇浇浇骄揪靠览览谅旅媚呐牌破乔乔父阜抖负汗腹杭技纠拷换换汉换汗阜范创创幢<E5889B>抃(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/d摛渤购夯患技浇揪究览览侣妹媚哪排排鸥阜贩犯汉汉汉患冀浇郊换缓汉汗父抖创吵吹氨瑨5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"C€洶胺父构汉患技浇揪谰览晾侣妹妹哪呐贩贩犯腹汉汉换技冀郊技缓汉汗父范创吵炒疮驳|
|
||||||
|
|
||||||
|
|
||||||
|
(Z仭<5A>刀犯构汉换唤伎祭嚼纠懒亮谅侣妹父父父构汉汉换患技技蓟汉汉父阜兜闯吵车唱ィD
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">h嫰<68>撤贩父购夯航嚎嚎焕嚼坷懒亮亮粮父腹构汉汉换换换患换汉汗垢阜抖闯巢炒党<E78292>}
|
||||||
|
|
||||||
|
!"! !!"!
?_洘Л捣斗犯构汉杭嚎箍豢伎究究览览构构购购汉夯换换换换汉汉腹阜范荡巢辈档播岾
|
||||||
|
|
||||||
|
"$#""#%()$ !(-,("
|
||||||
|
|
||||||
|
|
||||||
|
+G嚋Κ扯刀斗父构汉脊竟亢炕窘浇揪究构汗汉汉汉夯杭杭夯脊脊汗狗父抖荡帛<E88DA1>蛋疄p!
&'%#$&*/2*! !!"!!! ! !!""###$'/9>?<6-"
|
||||||
|
|
||||||
|
!5j暔┏反档犯腹构构还礁竞交技冀浇焦汗缓够杭夯患杭杭汉几汗垢狗贩档潮<E6A1A3>按┍<E68C89>;$
|
||||||
|
!*($$&).49/$ "###"""""""""##$$%%&&'()*,19AGKMLI@4(
'?l湯岛荡捣构父腹构桓焦胶换换换冀汉汉夯夯夯夯杭辜夯还还汗垢阜兜闯<E5859C><E997AF>槞塋/)
|
||||||
|
%+'%%(,16:0' #$%%%$$"#"""#$$%&'()*,,.04:@GMQSUURLC90&
|
||||||
|
%%#Fz<46>径豆缓阜父构汗桓脊缓汉构患己夯夯夯汉蓟换杭夯汉桓汗垢狗范洞嘲<E6B49E>|vt[(,'
|
||||||
|
|
||||||
|
&+'%&).267/' #&'''&%$$####$%%'()*,.147<AGLQUXYZYWRKD=4+!
&)1Qⅹ傅范斗够垢腹购够购购汉汉夯缓脊己缓患讣己缓缓夯够构构犯范档闯<E6A1A3>q}\4(.&
|
||||||
|
|
||||||
|
|
||||||
|
&*'%'+/364*%"&)*)('&%$###$%&')*+-049>CHMQVZ\^__^\WPJF?5)!
#+*0彽恫<E5BDBD><E681AB>疆<EFBFBD>饭构构构构杭浇娇技辜辜换还胶换换夯汉还汗垢狗范荡炊▄帎H'61$
&)'&)-1562%! $+/+))'&%$##$$')+-.049?DHMRX\`cddedca[UPLH>/&
|
||||||
|
|
||||||
|
)"t<>牏晲yu厽春汗构构构构级<E69E84>炯夯夯换换缓换缓夯汉还汗焊父贩兜创蛋~猳 NK0!
$(&'*/3995 "(34+))''%$##$&)-/138@HNQTX]bfijjjihge`[VSOE4)!
|
||||||
|
|
||||||
|
' Z巼bU3FFo櫚患汗构构构构伐媫郴缓菇辜夯换换杭汉汉汉构购父阜兜创党<E5889B>+&fH)
"&&(,16??=#-?:(()('%$##%(+048<DNVZ[^bgkoppponnlje_]ZVJ8-%
|
||||||
|
|
||||||
|
|
||||||
|
%( 8X`XK3BV挳芳己构构构购勾檥e<E6AAA5>杭还礁胶换脊靖换汉汉还焊父阜兜创亥<E5889B>.cC0$
$&).4:CCF"#7KA%''('&$#%',3;CJOU[_abeiptvwxwvutrohccaZL;1)!
|
||||||
|
!+( ;HUMJNu┇椿己构构构杭挤泘c肪几技辜夯换嚎毒汉缓汉购父垢阜兜闯氮<E997AF>/J8*#
"%)06<EFJ*!$CPH$&'''()+.4;CJRWZ]adghlqwz|}}}|{{zwkeidYJ=4-%
|
||||||
|
'-FPEBLx哎不己构构构辜澜甌L竟杭夯杭航辜椒婪蓟汉汉汗汗父贩洞炒節I:4/*#$*08>EGJ1! -GOL'((&').3:BJOTY]`cfiklqy~€們儌亖€倐nkoaTI>70(
|
||||||
|
|
||||||
|
)+),8D8BDw灕椿己构构构航揽礧L阑脊镜链蓝亢壕毒汉缓汗汗垢垢阜洞扯硏1(920'#")08?CGG3! (@JNK-,+(&(,4<DKRY]acfilnry€剢垑墖唴唺峬qqZPKB92+" "(**+50='a摪痘缓构构构杭揽竘S豢壕疵材裁督还竟换汉汉汉构父父兜捣終*I@2,&# '/8>BFC2('?[VQK8540,)+1:BIPV\_cgjnsz儔實彁弽妶嫄昹voROOG=5.% $&$',4(z犯负缓构构构杭靠簯i嘎汉椒赖麓抗蓟夯缓缓夯负汗父父阜贩繤8H<2-*#&.6=@C=4<C_maVOEA>;72017>FNUZ_dgkq{剫彃晽槚搷姀暅nvjMQTL@71)
|
||||||
|
!2=<3D>斗汉汗构腹夯季拷硩耗杭夯杭妇汉杭夯夯汉汗缓构构腹购构<E8B4AD>?MD543.#$-5<>?=E^isnc]WOKGEB>:5227ANX^bcjw剭憰櫅潪潣悑憳漵peNTXNB:5-#
|
||||||
|
G<慷抖购构狗还夯季窘晶宦敬栏焦技辜己换夯夯缓购汗构购患夯<E682A3>.QC69;0"$,6<@BK]ptqida^YTPNLJHC=505AKPWbv啋棛湡ⅲあ潝寫棜zibQWYO@<92(
|
||||||
|
|
||||||
|
+]?碳复腹构购坊夯冀交嫉祭壕房毒几交夯缓汉缓汉汉汗构杭技兜|>R79?@. ! "%-7@FP_ioomkigda^[ZXXWVWTOMRW^k|摐牎。ェЖΒ槑悥梺h`VYYL>=<6.%
|
||||||
|
8WB殴党豆构狗挤缓患交缓季航富己杭缓换缓汉夯汉汉构购唤换<E594A4><E68DA2>>K3>D=&&)(&%)0:DM[hmqrppomjhfdb```accejs}剫敐ⅵΘ┆<CE98><E29486><EFBFBD>憪晼噉aZ\WF:@>:3+"
|
||||||
|
"3RD<52>闯陡构购芳讣患蓟换冀几胶患辜换患缓购夯缓还汗购唤垢攰<E59EA2>?D5>@1
#031/.07AKVclpstutsrpomljihjmrvy~厡憰洟И<E6B49F><D098><EFBFBD><EFBFBD><EFBFBD>棑枛峸d^^U>7DB=81)
-IA<49>渤陡构垢焊脊蓟换换技缓焦换蓟换换浇汗夯换夯构构冀复巶|D=696#
-9:888;AKU^gmrvwxxwwutsrqpqtx}倖姀暀潱Й<E6BDB1>氨辈巢伯<E5B7A2>棙槕~ia`S68JFB>80%
|
||||||
|
)?>倒背陡垢腹够附夯换换患壕肪夯患换汗菇竞患换缓汗购技番憜zE920)
|
||||||
|
|
||||||
|
(7@@@CHMSZaglquy{|||zzyxxxxz}倖妽憳潯エ<E6BDAF>氨吵吹档幢珷洓殧俷faR3>PLHGA6+
(:@胶背犯父父购还唤换换换几抗换技换汗堡换技技汉构构蓟窛拤w<6+*
|
||||||
|
|
||||||
|
!'4BHJLS\dinqsvx|~€亐€~~~~亙唺帒敊煠З<E785A0>安车抖斗范钞<E88C83>灊棃ukcQ6JYUMPN@1
|
||||||
|
%9B炕车父父父购夯还唤夯换壕富蓟患蓟换竫<E68DA2>骄技缓构腹己矂噭s/3&#
|
||||||
|
|
||||||
|
|
||||||
|
$)5CNSWZajrx{}~亙剠厖剟儎剟唸妽悡枡灒З<E78192><D097>炊斗犯父付皑!牄<EFBC81>tiR9WebRVXK8#
|
||||||
|
6@换炊构父饭够换换脊蓟换几交夯患技己簗8骄技缓垢贩还<E8B4A9>u~w'/!
|
||||||
|
).5GRZ^afmt{亜唶噲垔墘墘墘妺媿帎摃槡潯ォ<E6BDAF><E382A9>炊斗腹构构烦<E69E84>ぃ灁<E38183>t[=`opXZ_UB(
|
||||||
|
4=稻捣构垢腹辜换换航汉胶咕购蓟换技蓟耿Υ冀蓟汗阜兜焊榁l~&)
|
||||||
|
-8>K[`dhkqy厞崓崕帋弾弾弿彁憭摃枠殰灎'<E7818E><EFBC87>驳犯负富购垢串<E59EA2><E4B8B2>枍噣mB_tz]\d[K,
|
||||||
|
2;戳捣垢构汉肪缓换缓患辜礁患夯夯换患几车杭蓟汗阜荡勾橵o{}(&
|
||||||
|
1HT\hjhkrx厞彃敂敃晻晻晼晼枛枟槞殰灍。Θ<E38082><CE98>炊父悍礁汉垢当<E59EA2><E5BD93>槕寛€QX{卋[icV0
.2航斗父换但<EFBFBD>缓换换缓己购脊换汉汉汉换垢够缓汗阜党覆焥qov)%
|
||||||
|
Ngpopoqv}儔帗枠櫄殯洓洓湝湝洓洓湞灍、うí<E38186><C3AD>刀负方芳购狗挡<E78B97><E68CA1>湑憢噃Gv巙Xjj_6
|
||||||
|
|
||||||
|
!6<冀锤阜几攊<E587A0>构换换换夯辜购还缓汉汉汉构汉汉构阜荡赴<E88DA1>zqq*#
|
||||||
|
&f~~wvx|倗寫暀湞灍煚牎 <E38080>牊灋灍、%Ж<EFBC85><D096>背捣垢挤脊还狗党隘<E5859A>煔枏妧O`僡ipi>$
|
||||||
|
%;D都掣贩蓟峈<E8939F>构患换夯缓焊汉够购汗构构构购汗构父洞赴<E6B49E>yqn,"
|
||||||
|
6s噦|~儑審挆洖牎ⅲ¥ゥゥゥイ"牋牎ⅲェí<E382A7><C3AD>贝斗腹够汉汗付党悲<E5859A><E682B2>洉崑qV`€rlurH-
|
||||||
|
|
||||||
|
&;L<>倍斗椒圴懊腹换缓还缓购汗桓汗构构构构构构构构洞喊瑵wpp4$
|
||||||
|
Gz崊儐嫃憯槣牏¥ゥΗЖěΗЁィⅰ、%Ж<EFBC85><D096><EFBFBD>泊捣腹汉汉汗范床悲<E5BA8A>ァ煕拲噏YutputQ8
|
||||||
|
'?W<>炒捣函搰寄父换汗购购垢构腹构构垢垢构构构垢购<E59EA2>撼盃|sr?+
|
||||||
|
U悊垗悡晿湣ぅゥゥウЗěイいぃ<E38184>牎うī<E38186><C4AB><EFBFBD>泊刀腹汉汉垢返床爱<E5BA8A>ア<EFBFBD>檼憢zqikooTB'
|
||||||
|
,C\棻党捶矾<E68DB6>铝腹夯汗构购负饭父构父父负腹构构狗苟尡焊疅倄sK5
|
||||||
|
|
||||||
|
!^剶噵悡枠湢うぁ牎 ·Жァ牉潨洔灍牏ォ<E7898F><E382A9><EFBFBD>安车斗腹构阜返床爱<E5BA8A>│"<E29482>槙槖塳fifUG0
!,BZ叄党捣烦祷郊腹汉垢贩购阜狗垢父腹饭父汗构汗狗激Pご户棄倀Z=
|
||||||
|
)e嫎垗摉槡灑あ洉枠殮殹èァ灈檿憯棙殲え<E6AEB2><E38188><EFBFBD>氨炒刀犯阜洞脖<E6B49E><E88496><EFBFBD><EFBFBD>#<EFBFBD>殫櫆湀qpgWM:$
|
||||||
|
)?X}洿贩贩捣够汗购汗党饭悍狗狗父腹腹腹垢构夯汉妨o`ザ鸡崕恮oE&
|
||||||
|
;d崣垙敆殱牎灀噭唵厔唵xpmiiimrz儔寧摑Κ<E69191><CE9A><EFBFBD>辈炒刀兜潮<E5859C><E6BDAE><EFBFBD>潩#潩ⅲ灆棗櫆枃€ueWG1
|
||||||
|
&=Us帺负父斗腹构购焊嘲豆焊犯犯阜腹饭父构购换旱兜X姲菇獘嫏wX3
|
||||||
|
|
||||||
|
>c帢墤枡湠灅寏sqqojggcRJE@==AIVjx亗剳牕┆<E78995><E29486><EFBFBD>膊膊碍─煘煗洐晵暁殮湜棎帍挄攷墌n_P='
|
||||||
|
"3Q`o〉还阜犯构购换懂<E68DA2>够贩犯犯饭祷豆构构杭几唇塯<E59487>妇睆倴墈lI%
|
||||||
|
?h彇寫枡洓攨uib_\VMGDB>962126;CUgtvt剹ⅵ┇<E285B5><E29487><EFBFBD><EFBFBD><EFBFBD><EFBFBD>弰{tnhaZW_mvy亝}z~儓媼寖ufZJ6 $COE煹己垢父构夯蓟川┒夯贩阜阜勾即焊腹购唤挤慷V櫤<56>竟<EFBFBD>實|s^8
>n彄崘晽晫~nc]ZYVPIB>:5/+)()-4>IXcidz帥ⅴ┇<E285B4><E29487><EFBFBD><EFBFBD><EFBFBD>弫uneYOHBB=;>ACM\hov|€剤崋{maUB) "1M+《技还构购患己阿Ц患阜贩父痘椿犯构夯冀脊縹Z环昂骄珛姀~smQ0<r帍帍挀媩lb]ZZZWRLFB<4.*('(+2;DNWa\s嚂潱ǐ<E6BDB1><C790>│<EFBFBD>棈乸bZPE=84642/029CNW_cgnz妶~rh_P6
|
||||||
|
/%J,ザ患己汉夯患己疄Ω冀父犯父付憾垢构夯缓缓烪惢驳杭镜爾晙yznS<
:x弻帊悗剈ic`__]XPF>9753211247<CIR\\p€彋牔<E5BD8B><E78994>ē<EFBFBD>晫p^PG=3-(#!"$%(,16:=@AEOc~剙wmh_E&
|
||||||
|
&9 6F<36>杭交换换患还瓲Ч冀父父父父饭父构汉夯匠j_陡倍够几<E5A49F>潅倖厈Y38}悏弻崐skgffec`ZSMJIE@:63368;AFNY^o{嫍煢<E5AB8D><E785A2>В灂媮reTI@70*&" !#%)059<>?CPmy|xqmhR1
|
||||||
|
|
||||||
|
)5#{倒航郊蓟换换狗<E68DA2>└骄父父父父父父构汗估臒L》钩饭换复瓱剦彁揾@%
|
||||||
|
4~巺寠寘yokjijklnqv}儌rdUF90-/4:AGR[nx垪煣<E59EAA><E785A3>В湊倂h[LB:3.,)%##$'+059<>@AA@DXjvwsqn]@
|
||||||
|
|
||||||
|
|
||||||
|
%-+淳窘揪技患缓狗串К菇扛父父父父犯腹购构疗tw档返腹汉苟皾嫃槣漷A/!
|
||||||
|
0}墐墘媬pkiklnmnpnikmoq|zqaJ1)*/6>ISjy嚄牘<E59A84><E78998>─潕{naRE;510.,)),-15:>>>@ADECBM[ltttqcL
|
||||||
|
"5#T赡量烤郊蓟垢洞艾<E6B49E>航靖腹父父父父腹购父沪i4礁饭夯还凡灀摕<E78180>塏2,( !r厑唸塹hilopokffaUMBAPWTT[\M<2//3?H[|嚈‖贝杯<E8B49D>潒tgYH=40/* &,--/48:;?ADFFELXepturdS&
|
||||||
|
|
||||||
|
&! <1D>辆烤窘蓟狗床<E78B97><E5BA8A>澈娇构腹泛犯贩父构汗汗彁坊竟购换缓狗<E7BC93>櫏<EFBFBD>歞21D9
|
||||||
|
h唦剢~W]ovtpjbVM<8Sr嫓殝oWONIB=73:BLt啘ぎ蹈恫哀潏m]M=3*&%$15==832215;@DGIHMXcmsvsfV)
勄坪唤窘蓟苟嘲<E88B9F><E598B2>岸冀靖构负豆犯贩父够娇矟犯换购换换缓共<E7BC93>┉牆w.-YZ5
Q亀亗rG{<7B>rlbT<7Gj帓媹yfUQNMKJHE>;?Ed儬Ρ航欢胆檭dO>1')=MUboqneWM?69?DHJKOZakruujV-
|
||||||
|
'#j斄脊唤浇缓傅悲<E58285>安倒冀竟构狗狗付抖斗够胶煵挤购换换换缓憾<E7BC93><E686BE><EFBFBD>w+'ZoP4pt{kQ6儜~mh_C5Pv€hB0(")AJHJKLKC?EW~(步晾换<E699BE>|X>1+*,;Yu儀d__ailhcXG@BGJMNSZ`jsuxqV-
|
||||||
|
f劅焕夯技蓟焊范兜斗腹冀揪构垢狗付抖档豆构⿷阜逗患技蓟换汗栋┉<E6A08B>峚-'Hi^7#+&NfmV`4唻zmfU;HkdB.%%0P?" QUFMORTODLNvΝ道琶览<E790B6>pJ3.,1>Zpn^RH?<>IWcniQA=DLOQV\]jtuywX+
|
||||||
|
Q<>概炕夯蓟缓构购汉夯冀浇竞汗垢狗范荡车狗畳暩蹈患郊蓟换换悍<E68DA2><E6828D><EFBFBD>L4/5O[Q:,!97*8DVT6寗zmdWCNTC?N@&() nmGKSY\]RSTlУ臼退抢異e>457K[e^NJL:##"!+?TZWI:<JPS[_[guuxy]+
+惿暇铰交换蓟换换换换技浇娇胶汉汗垢范床背副焺<E589AF>饭患蓟换换换悍<E68DA2><E6828D>泎G<<3<M[OA8Ko5"'p@7攩{nd\OFDJY[E-$23€刐NNUbkfUjj熀朴肿智祿_<:@Ke`QELk\& 01%/E=GRC:GPT_f[btxuwd-
S汗<53>纠交患患换换患技浇浇考竞汉购父返潮按寒枏督父够换汉患蓟苟哎<E88B9F>瀢RIMNNJVZSH[剝h.|;M搱~vmcZUV_feU?513<W妽oe`fpwqho儬灕缕嫉郸嘳@<JaaMJK[卭(!(\:.DF>GPTcnb_k|wxg-&6漂<36>揽郊技技换换蓟技浇骄娇竞缓还垢返潮案氦崶焦创泛技桓贩贩兜勃<E5859C>瀦b]gqwngc`Qy儏<79>;卋g槉厓€}xsqrv~噯pdfmx垖噣倕寘<E58095>:945GUUZ[TNRA7Dk{bSU`s崁2'!";kN25<BKPSfrphXwzh0."来捣辆郊技换蓟技患冀浇浇揪净杭够构付巢尘穼嵎礁吹返档腹壕焦兜钞<E5859C>泑nnz噺剅hcU!弶儢@~vn泹媼墕亅upmmt亸憮悐崚搼憫挃{<7B>)ey摠瀻媫oWYD+Iqzolo|噽岻3215=Vm[E98BMOTkxyjJZ寋n6
#(+,交斗澜蓟患换患换技冀浇骄揪净蓟己汗阜闯德猵牸骄档患炕礁炒<E7A481>┋膊悲渷wv€崜卹e[U(憫墮Y€唚檹彃搾崉{tnicafiigksz}€厠悋w<E6828B>(`惗淘谲谈唓_&Vnz剟剨審損OC96JjrcUJEIOS\r~|pVG妔Y,
#,+c煽贩炯蓟换患夯患患冀骄揪究炕技蓟缓狗党到i布及俧cbjtwi]_es懍荡脖爢{|厰攦oaOQ9悧彎姍啌憭晿様寔wrpoopplhhklmr{墝||r$y谷人汕桥潅]'cp{寘噳垐媼憴棈垉p`URU[`cn<6E>vIY乯-* %+%;P痉坊换换蓟杭换换换冀浇浇骄交蓟蓟缓复车県嵓患盃0搏<EFBC90>櫁煥不还冻肠<E586BB>倞槖俴]IHK摓挍妛<E68C8D>搻摌湜槗妦sliiihfc`_cp}啀媻Lc3壙氖仙那搂欳+Ygz媴垍€yrplga[^a]ZZ`mz{y€姀厁B`I="<#&%"}铰冻垂夯换杭换换缓汉垢抖斗购冀唤技蓟复犯<E5A48D>独锤膊附礁吹饭阜斗腹反惮搫垗槕乮^NIV枮挅孿湧殣挋煙潥枎乼kd_chmt|垞棗攼<E6A397>:_U櫪认盐敲绩<E695B2>;1FP亴妿巻xiaacfhgc``fq亴寠帞晫wTb1' 2:"$"(Ω悲<CEA9>饭缓夯够换换汉沟<E6B189>Ж<EFBFBD>苯痪冀浇挤彻瓋傅兜缓垢负焊犯汉垢负焊档瘶噹彇悂iaZVg暀挃攃v"敂槧!牊湑崋倐墛姂殶煗湚櫃pGk<47>释烫肆滑滼4;=帋悞晳僺e]ZZ]]_diq{垚挃棙棎dZ?_XH($ "' )ク<><E382AF>饭汉还缓夯换购憾<E8B4AD>煙。<E78599>炯浇骄椒驳恎背坊季技换技唤揪郊蓟焊档矟墦挄憙necn潣挃敆區ǔ崗殲ぅΗě<CE97>牊湚殱牐!牄ΑpC|<7C>鞘颂死韩燷4FY殣摃槝悈|qia[Y_hqz啈槢洓殫悂p_Noub+26541./9>!<o惄泊泊饭夯讣购夯冀阜己桓铂А熅痪浇骄靖腐b澏<62>窔蓟饭换技冀浇技缓傅挡<E58285>槙棔唗nr尟憣晻敆崊噩崨湤エ<E6B9A4><E382A8><EFBFBD><EFBFBD>あ'┃#イ<EFBC83>>y摣睹商紊抗珮~;Us湑晽洑枑寢垍儏崝枟洝ⅱ灈殩恾僝q厒o;!7=FNN@<E`~潤Ο范刀腹汗几汉汉痪龚<炯沟<E782AF>灱窘浇娇径秾t辜卜﹋痘逗换技技技技缓付挡瓔潥殬<E6BDA5>垻畧垟棓槣Z撥煝殰ˇ<E6AEB0>北爱<E58C97><E788B1><EFBFBD><EFBFBD><EFBFBD>梾Mp嫅<70>寥舷染伐晪VZ枟枤灎灉湡牊煟И<E7859F>īВ灇棏寢匤厡zsN$6=HYaA<Vx煪毃<E785AA>付腹购汗缓汗够骄<E5A49F>稻夯覆ā浇浇浇揪东pし环稓`负逗换技技技换汉付当矏、灉晱摐<E699B1>啌枖棤枅y嗜瘺灑Λ<E78191>鞍隘<E99E8D><E99A98><EFBFBD><EFBFBD>峃v垬<7F>廊蜒萍担様yl}晽枩ⅴΖΖΗΗ┇<CE97><E29487>Β湕晱晬b\槖俿\+7?L_gHBnn枮灒<E69EAE>垢腹汗汉汉构够嚎<E5A49F>*灪缓捍<E7BC93>窘浇蓟玖緩}惫贩硿偭阜夯换换换汉汉垢返贝枹<E8B49D><E69EB9>湣Λ泏剱晵敍湚哬<E6B99A>禐煟ЗЖ<D097>氨北艾珰塡唹厫灟毫捎优共<E4BC98>攪}o彈槤え<E6A7A4><E38188><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Α檿搸憢H彎厊sc97BRejMPhH悺<48><E682BA>垢父购购购构够痪笿嵒缓旱<E7BC93>浇浇换颗礯湹阜凡<E9989C>姆负换换缓汉汉汗父恫礇灜┃ゥЖ<E382A5>w倣搼挅潰枈tα<74><CEB1><EFBFBD>ō卜范繁<E88C83>峸櫊儕敜臣滤栽歉埃枏<E59F83>e|悧灔┇<E78194><E29487><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Д灂憫枺檘拞|tfP;BUjmJiL€ⅳ牞饭垢构负购汗构痪椒櫁靖购诞ň浇交豢脗]苯豆洞坊痉负汉换汉缓汉构垢返碃敨<E7A283><E695A8><EFBFBD><EFBFBD>y€嫅悜敆棜攷悅椆咸嫉讣拿欢<E68BBF>帊槡寪櫄<E5AFAA>颗握杖腐<E69D96>悑僲q亼湨<E4BABC><E6B9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>В<EFBFBD>棊帓珱Ow倓倈thiDDXnpQ<70>1\洠<>腹垢构汗汉构购痪椒奖几购动<E8B4AD>浇交搅絃樅脊沟蹈汉父汉汉汗挤几汉构父反<E788B6><E58F8D><EFBFBD>荡<EFBFBD>攟~垘彁摉枛枠檿剗儧钙舆阕粸憤悧棛拰棟牤宦尚种斯唉洅崍{vy倯Ο<E580AF><CE9F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>牊煋彏槷K寪倓亂pfzPK_sre<72>.嫭0购父购购汗汉汉唤礁换还构繁<E69E84>窘浇烂礢祷附苟斗父腹购汉辜方都腹构构苟瓝槳<E7939D>豆勃渶{唺寧憯晻晼櫃拹摍ˇ┈<CB87><E29488>殮殮棖憭洜Σ酒逃字秃畅潟帄儈~}湵饱エ<E9A5B1>èΔ瀿帴<E780BF>贾UWv€唦€|tkf}YTitp亀K<>祷还构购汉够购汉换购换构垢<E69E84>揪浇桓皸J洺壕桓斗父腹构购焊级椒汗垢腹苟啊棫铂备传瀮v倗墝彃敃敃棗晻槢潪煛¥<E7859B>洑槜晸挅灑ù郎卧刂位传<E4BD8D>悑唩亙剬ê睜ⅶГ#!檪棳肱Xx亷|}||wohj}``rpi扝!x卜郊构构汉讣富购汉汉汉汗父丁幗浇焦椽<E784A6>?Rb~湱刀贩父腹构负焊挤焊父父垢弹<E59EA2>┛卑礁<E58D91>剆~剢墠彃摂晼枙敄槡洓潩灉殭槜枖摂櫊+睹萄兆治嫉<E6B2BB>殦巿個儑姈熀平啊棔棙櫘<E6A399><E6AB98>鄩\啇寙{{{xrljpxflxnn<6E>"W倒窘汗构汗挤椒还汉汉构垢贩穿⒔浇浇玖榔莱扯贩贩犯负饭构负汗汉父父父苟<E788B6>煋碍ň澜瑓ty儑嫀悞摂晼晻枟槞殮洓殭櫂棖晹棡う<E6A3A1>耐言衷尉懂<E5B089>様崈亯嫎<E4BAAF>}lu倞憰巘MQo搵z墖€|zzxtnjkqtox{nwlk杭烤汉购夯妇毒坊构构构阜陡焦督浇究僚禄犯苟档斗犯付环构焊汗汗垢阜犯构伯<E69E84><E4BCAF>湦膊<E6B9A6>qsz~儓嫀悞摃晼枟棙櫃殯洑殮櫃槜棞ぇН改滔延彝糠<E5BD9D>牆洉媭墡棜帞殯枔敄枏巣<E69E8F>}€厑~|zxuqljkrv{zo凙?壓嚼胶汉汉杭附芳负汗构垢贩患爣窘浇郊技交构范抖贩犯憾桓构汉汗汉父贩饭憾<E9A5AD>@V塿lknh__ksy剦審憭敃枟棙櫃殯洔湝湝洓殰*<E6AEB0>胺辽掏瓮士贡<E5A3AB>煙煏<E78599>姁晻敄槝棔晼晭妴垐噞€~{xurnkhlu}剙z€<7A>$|挼娇交换夯够还还还购构狗贩罕_娇浇郊缓反膊吹抖贩阜泛坊负购购汉焊范饭换躬>)Votd\YVZhpt{亣妽彂摃枟槝殮洔潪灍煘灊潬┉<E6BDAC>岸灸巧噬瓶共<E793B6>煚<EFBFBD>崁寫晻搼憭挀敃攽帉媻坿~~|zvspljfo|厠亝憥N敇凹窘蓟换杭够汉汉购构垢阜饭磼}拷窘郊焊兜吹抖贩贩犯阜焊汗购汉夯己阜负汗焙抦QEay個pkmqrw~剤嫀悡晼棙櫄湞灍牎 ⅰ牊+<E7898A>┋岛柯牌泼靖报煔櫉爼亷晿棓拺憫拻摀憥寣妵~}|zwtqnkjbv厡拡搵V
|
||||||
|
0創“唤郊换杭辜够夯汉构汗垢贩够<EFBFBD>娇揪交悍荡刀犯贩贩贩犯饭构汗购夯窘阜航脊闯<EFBFBD>]17D[ntzutprz亞妽悞晼棛殯潪煚ⅱい#<E38184>ˉ<EFBFBD>湬岸夯季谰捍<E8B0B0>棎彅殨亹洓殩敁拻拻拻悗寢墕~|{yuqnljj]{垘拤杹%n<>“航郊换脊焦几脊还汗构垢父构抱烤烤窘烤憾捣父阜抖抖贩犯购汉汗垢宦拱防炕窗<E78295>c)+ 9Myyqqv~剤嫃挃枠殯潪牎ⅳゥΖΒ潨潧張槪<E5BCB5>鞍车窗<E8BDA6>晞y|厠<>憻灉櫁晹摀拻憪帉妶<E5B889>|ywsolkieWr{{寖] `槹┇彻技蓟焦竟礁靖几几桓焊垢父复<E788B6>靠烤纠侗<E7BAA0>捕抖档荡吹斗腹购汉构董<E69E84>人两繁帆|[;4&i乼st{倖妽憯枠殰灎。ぅΗЖá棊厏m^j摛イЖΒ湈y`V`nwy悺牆洐棖晸搾憪帉墖儈{xupljjg^T`pz亴S(<櫗超<E6AB97>够技脊靖胶几礁级蕉降桓父阜嘲揽揽净禂噣垯Κ<E59EAF>膊膊吹犯构汉汉汗磿s嚛醇舶藩刕B;(@vqtry剤寪摉槢潪牏ぅΗè┅爺墂kXIM[r崚挄攷寘lN:7CUcss師牊潧櫁枙搾憦崑墕倊zvrmigjg__q|uml2"g\)<><EFBC89>够技痪妇汉换辜妇蠢尘岛父付碑懒亮焦瘋fal倴々<E580B4>鞍辈炊饭汉换缓苟矎<Ng埄画瓑i:>-G+btsqv}倖嫃摉櫅潫。うЖ<E38186><D096>煈噁O8.+/GeqtxupqhF+#%0DWmq対<71>灊洐棔敀憦崑垍倉ytpkeflncfliQ8!,V櫅q牑<71><E78991>够技脊竞患辜汗级啦敛椒父付<E788B6>亮亮交穾NQaw嫓Μ<E5AB93><CE9C>安捶购患己还交<E8BF98>CTW^灛箳`KO6O$Fupty剦帗棛湠牏%Θ┆<CE98><E29486>拵iI:2-)1ESX\ZYXM0"!%.ATku帨ⅱ牉湙槙敀憦寠噭€|wrmhcgrpOG>&3啰罉嚙Θ<E59A99>倒换蓟交患夯换汗酱啦慷焊阜淡Я谅陆伎濦Oew姕Μ<E5A795><CE9C><EFBFBD>炊购患己淮<E5B7B1>瞷FHKBZ姷焁fq&2(€ursw}倗崚枤湠牏うЗ<E38186><D097><EFBFBD>晼wSA9632;CGGGGE>1.129I[o|挐#<E68C90>湜槚敀悗寜唭ztojfckud'"_潯<5F>灚ī<E7819A>豆换蓟蓟蓟航讣夯附纯椿父阜惮チ侣媒焕燞Zr€憿ǐ<E686BF><C790><EFBFBD>炊负患胶即境朾ZJ7&8帩mb<6D>(#zuwvw{厡憱殰煚ⅳェ┆<E382A7><E29486><EFBFBD>瀸lWKJHA===;;;;;<ACDJWgx啒牓ぁ煗殬枖拹帇垍倉xrmifepvN x<>ぅ<EFBFBD>ī<EFBFBD>逗换唤杭脊康炼己桓级挤垢父船ち旅慕寂濺Ri{懁Й<E68781><D099><EFBFBD>炊负患己悍z彻瑏qa8+C€}f<>, #hw{yxz}儕悤殰灎ⅳΗí<CE97><C3AD><EFBFBD><EFBFBD>噋`XUPG?<;:::>EKPU\hw啇潱Δ<E6BDB1>潥槙攽弽妴<E5BCBD>{uokhhgr|(
|
||||||
|
r*<72><EFBC8A>í<EFBFBD>逗换己冀仿衬擦负汉购负父阜船ぢ旅沤磕<E6B2A4>9;Xn姟(<E5A79F><EFBC88><EFBFBD>扯腹夯缓构У矾晍](!*;[k<>(+Wt|}yy|亪帞槣灎。ェ┆<E382A7><E29486><EFBFBD>Α枅{qi^RE>988<DOX`hoz噾槨イ 灉殫晸憦寛剚}ysmjjiksv
|
||||||
|
P敒朝<E69592>í<EFBFBD>逗患患椒虏挪牡交够购腹垢付倡っ媚啪铝僀B\n垵牔<E59EB5><E78994><EFBFBD>车腹夯缓够构钩▇HLGU劅!35>x}~{y{啀挆洕煛¥Θ<EFBFA5><CE98><EFBFBD><EFBFBD><EFBFBD>攭vk]MC=:<CN[enu}啇棞ⅳ!煗洐枖拹帇唫~zvpljkknr_ ,l嫴<6C>è┉岸夯患还赖么麓抗杭讣坊腹阜恫<E9989C>妹呐韭<E59190>\Rbn儣湥<E584A3><E6B9A5><EFBFBD>车饭购汗构父挤磭O#`T^喆`+AR7AHOz|~|yz~剫憰櫆灎ⅳェ┆<E382A7><E29486><EFBFBD><EFBFBD>檹唦tfUKECGO[gpw|儗敋灐ⅰ煘湙槙搼弽墑{xtokkmopn;
|
||||||
|
Q叒<51>Ηǐ<CE97>夯换技咕妇缚富几椒椒焊阜当<E9989C>媚排搅線JMdn}帞灙<E5B89E><E78199>俺刀腹购构父富阜攐J"$a[v}灮FAs巹弳v}~}zy}倝帗棜潫牏うЗ<E38186><D097>┃<EFBFBD>殥媴}p_UPOT[fpx}亣悥殰灋灊湚槚搾悕媷倊zvqmkkorqio殼<6F>いお<E38184>够患杭换换蓟换辜方痘饭贩幢<E8B4A9>媚牌伎紏MOcir亰棬<E4BAB0><E6A3AC>安刀腹腹构父负憾歿V-,Zm億兗奊s垊<73>亐~{z|亣寫晿洕煚ⅳェī┄Δ<E29484>殧強剒kc_]`fow}亝姁晿櫄殮殬槚敀悗寜厐{wtpljmrvu`
!懃<><E68783>灋ó逗换患换换换换换够富腹阜反皑∶呐萍竟uTUccgt~彜<><E5BD9C><EFBFBD>刀贩悍汗父父即檧]B3Feu}彍怸r<E680B8>8~厑€}z|€厞彃枡洕灎ⅳウΖィ<CE96>湗晳帄剒tpnosy剢墠悞敃晼棖晹搾悗寠噧~zvrnjjowzvH -'枻牬瑳摋ǒ泛换换换换换换缓汉还汗父反哀犆呐墙级n]Ya_cox姞í<E5A79E><C3AD>捣饭痘负汗父匠煇vPB9Rl寗~+<><EFBC8B>厡們~||儑嫄敆櫅潪牋ⅲ#<E285B2>潧櫁晸拸寙倊}}亝墜寣崕帍彁憫拺憪弽寠噮亅wspljkqzxn*
7NРΧ珨姇<E78FA8>负换换换换换换换缓汉构父反哀犆呐凭汗nYS\[anv厹Θ┇<CE98>炊贩坏汗汉垢话<E59EA2>卐N:?Lw剘姕篂D i<><EFBFBD>}}倕墠悢枠洔潪灍煘湜櫂棖敂敂搼弽寢實帊寣寣媻妺實帋帋崑妵厒~yvqnkikpytf
|
||||||
|
!"Acu俺<75>獥枺捶购汉汉汉夯患技缓汉汉构垢返唉犆媚偶患kPN[Zalr~槬Θ<E6A7AC>驳贩苟挤汉汉腹獟<E885B9>|UD9>Sotx€慛
A巰<41>~~亙唺崘摃棙槚敂敃棗棗晹憪憫摂棜洑晲寜垎唵厔們儍儏噳妷噭<E5A6B7>{wsoljhkpurk '@3;o﹙Ξ<EFB999><CE9E><EFBFBD>构汗购汉购汉患技汉汉汉汉垢返唉犆媚暮骄oKL^\cimw敚ウ┊扯贩泛逗购汉贩﹜<E8B4A9>tQFD:EV]_YO#€<E282AC>~亜唹嫀悜憦墐€€儑噰垐垐噯唵垙槢殨搶厑|xwx{{|zvuvx~儎個~{xtqnkiijpssj 3T/@摳w澃<77>辈豆构构垢父构垢辜蓟贩父构汉汗返唉犆媚墓季|QObcgjkw悽ぅó扯犯阜桓购汉贩畊<E8B4A9>mUQP9BJKF1i{坿~€亜唸墛妵倅nggkswwvtsqpqstu~垔剒ulfeedeee_]YTTV^jw|}|zxurolkiijnprT .WN€拱{⒊驳吹贩犯犯贩兜附降吵蹈负脊贩够缓付哀÷媚墓构奰Xfkkkk{悽¥Л捶犯腹腹构汉范祦カ俶oG6:H?-Px剕}~}}~€們儌yqdULGGNTX[]_`acdbahqqka\TQRQRQOJA?=;>BIVhrvwvtrpmkjiiilnm3H捄酱u<E985B1>炊档刀贩贩恫<E8B4A9><E681AB><EFBFBD>戮骄焊季苟泛己苟报⒚媚暮沟峧cnqmkiz懀"Ν蹈父腹父构汉范穽灖墌t409E0
8wzy||||}}~~}ysj^PC<536;BHMOQRRNHDHMMLIMKJHEC@;4-,.169=IZgnqrqomkjihhgknk
)淮脊z┐抖档抖贩返喘い<E59698>tfmy嫙Η<E5AB99>悍都良悍暴⒙媚没降噅ivqigfr帰!-陡构父父腹汗贩祽敁|乚13E:
|
||||||
|
!tyyuzzzyzzzywrld\TOOMJOXadaYROOOKBA?;==?EKNOSUTWTYbkpja[\agkmmlkjihhhejkc3牡惀狈返刀贩犯反爱<E58F8D>僛>>CIMF@P€暆枺两脊暴⒙媚戮凉xdl|necdm垺 …负构垢垢腹够构皨唦u€R?GO*
guwpvxwwvvutrpmlkkpy~~}|亪垉}|}zscZPEIP_nyzy}}xrnt~唵}tnhefhjjjiihghfbheI |