aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 17:24:39 +1000
committerDavid Walter Seikel2013-01-13 17:24:39 +1000
commit393b5cd1dc438872af89d334ef6e5fcc59f27d47 (patch)
tree6a14521219942a08a1b95cb2f5a923a9edd60f63 /libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib
parentAdd a note about rasters suggested start up code. (diff)
downloadSledjHamr-393b5cd1dc438872af89d334ef6e5fcc59f27d47.zip
SledjHamr-393b5cd1dc438872af89d334ef6e5fcc59f27d47.tar.gz
SledjHamr-393b5cd1dc438872af89d334ef6e5fcc59f27d47.tar.bz2
SledjHamr-393b5cd1dc438872af89d334ef6e5fcc59f27d47.tar.xz
Added Irrlicht 1.8, but without all the Windows binaries.
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/README.txt4
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/COPYING340
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/LICENSE50
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.mingw32130
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.sgi104
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.unx132
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.w32113
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/README186
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/makevms.com132
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng.c311
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng.h88
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c511
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.h116
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readppm.c179
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-win.c728
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-x.c904
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng2-win.c1253
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng2-x.c2107
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/toucan.pngbin0 -> 12901 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/wpng.c853
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/writepng.c400
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/writepng.h133
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c9837
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/README10
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/makefile150
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/pngusr.dfa39
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/pngusr.h24
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/README10
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/makefile149
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/pngusr.dfa35
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/pngusr.h24
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/README15
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/makefile165
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/pngusr.dfa40
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/pngusr.h24
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/README153
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makefile.std65
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makefile.tc338
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makevms.com92
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.bat41
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.c430
-rwxr-xr-xlibraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.sh42
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pngminus.bat4
-rwxr-xr-xlibraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pngminus.sh5
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.bat41
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.c533
-rwxr-xr-xlibraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.sh42
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g01.pngbin0 -> 164 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g02.pngbin0 -> 104 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g04.pngbin0 -> 145 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g08.pngbin0 -> 138 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g16.pngbin0 -> 167 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn2c08.pngbin0 -> 145 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn2c16.pngbin0 -> 302 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p01.pngbin0 -> 112 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p02.pngbin0 -> 146 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p04.pngbin0 -> 216 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p08.pngbin0 -> 1286 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn4a08.pngbin0 -> 126 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn4a16.pngbin0 -> 2206 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn6a08.pngbin0 -> 184 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn6a16.pngbin0 -> 3435 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn1g04.pngbin0 -> 429 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn2c16.pngbin0 -> 2041 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn3p08.pngbin0 -> 1499 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbgn2c16.pngbin0 -> 2041 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbgn3p08.pngbin0 -> 1499 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbrn2c08.pngbin0 -> 1633 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbwn1g16.pngbin0 -> 1313 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbwn3p08.pngbin0 -> 1496 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbyn3p08.pngbin0 -> 1499 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n1g08.pngbin0 -> 719 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n2c08.pngbin0 -> 1594 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n3p08.pngbin0 -> 1476 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp1n3p08.pngbin0 -> 1483 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/PngFile.c450
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/PngFile.h30
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/README.txt61
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.c969
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.icobin0 -> 766 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.pngbin0 -> 208 bytes
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.rc152
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/cexcept.h248
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/resource.h23
84 files changed, 22715 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/README.txt b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/README.txt
new file mode 100644
index 0000000..7e9b7d0
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/README.txt
@@ -0,0 +1,4 @@
1
2This "contrib" directory contains contributions which are not necessarily under
3the libpng license, although all are open source. They are not part of
4libpng proper and are not used for building the library.
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/COPYING b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/COPYING
new file mode 100644
index 0000000..c2d382b
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/COPYING
@@ -0,0 +1,340 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Library General Public License instead.) You can apply it to
19your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40(2) offer you this license which gives you legal permission to copy,
41distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
281
282 How to Apply These Terms to Your New Programs
283
284 If you develop a new program, and you want it to be of the greatest
285possible use to the public, the best way to achieve this is to make it
286free software which everyone can redistribute and change under these terms.
287
288 To do so, attach the following notices to the program. It is safest
289to attach them to the start of each source file to most effectively
290convey the exclusion of warranty; and each file should have at least
291the "copyright" line and a pointer to where the full notice is found.
292
293 <one line to give the program's name and a brief idea of what it does.>
294 Copyright (C) <year> <name of author>
295
296 This program is free software; you can redistribute it and/or modify
297 it under the terms of the GNU General Public License as published by
298 the Free Software Foundation; either version 2 of the License, or
299 (at your option) any later version.
300
301 This program is distributed in the hope that it will be useful,
302 but WITHOUT ANY WARRANTY; without even the implied warranty of
303 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 GNU General Public License for more details.
305
306 You should have received a copy of the GNU General Public License
307 along with this program; if not, write to the Free Software
308 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
309
310
311Also add information on how to contact you by electronic and paper mail.
312
313If the program is interactive, make it output a short notice like this
314when it starts in an interactive mode:
315
316 Gnomovision version 69, Copyright (C) year name of author
317 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318 This is free software, and you are welcome to redistribute it
319 under certain conditions; type `show c' for details.
320
321The hypothetical commands `show w' and `show c' should show the appropriate
322parts of the General Public License. Of course, the commands you use may
323be called something other than `show w' and `show c'; they could even be
324mouse-clicks or menu items--whatever suits your program.
325
326You should also get your employer (if you work as a programmer) or your
327school, if any, to sign a "copyright disclaimer" for the program, if
328necessary. Here is a sample; alter the names:
329
330 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331 `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
333 <signature of Ty Coon>, 1 April 1989
334 Ty Coon, President of Vice
335
336This General Public License does not permit incorporating your program into
337proprietary programs. If your program is a subroutine library, you may
338consider it more useful to permit linking proprietary applications with the
339library. If this is what you want to do, use the GNU Library General
340Public License instead of this License.
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/LICENSE b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/LICENSE
new file mode 100644
index 0000000..40a0c8e
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/LICENSE
@@ -0,0 +1,50 @@
1 ---------------------------------------------------------------------------
2
3 Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
4
5 This software is provided "as is," without warranty of any kind,
6 express or implied. In no event shall the author or contributors
7 be held liable for any damages arising in any way from the use of
8 this software.
9
10 The contents of this file are DUAL-LICENSED. You may modify and/or
11 redistribute this software according to the terms of one of the
12 following two licenses (at your option):
13
14
15 LICENSE 1 ("BSD-like with advertising clause"):
16
17 Permission is granted to anyone to use this software for any purpose,
18 including commercial applications, and to alter it and redistribute
19 it freely, subject to the following restrictions:
20
21 1. Redistributions of source code must retain the above copyright
22 notice, disclaimer, and this list of conditions.
23 2. Redistributions in binary form must reproduce the above copyright
24 notice, disclaimer, and this list of conditions in the documenta-
25 tion and/or other materials provided with the distribution.
26 3. All advertising materials mentioning features or use of this
27 software must display the following acknowledgment:
28
29 This product includes software developed by Greg Roelofs
30 and contributors for the book, "PNG: The Definitive Guide,"
31 published by O'Reilly and Associates.
32
33
34 LICENSE 2 (GNU GPL v2 or later):
35
36 This program is free software; you can redistribute it and/or modify
37 it under the terms of the GNU General Public License as published by
38 the Free Software Foundation; either version 2 of the License, or
39 (at your option) any later version.
40
41 This program is distributed in the hope that it will be useful,
42 but WITHOUT ANY WARRANTY; without even the implied warranty of
43 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 GNU General Public License for more details.
45
46 You should have received a copy of the GNU General Public License
47 along with this program; if not, write to the Free Software Foundation,
48 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
49
50 ---------------------------------------------------------------------------
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.mingw32 b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.mingw32
new file mode 100644
index 0000000..a736556
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.mingw32
@@ -0,0 +1,130 @@
1# Sample makefile for rpng-win / rpng2-win / wpng using mingw32-gcc and make.
2# Greg Roelofs
3# Last modified: 2 June 2007
4#
5# The programs built by this makefile are described in the book,
6# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and
7# Associates, 1999). Go buy a copy, eh? Well, OK, it's not
8# generally for sale anymore, but it's the thought that counts,
9# right? (Hint: http://www.libpng.org/pub/png/book/ )
10#
11# Invoke this makefile from a DOS-prompt window via:
12#
13# make -f Makefile.mingw32
14#
15# This makefile assumes libpng and zlib have already been built or downloaded
16# and are in subdirectories at the same level as the current subdirectory
17# (as indicated by the PNGDIR and ZDIR macros below). It makes no assumptions
18# at all about the mingw32 installation tree (W32DIR). Edit as appropriate.
19#
20# Note that the names of the dynamic and static libpng and zlib libraries
21# used below may change in later releases of the libraries. This makefile
22# builds both statically and dynamically linked executables by default.
23# (You need only one set, but for testing it can be handy to have both.)
24
25
26# macros --------------------------------------------------------------------
27
28#PNGDIR = ../..# for libpng-x.y.z/contrib/gregbook builds
29PNGDIR = ../libpng-win32
30PNGINC = -I$(PNGDIR)
31PNGLIBd = $(PNGDIR)/libpng.dll.a # dynamically linked
32PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng
33
34#ZDIR = ../../../zlib-win32# for libpng-x.y.z/contrib/gregbook builds
35ZDIR = ../zlib-win32
36ZINC = -I$(ZDIR)
37ZLIBd = $(ZDIR)/libzdll.a
38ZLIBs = $(ZDIR)/libz.a
39
40# change this to be the path where mingw32 installs its stuff:
41W32DIR =
42#W32DIR = /usr/local/cross-tools/i386-mingw32msvc
43W32INC = -I$(W32DIR)/include
44W32LIB = $(W32DIR)/lib/libuser32.a $(W32DIR)/lib/libgdi32.a
45
46CC = gcc
47#CC = i386-mingw32msvc-gcc # e.g., Linux -> Win32 cross-compilation
48LD = $(CC)
49RM = rm -f
50CFLAGS = -O -Wall $(INCS) $(MINGW_CCFLAGS)
51# [note that -Wall is a gcc-specific compilation flag ("most warnings on")]
52# [-ansi, -pedantic and -W can also be used]
53LDFLAGS = $(MINGW_LDFLAGS)
54O = .o
55E = .exe
56
57INCS = $(PNGINC) $(ZINC) $(W32INC)
58RLIBSd = $(PNGLIBd) $(ZLIBd) $(W32LIB) -lm
59RLIBSs = $(PNGLIBs) $(ZLIBs) $(W32LIB) -lm
60WLIBSd = $(PNGLIBd) $(ZLIBd)
61WLIBSs = $(PNGLIBs) $(ZLIBs)
62
63RPNG = rpng-win
64RPNG2 = rpng2-win
65WPNG = wpng
66
67ROBJSd = $(RPNG)$(O) readpng.pic$(O)
68ROBJS2d = $(RPNG2)$(O) readpng2.pic$(O)
69WOBJSd = $(WPNG)$(O) writepng.pic$(O)
70
71RPNGs = $(RPNG)-static
72RPNG2s = $(RPNG2)-static
73WPNGs = $(WPNG)-static
74
75ROBJSs = $(RPNG)$(O) readpng$(O)
76ROBJS2s = $(RPNG2)$(O) readpng2$(O)
77WOBJSs = $(WPNG)$(O) writepng$(O)
78
79STATIC_EXES = $(RPNGs)$(E) $(RPNG2s)$(E) $(WPNGs)$(E)
80DYNAMIC_EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
81
82EXES = $(STATIC_EXES) $(DYNAMIC_EXES)
83
84
85# implicit make rules -------------------------------------------------------
86
87.c$(O):
88 $(CC) -c $(CFLAGS) $<
89
90%.pic$(O): %.c
91 $(CC) -c $(CFLAGS) -DPNG_BUILD_DLL -o $@ $<
92
93
94# dependencies --------------------------------------------------------------
95
96all: $(EXES)
97
98$(RPNGs)$(E): $(ROBJSs)
99 $(LD) $(LDFLAGS) -o $@ $(ROBJSs) $(RLIBSs)
100
101$(RPNG)$(E): $(ROBJSd)
102 $(LD) $(LDFLAGS) -o $@ $(ROBJSd) $(RLIBSd)
103
104$(RPNG2s)$(E): $(ROBJS2s)
105 $(LD) $(LDFLAGS) -o $@ $(ROBJS2s) $(RLIBSs)
106
107$(RPNG2)$(E): $(ROBJS2d)
108 $(LD) $(LDFLAGS) -o $@ $(ROBJS2d) $(RLIBSd)
109
110$(WPNGs)$(E): $(WOBJSs)
111 $(LD) $(LDFLAGS) -o $@ $(WOBJSs) $(WLIBSs)
112
113$(WPNG)$(E): $(WOBJSd)
114 $(LD) $(LDFLAGS) -o $@ $(WOBJSd) $(WLIBSd)
115
116$(RPNG)$(O): $(RPNG).c readpng.h
117$(RPNG2)$(O): $(RPNG2).c readpng2.h
118$(WPNG)$(O): $(WPNG).c writepng.h
119
120readpng$(O) readpng.pic$(O): readpng.c readpng.h
121readpng2$(O) readpng2.pic$(O): readpng2.c readpng2.h
122writepng$(O) writepng.pic$(O): writepng.c writepng.h
123
124
125# maintenance ---------------------------------------------------------------
126
127clean:
128 $(RM) $(EXES)
129 $(RM) $(ROBJSs) $(ROBJS2s) $(WOBJSs)
130 $(RM) $(ROBJSd) $(ROBJS2d) $(WOBJSd)
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.sgi b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.sgi
new file mode 100644
index 0000000..8773a00
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.sgi
@@ -0,0 +1,104 @@
1# Sample makefile for rpng-x / rpng2-x / wpng for SGI using cc and make.
2# Greg Roelofs
3# Last modified: 7 March 2002
4#
5# The programs built by this makefile are described in the book,
6# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and
7# Associates, 1999). Go buy a copy, eh? Buy some for friends
8# and family, too. (Not that this is a blatant plug or anything.)
9#
10# Invoke this makefile from a shell prompt in the usual way; for example:
11#
12# make -f Makefile.sgi
13#
14# This makefile assumes libpng and zlib have already been built or downloaded
15# and are both installed in /usr/local/{include,lib} (as indicated by the
16# PNG* and Z* macros below). Edit as appropriate--choose only ONE each of
17# the PNGINC, PNGLIB, ZINC and ZLIB lines.
18#
19# This makefile builds dynamically linked executables (against libpng and zlib,
20# that is), but that can be changed by uncommenting the appropriate PNGLIB and
21# ZLIB lines.
22
23
24# macros --------------------------------------------------------------------
25
26PNGINC = -I/usr/local/include/libpng15
27PNGLIB = -L/usr/local/lib -lpng15 # dynamically linked against libpng
28#PNGLIB = /usr/local/lib/libpng15.a # statically linked against libpng
29# or:
30#PNGINC = -I../..
31#PNGLIB = -L../.. -lpng
32#PNGLIB = ../../libpng.a
33
34ZINC = -I/usr/local/include
35ZLIB = -L/usr/local/lib -lz # dynamically linked against zlib
36#ZLIB = /usr/local/lib/libz.a # statically linked against zlib
37#ZINC = -I../zlib
38#ZLIB = -L../zlib -lz
39#ZLIB = ../../../zlib/libz.a
40
41XINC = -I/usr/include/X11 # old-style, stock X distributions
42XLIB = -L/usr/lib/X11 -lX11
43#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows)
44#XLIB = -L/usr/openwin/lib -lX11
45#XINC = -I/usr/X11R6/include # new X distributions (XFree86, etc.)
46#XLIB = -L/usr/X11R6/lib -lX11
47
48INCS = $(PNGINC) $(ZINC) $(XINC)
49RLIBS = $(PNGLIB) $(ZLIB) $(XLIB) -lm
50WLIBS = $(PNGLIB) $(ZLIB)
51
52CC = cc
53LD = cc
54RM = rm -f
55# ABI must be the same as that used to build libpng.
56ABI=
57CFLAGS = $(ABI) -O -fullwarn $(INCS)
58LDFLAGS = $(ABI)
59O = .o
60E =
61
62RPNG = rpng-x
63RPNG2 = rpng2-x
64WPNG = wpng
65
66ROBJS = $(RPNG)$(O) readpng$(O)
67ROBJS2 = $(RPNG2)$(O) readpng2$(O)
68WOBJS = $(WPNG)$(O) writepng$(O)
69
70EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
71
72
73# implicit make rules -------------------------------------------------------
74
75.c$(O):
76 $(CC) -c $(CFLAGS) $<
77
78
79# dependencies --------------------------------------------------------------
80
81all: $(EXES)
82
83$(RPNG)$(E): $(ROBJS)
84 $(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBS)
85
86$(RPNG2)$(E): $(ROBJS2)
87 $(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBS)
88
89$(WPNG)$(E): $(WOBJS)
90 $(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBS)
91
92$(RPNG)$(O): $(RPNG).c readpng.h
93$(RPNG2)$(O): $(RPNG2).c readpng2.h
94$(WPNG)$(O): $(WPNG).c writepng.h
95
96readpng$(O): readpng.c readpng.h
97readpng2$(O): readpng2.c readpng2.h
98writepng$(O): writepng.c writepng.h
99
100
101# maintenance ---------------------------------------------------------------
102
103clean:
104 $(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.unx b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.unx
new file mode 100644
index 0000000..3bffc2f
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.unx
@@ -0,0 +1,132 @@
1# Sample makefile for rpng-x / rpng2-x / wpng using gcc and make.
2# Greg Roelofs
3# Last modified: 2 June 2007
4#
5# The programs built by this makefile are described in the book,
6# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and
7# Associates, 1999). Go buy a copy, eh? Well, OK, it's not
8# generally for sale anymore, but it's the thought that counts,
9# right? (Hint: http://www.libpng.org/pub/png/book/ )
10#
11# Invoke this makefile from a shell prompt in the usual way; for example:
12#
13# make -f Makefile.unx
14#
15# This makefile assumes libpng and zlib have already been built or downloaded
16# and are installed in /usr/local/{include,lib} or as otherwise indicated by
17# the PNG* and Z* macros below. Edit as appropriate--choose only ONE each of
18# the PNGINC, PNGLIBd, PNGLIBs, ZINC, ZLIBd and ZLIBs lines.
19#
20# This makefile builds both dynamically and statically linked executables
21# (against libpng and zlib, that is), but that can be changed by modifying
22# the "EXES =" line. (You need only one set, but for testing it can be handy
23# to have both.)
24
25
26# macros --------------------------------------------------------------------
27
28#PNGDIR = /usr/local/lib
29#PNGINC = -I/usr/local/include/libpng15
30#PNGLIBd = -L$(PNGDIR) -lpng15 # dynamically linked, installed libpng
31#PNGLIBs = $(PNGDIR)/libpng15.a # statically linked, installed libpng
32# or:
33PNGDIR = ../..# this one is for libpng-x.y.z/contrib/gregbook builds
34#PNGDIR = ../libpng
35PNGINC = -I$(PNGDIR)
36PNGLIBd = -Wl,-rpath,$(PNGDIR) -L$(PNGDIR) -lpng15 # dynamically linked
37PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng
38
39ZDIR = /usr/local/lib
40#ZDIR = /usr/lib64
41ZINC = -I/usr/local/include
42ZLIBd = -L$(ZDIR) -lz # dynamically linked against zlib
43ZLIBs = $(ZDIR)/libz.a # statically linked against zlib
44# or:
45#ZDIR = ../zlib
46#ZINC = -I$(ZDIR)
47#ZLIBd = -Wl,-rpath,$(ZDIR) -L$(ZDIR) -lz # -rpath allows in-place testing
48#ZLIBs = $(ZDIR)/libz.a
49
50#XINC = -I/usr/include # old-style, stock X distributions
51#XLIB = -L/usr/lib/X11 -lX11 # (including SGI IRIX)
52#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows)
53#XLIB = -L/usr/openwin/lib -lX11
54XINC = -I/usr/X11R6/include # new X distributions (X.org, etc.)
55XLIB = -L/usr/X11R6/lib -lX11
56#XLIB = -L/usr/X11R6/lib64 -lX11 # e.g., Red Hat on AMD64
57
58INCS = $(PNGINC) $(ZINC) $(XINC)
59RLIBSd = $(PNGLIBd) $(ZLIBd) $(XLIB) -lm
60RLIBSs = $(PNGLIBs) $(ZLIBs) $(XLIB) -lm
61WLIBSd = $(PNGLIBd) $(ZLIBd) -lm
62WLIBSs = $(PNGLIBs) $(ZLIBs)
63
64CC = gcc
65LD = gcc
66RM = rm -f
67CFLAGS = -O -Wall $(INCS) -DFEATURE_LOOP
68# [note that -Wall is a gcc-specific compilation flag ("most warnings on")]
69# [-ansi, -pedantic and -W can also be used]
70LDFLAGS =
71O = .o
72E =
73
74RPNG = rpng-x
75RPNG2 = rpng2-x
76WPNG = wpng
77
78RPNGs = $(RPNG)-static
79RPNG2s = $(RPNG2)-static
80WPNGs = $(WPNG)-static
81
82ROBJS = $(RPNG)$(O) readpng$(O)
83ROBJS2 = $(RPNG2)$(O) readpng2$(O)
84WOBJS = $(WPNG)$(O) writepng$(O)
85
86STATIC_EXES = $(RPNGs)$(E) $(RPNG2s)$(E) $(WPNGs)$(E)
87DYNAMIC_EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
88
89EXES = $(STATIC_EXES) $(DYNAMIC_EXES)
90
91
92# implicit make rules -------------------------------------------------------
93
94.c$(O):
95 $(CC) -c $(CFLAGS) $<
96
97
98# dependencies --------------------------------------------------------------
99
100all: $(EXES)
101
102$(RPNGs)$(E): $(ROBJS)
103 $(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBSs)
104
105$(RPNG)$(E): $(ROBJS)
106 $(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBSd)
107
108$(RPNG2s)$(E): $(ROBJS2)
109 $(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBSs)
110
111$(RPNG2)$(E): $(ROBJS2)
112 $(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBSd)
113
114$(WPNGs)$(E): $(WOBJS)
115 $(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBSs)
116
117$(WPNG)$(E): $(WOBJS)
118 $(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBSd)
119
120$(RPNG)$(O): $(RPNG).c readpng.h
121$(RPNG2)$(O): $(RPNG2).c readpng2.h
122$(WPNG)$(O): $(WPNG).c writepng.h
123
124readpng$(O): readpng.c readpng.h
125readpng2$(O): readpng2.c readpng2.h
126writepng$(O): writepng.c writepng.h
127
128
129# maintenance ---------------------------------------------------------------
130
131clean:
132 $(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.w32 b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.w32
new file mode 100644
index 0000000..eced083
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/Makefile.w32
@@ -0,0 +1,113 @@
1# Sample makefile for rpng-win / rpng2-win / wpng using MSVC and NMAKE.
2# Greg Roelofs
3# Last modified: 2 June 2007
4#
5# The programs built by this makefile are described in the book,
6# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and
7# Associates, 1999). Go buy a copy, eh? Well, OK, it's not
8# generally for sale anymore, but it's the thought that counts,
9# right? (Hint: http://www.libpng.org/pub/png/book/ )
10#
11# Invoke this makefile from a DOS prompt window via:
12#
13# %devstudio%\vc\bin\vcvars32.bat
14# nmake -nologo -f Makefile.w32
15#
16# where %devstudio% is the installation directory for MSVC / DevStudio. If
17# you get "environment out of space" errors, create a desktop shortcut with
18# "c:\windows\command.com /e:4096" as the program command line and set the
19# working directory to this directory. Then double-click to open the new
20# DOS-prompt window with a bigger environment and retry the commands above.
21#
22# This makefile assumes libpng and zlib have already been built or downloaded
23# and are in subdirectories at the same level as the current subdirectory
24# (as indicated by the PNGPATH and ZPATH macros below). Edit as appropriate.
25#
26# Note that the names of the dynamic and static libpng and zlib libraries
27# used below may change in later releases of the libraries. This makefile
28# builds statically linked executables, but that can be changed by uncom-
29# menting the appropriate PNGLIB and ZLIB lines.
30
31!include <ntwin32.mak>
32
33
34# macros --------------------------------------------------------------------
35
36PNGPATH = ../libpng
37PNGINC = -I$(PNGPATH)
38#PNGLIB = $(PNGPATH)/pngdll.lib
39PNGLIB = $(PNGPATH)/libpng.lib
40
41ZPATH = ../zlib
42ZINC = -I$(ZPATH)
43#ZLIB = $(ZPATH)/zlibdll.lib
44ZLIB = $(ZPATH)/zlibstat.lib
45
46WINLIBS = -defaultlib:user32.lib gdi32.lib
47# ["real" apps may also need comctl32.lib, comdlg32.lib, winmm.lib, etc.]
48
49INCS = $(PNGINC) $(ZINC)
50RLIBS = $(PNGLIB) $(ZLIB) $(WINLIBS)
51WLIBS = $(PNGLIB) $(ZLIB)
52
53CC = cl
54LD = link
55RM = del
56CFLAGS = -nologo -O -W3 $(INCS) $(cvars)
57# [note that -W3 is an MSVC-specific compilation flag ("all warnings on")]
58# [see %devstudio%\vc\include\win32.mak for cvars macro definition]
59O = .obj
60E = .exe
61
62RLDFLAGS = -nologo -subsystem:windows
63WLDFLAGS = -nologo
64
65RPNG = rpng-win
66RPNG2 = rpng2-win
67WPNG = wpng
68
69ROBJS = $(RPNG)$(O) readpng$(O)
70ROBJS2 = $(RPNG2)$(O) readpng2$(O)
71WOBJS = $(WPNG)$(O) writepng$(O)
72
73EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
74
75
76# implicit make rules -------------------------------------------------------
77
78.c$(O):
79 $(CC) -c $(CFLAGS) $<
80
81
82# dependencies --------------------------------------------------------------
83
84all: $(EXES)
85
86$(RPNG)$(E): $(ROBJS)
87 $(LD) $(RLDFLAGS) -out:$@ $(ROBJS) $(RLIBS)
88
89$(RPNG2)$(E): $(ROBJS2)
90 $(LD) $(RLDFLAGS) -out:$@ $(ROBJS2) $(RLIBS)
91
92$(WPNG)$(E): $(WOBJS)
93 $(LD) $(WLDFLAGS) -out:$@ $(WOBJS) $(WLIBS)
94
95$(RPNG)$(O): $(RPNG).c readpng.h
96$(RPNG2)$(O): $(RPNG2).c readpng2.h
97$(WPNG)$(O): $(WPNG).c writepng.h
98
99readpng$(O): readpng.c readpng.h
100readpng2$(O): readpng2.c readpng2.h
101writepng$(O): writepng.c writepng.h
102
103
104# maintenance ---------------------------------------------------------------
105
106clean:
107# ideally we could just do this:
108# $(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)
109# ...but the Windows "DEL" command is none too bright, so:
110 $(RM) r*$(E)
111 $(RM) w*$(E)
112 $(RM) r*$(O)
113 $(RM) w*$(O)
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/README b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/README
new file mode 100644
index 0000000..791fec8
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/README
@@ -0,0 +1,186 @@
1 ===========================
2 PNG: The Definitive Guide
3 ===========================
4
5 Source Code
6
7Chapters 13, 14 and 15 of "PNG: The Definitive Guide" discuss three free,
8cross-platform demo programs that show how to use the libpng reference
9library: rpng, rpng2 and wpng. rpng and rpng2 are viewers; the first is
10a very simple example that that shows how a standard file-viewer might use
11libpng, while the second is designed to process streaming data and shows
12how a web browser might be written. wpng is a simple command-line program
13that reads binary PGM and PPM files (the ``raw'' grayscale and RGB subsets
14of PBMPLUS/NetPBM) and converts them to PNG.
15
16The source code for all three demo programs currently compiles under
17Unix, OpenVMS, and 32-bit Windows. (Special thanks to Martin Zinser,
18zinser@decus.de, for making the necessary changes for OpenVMS and for
19providing an appropriate build script.) Build instructions can be found
20below.
21
22Files:
23
24 README this file
25 LICENSE terms of distribution and reuse (BSD-like or GNU GPL)
26 COPYING GNU General Public License (GPL)
27
28 Makefile.unx Unix makefile
29 Makefile.w32 Windows (MSVC) makefile
30 makevms.com OpenVMS build script
31
32 rpng-win.c Windows front end for the basic viewer
33 rpng-x.c X Window System (Unix, OpenVMS) front end
34 readpng.c generic back end for the basic viewer
35 readpng.h header file for the basic viewer
36
37 rpng2-win.c Windows front end for the progressive viewer
38 rpng2-x.c X front end for the progressive viewer
39 readpng2.c generic back end for the progressive viewer
40 readpng2.h header file for the progressive viewer
41
42 wpng.c generic (text) front end for the converter
43 writepng.c generic back end for the converter
44 writepng.h header file for the converter
45
46 toucan.png transparent PNG for testing (by Stefan Schneider)
47
48Note that, although the programs are designed to be functional, their
49primary purpose is to illustrate how to use libpng to add PNG support to
50other programs. As such, their user interfaces are crude and definitely
51are not intended for everyday use.
52
53Please see http://www.libpng.org/pub/png/pngbook.html for further infor-
54mation and links to the latest version of the source code, and Chapters
5513-15 of the book for detailed discussion of the three programs.
56
57Greg Roelofs
58http://pobox.com/~newt/greg_contact.html
5916 March 2008
60
61
62BUILD INSTRUCTIONS
63
64 - Prerequisites (in order of compilation):
65
66 - zlib http://zlib.net/
67 - libpng http://www.libpng.org/pub/png/libpng.html
68 - pngbook http://www.libpng.org/pub/png/book/sources.html
69
70 The pngbook demo programs are explicitly designed to demonstrate proper
71 coding techniques for using the libpng reference library. As a result,
72 you need to download and build both zlib (on which libpng depends) and
73 libpng. A common build setup is to place the zlib, libpng and pngbook
74 subdirectory trees ("folders") in the same parent directory. Then the
75 libpng build can refer to files in ../zlib (or ..\zlib or [-.zlib]),
76 and similarly for the pngbook build.
77
78 Note that all three packages are designed to be built from a command
79 line by default; those who wish to use a graphical or other integrated
80 development environments are on their own.
81
82
83 - Unix:
84
85 Unpack the latest pngbook sources (which should correspond to this
86 README file) into a directory and change into that directory.
87
88 Copy Makefile.unx to Makefile and edit the PNG* and Z* variables
89 appropriately (possibly also the X* variables if necessary).
90
91 make
92
93 There is no "install" target, so copy the three executables somewhere
94 in your path or run them from the current directory. All three will
95 print a basic usage screen when run without any command-line arguments;
96 see the book for more details.
97
98
99 - Windows:
100
101 Unpack the latest pngbook sources (which should correspond to this
102 README file) into a folder, open a "DOS shell" or "command prompt"
103 or equivalent command-line window, and cd into the folder where you
104 unpacked the source code.
105
106 For MSVC, set up the necessary environment variables by invoking
107
108 %devstudio%\vc\bin\vcvars32.bat
109
110 where where %devstudio% is the installation directory for MSVC /
111 DevStudio. If you get "environment out of space" errors under 95/98,
112 create a desktop shortcut with "c:\windows\command.com /e:4096" as
113 the program command line and set the working directory to the pngbook
114 directory. Then double-click to open the new DOS-prompt window with
115 a bigger environment and retry the commands above.
116
117 Copy Makefile.w32 to Makefile and edit the PNGPATH and ZPATH variables
118 appropriately (possibly also the "INC" and "LIB" variables if needed).
119 Note that the names of the dynamic and static libpng and zlib libraries
120 used in the makefile may change in later releases of the libraries.
121 Also note that, as of libpng version 1.0.5, MSVC DLL builds do not work.
122 This makefile therefore builds statically linked executables, but if
123 the DLL problems ever get fixed, uncommenting the appropriate PNGLIB
124 and ZLIB lines will build dynamically linked executables instead.
125
126 Do the build by typing
127
128 nmake
129
130 The result should be three executables: rpng-win.exe, rpng2-win.exe,
131 and wpng.exe. Copy them somewhere in your PATH or run them from the
132 current folder. Like the Unix versions, the two windowed programs
133 (rpng and rpng2) now display a usage screen in a console window when
134 invoked without command-line arguments; this is new behavior as of
135 the June 2001 release. Note that the programs use the Unix-style "-"
136 character to specify options, instead of the more common DOS/Windows
137 "/" character. (For example: "rpng2-win -bgpat 4 foo.png", not
138 "rpng2-win /bgpat 4 foo.png")
139
140
141 - OpenVMS:
142
143 Unpack the pngbook sources into a subdirectory and change into that
144 subdirectory.
145
146 Edit makevms.com appropriately, specifically the zpath and pngpath
147 variables.
148
149 @makevms
150
151 To run the programs, they probably first need to be set up as "foreign
152 symbols," with "disk" and "dir" set appropriately:
153
154 $ rpng == "$disk:[dir]rpng-x.exe"
155 $ rpng2 == "$disk:[dir]rpng2-x.exe"
156 $ wpng == "$disk:[dir]wpng.exe"
157
158 All three will print a basic usage screen when run without any command-
159 line arguments; see the book for more details. Note that the options
160 style is Unix-like, i.e., preceded by "-" rather than "/".
161
162
163RUNNING THE PROGRAMS: (VERY) BRIEF INTRO
164
165 rpng is a simple PNG viewer that can display transparent PNGs with a
166 specified background color; for example,
167
168 rpng -bgcolor \#ff0000 toucan.png
169
170 would display the image with a red background. rpng2 is a progressive
171 viewer that simulates a web browser in some respects; it can display
172 images against either a background color or a dynamically generated
173 background image. For example:
174
175 rpng2 -bgpat 16 toucan.png
176
177 wpng is a purely command-line image converter from binary PBMPLUS/NetPBM
178 format (.pgm or .ppm) to PNG; for example,
179
180 wpng -time < toucan-notrans.ppm > toucan-notrans.png
181
182 would convert the specified PPM file (using redirection) to PNG, auto-
183 matically setting the PNG modification-time chunk.
184
185 All options can be abbreviated to the shortest unique value; for example,
186 "-bgc" for -bgcolor (versus "-bgp" for -bgpat), or "-g" for -gamma.
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/makevms.com b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/makevms.com
new file mode 100644
index 0000000..29a5727
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/makevms.com
@@ -0,0 +1,132 @@
1$!------------------------------------------------------------------------------
2$! make "PNG: The Definitive Guide" demo programs (for X) under OpenVMS
3$!
4$! Script created by Martin Zinser for libpng; modified by Greg Roelofs
5$! for standalone pngbook source distribution.
6$!
7$!
8$! Set locations where zlib and libpng sources live.
9$!
10$ zpath = ""
11$ pngpath = ""
12$!
13$ if f$search("[---.zlib]zlib.h").nes."" then zpath = "[---.zlib]"
14$ if f$search("[--]png.h").nes."" then pngpath = "[--]"
15$!
16$ if f$search("[-.zlib]zlib.h").nes."" then zpath = "[-.zlib]"
17$ if f$search("[-.libpng]png.h").nes."" then pngpath = "[-.libpng]"
18$!
19$ if zpath .eqs. ""
20$ then
21$ write sys$output "zlib include not found. Exiting..."
22$ exit 2
23$ endif
24$!
25$ if pngpath .eqs. ""
26$ then
27$ write sys$output "libpng include not found. Exiting..."
28$ exit 2
29$ endif
30$!
31$! Look for the compiler used.
32$!
33$ ccopt="/include=(''zpath',''pngpath')"
34$ if f$getsyi("HW_MODEL").ge.1024
35$ then
36$ ccopt = "/prefix=all"+ccopt
37$ comp = "__decc__=1"
38$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
39$ else
40$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
41$ then
42$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
43$ if f$search("SYS$SYSTEM:VAXC.EXE").eqs.""
44$ then
45$ comp = "__gcc__=1"
46$ CC :== GCC
47$ else
48$ comp = "__vaxc__=1"
49$ endif
50$ else
51$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include:
52$ ccopt = "/decc/prefix=all"+ccopt
53$ comp = "__decc__=1"
54$ endif
55$ endif
56$ open/write lopt lib.opt
57$ write lopt "''pngpath'libpng.olb/lib"
58$ write lopt "''zpath'libz.olb/lib"
59$ close lopt
60$ open/write xopt x11.opt
61$ write xopt "sys$library:decw$xlibshr.exe/share"
62$ close xopt
63$!
64$! Build 'em.
65$!
66$ write sys$output "Compiling PNG book programs ..."
67$ CALL MAKE readpng.OBJ "cc ''CCOPT' readpng" -
68 readpng.c readpng.h
69$ CALL MAKE readpng2.OBJ "cc ''CCOPT' readpng2" -
70 readpng2.c readpng2.h
71$ CALL MAKE writepng.OBJ "cc ''CCOPT' writepng" -
72 writepng.c writepng.h
73$ write sys$output "Building rpng-x..."
74$ CALL MAKE rpng-x.OBJ "cc ''CCOPT' rpng-x" -
75 rpng-x.c readpng.h
76$ call make rpng-x.exe -
77 "LINK rpng-x,readpng,lib.opt/opt,x11.opt/opt" -
78 rpng-x.obj readpng.obj
79$ write sys$output "Building rpng2-x..."
80$ CALL MAKE rpng2-x.OBJ "cc ''CCOPT' rpng2-x" -
81 rpng2-x.c readpng2.h
82$ call make rpng2-x.exe -
83 "LINK rpng2-x,readpng2,lib.opt/opt,x11.opt/opt" -
84 rpng2-x.obj readpng2.obj
85$ write sys$output "Building wpng..."
86$ CALL MAKE wpng.OBJ "cc ''CCOPT' wpng" -
87 wpng.c writepng.h
88$ call make wpng.exe -
89 "LINK wpng,writepng,lib.opt/opt" -
90 wpng.obj writepng.obj
91$ exit
92$!
93$!
94$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES
95$ V = 'F$Verify(0)
96$! P1 = What we are trying to make
97$! P2 = Command to make it
98$! P3 - P8 What it depends on
99$
100$ If F$Search(P1) .Eqs. "" Then Goto Makeit
101$ Time = F$CvTime(F$File(P1,"RDT"))
102$arg=3
103$Loop:
104$ Argument = P'arg
105$ If Argument .Eqs. "" Then Goto Exit
106$ El=0
107$Loop2:
108$ File = F$Element(El," ",Argument)
109$ If File .Eqs. " " Then Goto Endl
110$ AFile = ""
111$Loop3:
112$ OFile = AFile
113$ AFile = F$Search(File)
114$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
115$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
116$ Goto Loop3
117$NextEL:
118$ El = El + 1
119$ Goto Loop2
120$EndL:
121$ arg=arg+1
122$ If arg .Le. 8 Then Goto Loop
123$ Goto Exit
124$
125$Makeit:
126$ VV=F$VERIFY(0)
127$ write sys$output P2
128$ 'P2
129$ VV='F$Verify(VV)
130$Exit:
131$ If V Then Set Verify
132$ENDSUBROUTINE
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng.c
new file mode 100644
index 0000000..27a2f11
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng.c
@@ -0,0 +1,311 @@
1/*---------------------------------------------------------------------------
2
3 rpng - simple PNG display program readpng.c
4
5 ---------------------------------------------------------------------------
6
7 Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
8
9 This software is provided "as is," without warranty of any kind,
10 express or implied. In no event shall the author or contributors
11 be held liable for any damages arising in any way from the use of
12 this software.
13
14 The contents of this file are DUAL-LICENSED. You may modify and/or
15 redistribute this software according to the terms of one of the
16 following two licenses (at your option):
17
18
19 LICENSE 1 ("BSD-like with advertising clause"):
20
21 Permission is granted to anyone to use this software for any purpose,
22 including commercial applications, and to alter it and redistribute
23 it freely, subject to the following restrictions:
24
25 1. Redistributions of source code must retain the above copyright
26 notice, disclaimer, and this list of conditions.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, disclaimer, and this list of conditions in the documenta-
29 tion and/or other materials provided with the distribution.
30 3. All advertising materials mentioning features or use of this
31 software must display the following acknowledgment:
32
33 This product includes software developed by Greg Roelofs
34 and contributors for the book, "PNG: The Definitive Guide,"
35 published by O'Reilly and Associates.
36
37
38 LICENSE 2 (GNU GPL v2 or later):
39
40 This program is free software; you can redistribute it and/or modify
41 it under the terms of the GNU General Public License as published by
42 the Free Software Foundation; either version 2 of the License, or
43 (at your option) any later version.
44
45 This program is distributed in the hope that it will be useful,
46 but WITHOUT ANY WARRANTY; without even the implied warranty of
47 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 GNU General Public License for more details.
49
50 You should have received a copy of the GNU General Public License
51 along with this program; if not, write to the Free Software Foundation,
52 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53
54 ---------------------------------------------------------------------------*/
55
56#include <stdio.h>
57#include <stdlib.h>
58
59#include "png.h" /* libpng header; includes zlib.h */
60#include "readpng.h" /* typedefs, common macros, public prototypes */
61
62/* future versions of libpng will provide this macro: */
63#ifndef png_jmpbuf
64# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
65#endif
66
67
68static png_structp png_ptr = NULL;
69static png_infop info_ptr = NULL;
70
71png_uint_32 width, height;
72int bit_depth, color_type;
73uch *image_data = NULL;
74
75
76void readpng_version_info(void)
77{
78 fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
79 PNG_LIBPNG_VER_STRING, png_libpng_ver);
80 fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
81 ZLIB_VERSION, zlib_version);
82}
83
84
85/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
86
87int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
88{
89 uch sig[8];
90
91
92 /* first do a quick check that the file really is a PNG image; could
93 * have used slightly more general png_sig_cmp() function instead */
94
95 fread(sig, 1, 8, infile);
96 if (png_sig_cmp(sig, 0, 8))
97 return 1; /* bad signature */
98
99
100 /* could pass pointers to user-defined error handlers instead of NULLs: */
101
102 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
103 if (!png_ptr)
104 return 4; /* out of memory */
105
106 info_ptr = png_create_info_struct(png_ptr);
107 if (!info_ptr) {
108 png_destroy_read_struct(&png_ptr, NULL, NULL);
109 return 4; /* out of memory */
110 }
111
112
113 /* we could create a second info struct here (end_info), but it's only
114 * useful if we want to keep pre- and post-IDAT chunk info separated
115 * (mainly for PNG-aware image editors and converters) */
116
117
118 /* setjmp() must be called in every function that calls a PNG-reading
119 * libpng function */
120
121 if (setjmp(png_jmpbuf(png_ptr))) {
122 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
123 return 2;
124 }
125
126
127 png_init_io(png_ptr, infile);
128 png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
129
130 png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
131
132
133 /* alternatively, could make separate calls to png_get_image_width(),
134 * etc., but want bit_depth and color_type for later [don't care about
135 * compression_type and filter_type => NULLs] */
136
137 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
138 NULL, NULL, NULL);
139 *pWidth = width;
140 *pHeight = height;
141
142
143 /* OK, that's all we need for now; return happy */
144
145 return 0;
146}
147
148
149
150
151/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
152 * scales values to 8-bit if necessary */
153
154int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
155{
156 png_color_16p pBackground;
157
158
159 /* setjmp() must be called in every function that calls a PNG-reading
160 * libpng function */
161
162 if (setjmp(png_jmpbuf(png_ptr))) {
163 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
164 return 2;
165 }
166
167
168 if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
169 return 1;
170
171 /* it is not obvious from the libpng documentation, but this function
172 * takes a pointer to a pointer, and it always returns valid red, green
173 * and blue values, regardless of color_type: */
174
175 png_get_bKGD(png_ptr, info_ptr, &pBackground);
176
177
178 /* however, it always returns the raw bKGD data, regardless of any
179 * bit-depth transformations, so check depth and adjust if necessary */
180
181 if (bit_depth == 16) {
182 *red = pBackground->red >> 8;
183 *green = pBackground->green >> 8;
184 *blue = pBackground->blue >> 8;
185 } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
186 if (bit_depth == 1)
187 *red = *green = *blue = pBackground->gray? 255 : 0;
188 else if (bit_depth == 2)
189 *red = *green = *blue = (255/3) * pBackground->gray;
190 else /* bit_depth == 4 */
191 *red = *green = *blue = (255/15) * pBackground->gray;
192 } else {
193 *red = (uch)pBackground->red;
194 *green = (uch)pBackground->green;
195 *blue = (uch)pBackground->blue;
196 }
197
198 return 0;
199}
200
201
202
203
204/* display_exponent == LUT_exponent * CRT_exponent */
205
206uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
207{
208 double gamma;
209 png_uint_32 i, rowbytes;
210 png_bytepp row_pointers = NULL;
211
212
213 /* setjmp() must be called in every function that calls a PNG-reading
214 * libpng function */
215
216 if (setjmp(png_jmpbuf(png_ptr))) {
217 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
218 return NULL;
219 }
220
221
222 /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
223 * transparency chunks to full alpha channel; strip 16-bit-per-sample
224 * images to 8 bits per sample; and convert grayscale to RGB[A] */
225
226 if (color_type == PNG_COLOR_TYPE_PALETTE)
227 png_set_expand(png_ptr);
228 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
229 png_set_expand(png_ptr);
230 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
231 png_set_expand(png_ptr);
232#ifdef PNG_READ_16_TO_8_SUPPORTED
233 if (bit_depth == 16)
234# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
235 png_set_scale_16(png_ptr);
236# else
237 png_set_strip_16(png_ptr);
238# endif
239#endif
240 if (color_type == PNG_COLOR_TYPE_GRAY ||
241 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
242 png_set_gray_to_rgb(png_ptr);
243
244
245 /* unlike the example in the libpng documentation, we have *no* idea where
246 * this file may have come from--so if it doesn't have a file gamma, don't
247 * do any correction ("do no harm") */
248
249 if (png_get_gAMA(png_ptr, info_ptr, &gamma))
250 png_set_gamma(png_ptr, display_exponent, gamma);
251
252
253 /* all transformations have been registered; now update info_ptr data,
254 * get rowbytes and channels, and allocate image memory */
255
256 png_read_update_info(png_ptr, info_ptr);
257
258 *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
259 *pChannels = (int)png_get_channels(png_ptr, info_ptr);
260
261 if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
262 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
263 return NULL;
264 }
265 if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
266 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
267 free(image_data);
268 image_data = NULL;
269 return NULL;
270 }
271
272 Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n",
273 *pChannels, rowbytes, height));
274
275
276 /* set the individual row_pointers to point at the correct offsets */
277
278 for (i = 0; i < height; ++i)
279 row_pointers[i] = image_data + i*rowbytes;
280
281
282 /* now we can go ahead and just read the whole image */
283
284 png_read_image(png_ptr, row_pointers);
285
286
287 /* and we're done! (png_read_end() can be omitted if no processing of
288 * post-IDAT text/time/etc. is desired) */
289
290 free(row_pointers);
291 row_pointers = NULL;
292
293 png_read_end(png_ptr, NULL);
294
295 return image_data;
296}
297
298
299void readpng_cleanup(int free_image_data)
300{
301 if (free_image_data && image_data) {
302 free(image_data);
303 image_data = NULL;
304 }
305
306 if (png_ptr && info_ptr) {
307 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
308 png_ptr = NULL;
309 info_ptr = NULL;
310 }
311}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng.h
new file mode 100644
index 0000000..ec6b483
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng.h
@@ -0,0 +1,88 @@
1/*---------------------------------------------------------------------------
2
3 rpng - simple PNG display program readpng.h
4
5 ---------------------------------------------------------------------------
6
7 Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
8
9 This software is provided "as is," without warranty of any kind,
10 express or implied. In no event shall the author or contributors
11 be held liable for any damages arising in any way from the use of
12 this software.
13
14 The contents of this file are DUAL-LICENSED. You may modify and/or
15 redistribute this software according to the terms of one of the
16 following two licenses (at your option):
17
18
19 LICENSE 1 ("BSD-like with advertising clause"):
20
21 Permission is granted to anyone to use this software for any purpose,
22 including commercial applications, and to alter it and redistribute
23 it freely, subject to the following restrictions:
24
25 1. Redistributions of source code must retain the above copyright
26 notice, disclaimer, and this list of conditions.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, disclaimer, and this list of conditions in the documenta-
29 tion and/or other materials provided with the distribution.
30 3. All advertising materials mentioning features or use of this
31 software must display the following acknowledgment:
32
33 This product includes software developed by Greg Roelofs
34 and contributors for the book, "PNG: The Definitive Guide,"
35 published by O'Reilly and Associates.
36
37
38 LICENSE 2 (GNU GPL v2 or later):
39
40 This program is free software; you can redistribute it and/or modify
41 it under the terms of the GNU General Public License as published by
42 the Free Software Foundation; either version 2 of the License, or
43 (at your option) any later version.
44
45 This program is distributed in the hope that it will be useful,
46 but WITHOUT ANY WARRANTY; without even the implied warranty of
47 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 GNU General Public License for more details.
49
50 You should have received a copy of the GNU General Public License
51 along with this program; if not, write to the Free Software Foundation,
52 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53
54 ---------------------------------------------------------------------------*/
55
56#ifndef TRUE
57# define TRUE 1
58# define FALSE 0
59#endif
60
61#ifndef MAX
62# define MAX(a,b) ((a) > (b)? (a) : (b))
63# define MIN(a,b) ((a) < (b)? (a) : (b))
64#endif
65
66#ifdef DEBUG
67# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
68#else
69# define Trace(x) ;
70#endif
71
72typedef unsigned char uch;
73typedef unsigned short ush;
74typedef unsigned long ulg;
75
76
77/* prototypes for public functions in readpng.c */
78
79void readpng_version_info(void);
80
81int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight);
82
83int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue);
84
85uch *readpng_get_image(double display_exponent, int *pChannels,
86 ulg *pRowbytes);
87
88void readpng_cleanup(int free_image_data);
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c
new file mode 100644
index 0000000..3bbd2ec
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c
@@ -0,0 +1,511 @@
1/*---------------------------------------------------------------------------
2
3 rpng2 - progressive-model PNG display program readpng2.c
4
5 ---------------------------------------------------------------------------
6
7 Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
8
9 This software is provided "as is," without warranty of any kind,
10 express or implied. In no event shall the author or contributors
11 be held liable for any damages arising in any way from the use of
12 this software.
13
14 The contents of this file are DUAL-LICENSED. You may modify and/or
15 redistribute this software according to the terms of one of the
16 following two licenses (at your option):
17
18
19 LICENSE 1 ("BSD-like with advertising clause"):
20
21 Permission is granted to anyone to use this software for any purpose,
22 including commercial applications, and to alter it and redistribute
23 it freely, subject to the following restrictions:
24
25 1. Redistributions of source code must retain the above copyright
26 notice, disclaimer, and this list of conditions.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, disclaimer, and this list of conditions in the documenta-
29 tion and/or other materials provided with the distribution.
30 3. All advertising materials mentioning features or use of this
31 software must display the following acknowledgment:
32
33 This product includes software developed by Greg Roelofs
34 and contributors for the book, "PNG: The Definitive Guide,"
35 published by O'Reilly and Associates.
36
37
38 LICENSE 2 (GNU GPL v2 or later):
39
40 This program is free software; you can redistribute it and/or modify
41 it under the terms of the GNU General Public License as published by
42 the Free Software Foundation; either version 2 of the License, or
43 (at your option) any later version.
44
45 This program is distributed in the hope that it will be useful,
46 but WITHOUT ANY WARRANTY; without even the implied warranty of
47 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 GNU General Public License for more details.
49
50 You should have received a copy of the GNU General Public License
51 along with this program; if not, write to the Free Software Foundation,
52 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53
54 ---------------------------------------------------------------------------*/
55
56
57#include <stdlib.h> /* for exit() prototype */
58#include <setjmp.h>
59
60#include <zlib.h>
61#include "png.h" /* libpng header from the local directory */
62#include "readpng2.h" /* typedefs, common macros, public prototypes */
63
64
65/* local prototypes */
66
67static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr);
68static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row,
69 png_uint_32 row_num, int pass);
70static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr);
71static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg);
72
73
74
75
76void readpng2_version_info(void)
77{
78 fprintf(stderr, " Compiled with libpng %s; using libpng %s\n",
79 PNG_LIBPNG_VER_STRING, png_libpng_ver);
80
81 fprintf(stderr, " and with zlib %s; using zlib %s.\n",
82 ZLIB_VERSION, zlib_version);
83}
84
85
86
87
88int readpng2_check_sig(uch *sig, int num)
89{
90 return !png_sig_cmp(sig, 0, num);
91}
92
93
94
95
96/* returns 0 for success, 2 for libpng problem, 4 for out of memory */
97
98int readpng2_init(mainprog_info *mainprog_ptr)
99{
100 png_structp png_ptr; /* note: temporary variables! */
101 png_infop info_ptr;
102
103
104 /* could also replace libpng warning-handler (final NULL), but no need: */
105
106 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
107 readpng2_error_handler, NULL);
108 if (!png_ptr)
109 return 4; /* out of memory */
110
111 info_ptr = png_create_info_struct(png_ptr);
112 if (!info_ptr) {
113 png_destroy_read_struct(&png_ptr, NULL, NULL);
114 return 4; /* out of memory */
115 }
116
117
118 /* we could create a second info struct here (end_info), but it's only
119 * useful if we want to keep pre- and post-IDAT chunk info separated
120 * (mainly for PNG-aware image editors and converters) */
121
122
123 /* setjmp() must be called in every function that calls a PNG-reading
124 * libpng function, unless an alternate error handler was installed--
125 * but compatible error handlers must either use longjmp() themselves
126 * (as in this program) or exit immediately, so here we are: */
127
128 if (setjmp(mainprog_ptr->jmpbuf)) {
129 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
130 return 2;
131 }
132
133
134#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
135 /* prepare the reader to ignore all recognized chunks whose data won't be
136 * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT,
137 * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */
138 {
139 /* These byte strings were copied from png.h. If a future libpng
140 * version recognizes more chunks, add them to this list. If a
141 * future version of readpng2.c recognizes more chunks, delete them
142 * from this list. */
143 static /* const */ png_byte chunks_to_ignore[] = {
144 99, 72, 82, 77, '\0', /* cHRM */
145 104, 73, 83, 84, '\0', /* hIST */
146 105, 67, 67, 80, '\0', /* iCCP */
147 105, 84, 88, 116, '\0', /* iTXt */
148 111, 70, 70, 115, '\0', /* oFFs */
149 112, 67, 65, 76, '\0', /* pCAL */
150 112, 72, 89, 115, '\0', /* pHYs */
151 115, 66, 73, 84, '\0', /* sBIT */
152 115, 67, 65, 76, '\0', /* sCAL */
153 115, 80, 76, 84, '\0', /* sPLT */
154 115, 84, 69, 82, '\0', /* sTER */
155 116, 69, 88, 116, '\0', /* tEXt */
156 116, 73, 77, 69, '\0', /* tIME */
157 122, 84, 88, 116, '\0' /* zTXt */
158 };
159
160 png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */,
161 chunks_to_ignore, sizeof(chunks_to_ignore)/5);
162 }
163#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */
164
165
166 /* instead of doing png_init_io() here, now we set up our callback
167 * functions for progressive decoding */
168
169 png_set_progressive_read_fn(png_ptr, mainprog_ptr,
170 readpng2_info_callback, readpng2_row_callback, readpng2_end_callback);
171
172
173 /* make sure we save our pointers for use in readpng2_decode_data() */
174
175 mainprog_ptr->png_ptr = png_ptr;
176 mainprog_ptr->info_ptr = info_ptr;
177
178
179 /* and that's all there is to initialization */
180
181 return 0;
182}
183
184
185
186
187/* returns 0 for success, 2 for libpng (longjmp) problem */
188
189int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length)
190{
191 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
192 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
193
194
195 /* setjmp() must be called in every function that calls a PNG-reading
196 * libpng function */
197
198 if (setjmp(mainprog_ptr->jmpbuf)) {
199 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
200 mainprog_ptr->png_ptr = NULL;
201 mainprog_ptr->info_ptr = NULL;
202 return 2;
203 }
204
205
206 /* hand off the next chunk of input data to libpng for decoding */
207
208 png_process_data(png_ptr, info_ptr, rawbuf, length);
209
210 return 0;
211}
212
213
214
215
216static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr)
217{
218 mainprog_info *mainprog_ptr;
219 int color_type, bit_depth;
220 png_uint_32 width, height;
221#ifdef PNG_FLOATING_POINT_SUPPORTED
222 double gamma;
223#else
224 png_fixed_point gamma;
225#endif
226
227
228 /* setjmp() doesn't make sense here, because we'd either have to exit(),
229 * longjmp() ourselves, or return control to libpng, which doesn't want
230 * to see us again. By not doing anything here, libpng will instead jump
231 * to readpng2_decode_data(), which can return an error value to the main
232 * program. */
233
234
235 /* retrieve the pointer to our special-purpose struct, using the png_ptr
236 * that libpng passed back to us (i.e., not a global this time--there's
237 * no real difference for a single image, but for a multithreaded browser
238 * decoding several PNG images at the same time, one needs to avoid mixing
239 * up different images' structs) */
240
241 mainprog_ptr = png_get_progressive_ptr(png_ptr);
242
243 if (mainprog_ptr == NULL) { /* we be hosed */
244 fprintf(stderr,
245 "readpng2 error: main struct not recoverable in info_callback.\n");
246 fflush(stderr);
247 return;
248 /*
249 * Alternatively, we could call our error-handler just like libpng
250 * does, which would effectively terminate the program. Since this
251 * can only happen if png_ptr gets redirected somewhere odd or the
252 * main PNG struct gets wiped, we're probably toast anyway. (If
253 * png_ptr itself is NULL, we would not have been called.)
254 */
255 }
256
257
258 /* this is just like in the non-progressive case */
259
260 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
261 NULL, NULL, NULL);
262 mainprog_ptr->width = (ulg)width;
263 mainprog_ptr->height = (ulg)height;
264
265
266 /* since we know we've read all of the PNG file's "header" (i.e., up
267 * to IDAT), we can check for a background color here */
268
269 if (mainprog_ptr->need_bgcolor &&
270 png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
271 {
272 png_color_16p pBackground;
273
274 /* it is not obvious from the libpng documentation, but this function
275 * takes a pointer to a pointer, and it always returns valid red,
276 * green and blue values, regardless of color_type: */
277 png_get_bKGD(png_ptr, info_ptr, &pBackground);
278
279 /* however, it always returns the raw bKGD data, regardless of any
280 * bit-depth transformations, so check depth and adjust if necessary */
281 if (bit_depth == 16) {
282 mainprog_ptr->bg_red = pBackground->red >> 8;
283 mainprog_ptr->bg_green = pBackground->green >> 8;
284 mainprog_ptr->bg_blue = pBackground->blue >> 8;
285 } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
286 if (bit_depth == 1)
287 mainprog_ptr->bg_red = mainprog_ptr->bg_green =
288 mainprog_ptr->bg_blue = pBackground->gray? 255 : 0;
289 else if (bit_depth == 2)
290 mainprog_ptr->bg_red = mainprog_ptr->bg_green =
291 mainprog_ptr->bg_blue = (255/3) * pBackground->gray;
292 else /* bit_depth == 4 */
293 mainprog_ptr->bg_red = mainprog_ptr->bg_green =
294 mainprog_ptr->bg_blue = (255/15) * pBackground->gray;
295 } else {
296 mainprog_ptr->bg_red = (uch)pBackground->red;
297 mainprog_ptr->bg_green = (uch)pBackground->green;
298 mainprog_ptr->bg_blue = (uch)pBackground->blue;
299 }
300 }
301
302
303 /* as before, let libpng expand palette images to RGB, low-bit-depth
304 * grayscale images to 8 bits, transparency chunks to full alpha channel;
305 * strip 16-bit-per-sample images to 8 bits per sample; and convert
306 * grayscale to RGB[A] */
307
308 if (color_type == PNG_COLOR_TYPE_PALETTE)
309 png_set_expand(png_ptr);
310 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
311 png_set_expand(png_ptr);
312 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
313 png_set_expand(png_ptr);
314#ifdef PNG_READ_16_TO_8_SUPPORTED
315 if (bit_depth == 16)
316# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
317 png_set_scale_16(png_ptr);
318# else
319 png_set_strip_16(png_ptr);
320# endif
321#endif
322 if (color_type == PNG_COLOR_TYPE_GRAY ||
323 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
324 png_set_gray_to_rgb(png_ptr);
325
326
327 /* Unlike the basic viewer, which was designed to operate on local files,
328 * this program is intended to simulate a web browser--even though we
329 * actually read from a local file, too. But because we are pretending
330 * that most of the images originate on the Internet, we follow the recom-
331 * mendation of the sRGB proposal and treat unlabelled images (no gAMA
332 * chunk) as existing in the sRGB color space. That is, we assume that
333 * such images have a file gamma of 0.45455, which corresponds to a PC-like
334 * display system. This change in assumptions will have no effect on a
335 * PC-like system, but on a Mac, SGI, NeXT or other system with a non-
336 * identity lookup table, it will darken unlabelled images, which effec-
337 * tively favors images from PC-like systems over those originating on
338 * the local platform. Note that mainprog_ptr->display_exponent is the
339 * "gamma" value for the entire display system, i.e., the product of
340 * LUT_exponent and CRT_exponent. */
341
342#ifdef PNG_FLOATING_POINT_SUPPORTED
343 if (png_get_gAMA(png_ptr, info_ptr, &gamma))
344 png_set_gamma(png_ptr, mainprog_ptr->display_exponent, gamma);
345 else
346 png_set_gamma(png_ptr, mainprog_ptr->display_exponent, 0.45455);
347#else
348 if (png_get_gAMA_fixed(png_ptr, info_ptr, &gamma))
349 png_set_gamma_fixed(png_ptr,
350 (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), gamma);
351 else
352 png_set_gamma_fixed(png_ptr,
353 (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), 45455);
354#endif
355
356 /* we'll let libpng expand interlaced images, too */
357
358 mainprog_ptr->passes = png_set_interlace_handling(png_ptr);
359
360
361 /* all transformations have been registered; now update info_ptr data and
362 * then get rowbytes and channels */
363
364 png_read_update_info(png_ptr, info_ptr);
365
366 mainprog_ptr->rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr);
367 mainprog_ptr->channels = png_get_channels(png_ptr, info_ptr);
368
369
370 /* Call the main program to allocate memory for the image buffer and
371 * initialize windows and whatnot. (The old-style function-pointer
372 * invocation is used for compatibility with a few supposedly ANSI
373 * compilers that nevertheless barf on "fn_ptr()"-style syntax.) */
374
375 (*mainprog_ptr->mainprog_init)();
376
377
378 /* and that takes care of initialization */
379
380 return;
381}
382
383
384
385
386
387static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row,
388 png_uint_32 row_num, int pass)
389{
390 mainprog_info *mainprog_ptr;
391
392
393 /* first check whether the row differs from the previous pass; if not,
394 * nothing to combine or display */
395
396 if (!new_row)
397 return;
398
399
400 /* retrieve the pointer to our special-purpose struct so we can access
401 * the old rows and image-display callback function */
402
403 mainprog_ptr = png_get_progressive_ptr(png_ptr);
404
405
406 /* save the pass number for optional use by the front end */
407
408 mainprog_ptr->pass = pass;
409
410
411 /* have libpng either combine the new row data with the existing row data
412 * from previous passes (if interlaced) or else just copy the new row
413 * into the main program's image buffer */
414
415 png_progressive_combine_row(png_ptr, mainprog_ptr->row_pointers[row_num],
416 new_row);
417
418
419 /* finally, call the display routine in the main program with the number
420 * of the row we just updated */
421
422 (*mainprog_ptr->mainprog_display_row)(row_num);
423
424
425 /* and we're ready for more */
426
427 return;
428}
429
430
431
432
433
434static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr)
435{
436 mainprog_info *mainprog_ptr;
437
438
439 /* retrieve the pointer to our special-purpose struct */
440
441 mainprog_ptr = png_get_progressive_ptr(png_ptr);
442
443
444 /* let the main program know that it should flush any buffered image
445 * data to the display now and set a "done" flag or whatever, but note
446 * that it SHOULD NOT DESTROY THE PNG STRUCTS YET--in other words, do
447 * NOT call readpng2_cleanup() either here or in the finish_display()
448 * routine; wait until control returns to the main program via
449 * readpng2_decode_data() */
450
451 (*mainprog_ptr->mainprog_finish_display)();
452
453
454 /* all done */
455
456 return;
457}
458
459
460
461
462
463void readpng2_cleanup(mainprog_info *mainprog_ptr)
464{
465 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
466 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
467
468 if (png_ptr && info_ptr)
469 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
470
471 mainprog_ptr->png_ptr = NULL;
472 mainprog_ptr->info_ptr = NULL;
473}
474
475
476
477
478
479static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg)
480{
481 mainprog_info *mainprog_ptr;
482
483 /* This function, aside from the extra step of retrieving the "error
484 * pointer" (below) and the fact that it exists within the application
485 * rather than within libpng, is essentially identical to libpng's
486 * default error handler. The second point is critical: since both
487 * setjmp() and longjmp() are called from the same code, they are
488 * guaranteed to have compatible notions of how big a jmp_buf is,
489 * regardless of whether _BSD_SOURCE or anything else has (or has not)
490 * been defined. */
491
492 fprintf(stderr, "readpng2 libpng error: %s\n", msg);
493 fflush(stderr);
494
495 mainprog_ptr = png_get_error_ptr(png_ptr);
496 if (mainprog_ptr == NULL) { /* we are completely hosed now */
497 fprintf(stderr,
498 "readpng2 severe error: jmpbuf not recoverable; terminating.\n");
499 fflush(stderr);
500 exit(99);
501 }
502
503 /* Now we have our data structure we can use the information in it
504 * to return control to our own higher level code (all the points
505 * where 'setjmp' is called in this file.) This will work with other
506 * error handling mechanisms as well - libpng always calls png_error
507 * when it can proceed no further, thus, so long as the error handler
508 * is intercepted, application code can do its own error recovery.
509 */
510 longjmp(mainprog_ptr->jmpbuf, 1);
511}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.h
new file mode 100644
index 0000000..7a59263
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.h
@@ -0,0 +1,116 @@
1/*---------------------------------------------------------------------------
2
3 rpng2 - progressive-model PNG display program readpng2.h
4
5 ---------------------------------------------------------------------------
6
7 Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
8
9 This software is provided "as is," without warranty of any kind,
10 express or implied. In no event shall the author or contributors
11 be held liable for any damages arising in any way from the use of
12 this software.
13
14 The contents of this file are DUAL-LICENSED. You may modify and/or
15 redistribute this software according to the terms of one of the
16 following two licenses (at your option):
17
18
19 LICENSE 1 ("BSD-like with advertising clause"):
20
21 Permission is granted to anyone to use this software for any purpose,
22 including commercial applications, and to alter it and redistribute
23 it freely, subject to the following restrictions:
24
25 1. Redistributions of source code must retain the above copyright
26 notice, disclaimer, and this list of conditions.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, disclaimer, and this list of conditions in the documenta-
29 tion and/or other materials provided with the distribution.
30 3. All advertising materials mentioning features or use of this
31 software must display the following acknowledgment:
32
33 This product includes software developed by Greg Roelofs
34 and contributors for the book, "PNG: The Definitive Guide,"
35 published by O'Reilly and Associates.
36
37
38 LICENSE 2 (GNU GPL v2 or later):
39
40 This program is free software; you can redistribute it and/or modify
41 it under the terms of the GNU General Public License as published by
42 the Free Software Foundation; either version 2 of the License, or
43 (at your option) any later version.
44
45 This program is distributed in the hope that it will be useful,
46 but WITHOUT ANY WARRANTY; without even the implied warranty of
47 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 GNU General Public License for more details.
49
50 You should have received a copy of the GNU General Public License
51 along with this program; if not, write to the Free Software Foundation,
52 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53
54 ---------------------------------------------------------------------------*/
55
56#ifndef TRUE
57# define TRUE 1
58# define FALSE 0
59#endif
60
61#ifndef MAX
62# define MAX(a,b) ((a) > (b)? (a) : (b))
63# define MIN(a,b) ((a) < (b)? (a) : (b))
64#endif
65
66#ifdef DEBUG
67# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
68#else
69# define Trace(x) ;
70#endif
71
72enum rpng2_states {
73 kPreInit = 0,
74 kWindowInit,
75 kDone
76};
77
78typedef unsigned char uch;
79typedef unsigned short ush;
80typedef unsigned long ulg;
81
82typedef struct _mainprog_info {
83 double display_exponent;
84 ulg width;
85 ulg height;
86 void *png_ptr;
87 void *info_ptr;
88 void (*mainprog_init)(void);
89 void (*mainprog_display_row)(ulg row_num);
90 void (*mainprog_finish_display)(void);
91 uch *image_data;
92 uch **row_pointers;
93 jmp_buf jmpbuf;
94 int passes; /* not used */
95 int pass;
96 int rowbytes;
97 int channels;
98 int need_bgcolor;
99 int state;
100 uch bg_red;
101 uch bg_green;
102 uch bg_blue;
103} mainprog_info;
104
105
106/* prototypes for public functions in readpng2.c */
107
108void readpng2_version_info(void);
109
110int readpng2_check_sig(uch *sig, int num);
111
112int readpng2_init(mainprog_info *mainprog_ptr);
113
114int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length);
115
116void readpng2_cleanup(mainprog_info *mainprog_ptr);
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readppm.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readppm.c
new file mode 100644
index 0000000..1ba2092
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readppm.c
@@ -0,0 +1,179 @@
1/*---------------------------------------------------------------------------
2
3 rpng - simple PNG display program readppm.c
4
5 ---------------------------------------------------------------------------
6
7 This is a special-purpose replacement for readpng.c that allows binary
8 PPM files to be used in place of PNG images.
9
10 ---------------------------------------------------------------------------
11
12 Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
13
14 This software is provided "as is," without warranty of any kind,
15 express or implied. In no event shall the author or contributors
16 be held liable for any damages arising in any way from the use of
17 this software.
18
19 The contents of this file are DUAL-LICENSED. You may modify and/or
20 redistribute this software according to the terms of one of the
21 following two licenses (at your option):
22
23
24 LICENSE 1 ("BSD-like with advertising clause"):
25
26 Permission is granted to anyone to use this software for any purpose,
27 including commercial applications, and to alter it and redistribute
28 it freely, subject to the following restrictions:
29
30 1. Redistributions of source code must retain the above copyright
31 notice, disclaimer, and this list of conditions.
32 2. Redistributions in binary form must reproduce the above copyright
33 notice, disclaimer, and this list of conditions in the documenta-
34 tion and/or other materials provided with the distribution.
35 3. All advertising materials mentioning features or use of this
36 software must display the following acknowledgment:
37
38 This product includes software developed by Greg Roelofs
39 and contributors for the book, "PNG: The Definitive Guide,"
40 published by O'Reilly and Associates.
41
42
43 LICENSE 2 (GNU GPL v2 or later):
44
45 This program is free software; you can redistribute it and/or modify
46 it under the terms of the GNU General Public License as published by
47 the Free Software Foundation; either version 2 of the License, or
48 (at your option) any later version.
49
50 This program is distributed in the hope that it will be useful,
51 but WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53 GNU General Public License for more details.
54
55 You should have received a copy of the GNU General Public License
56 along with this program; if not, write to the Free Software Foundation,
57 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
58
59 ---------------------------------------------------------------------------*/
60
61#include <stdio.h>
62#include <stdlib.h>
63
64#include "readpng.h" /* typedefs, common macros, public prototypes */
65
66
67ulg width, height;
68int bit_depth, color_type, channels;
69uch *image_data = NULL;
70FILE *saved_infile;
71
72
73void readpng_version_info()
74{
75 fprintf(stderr, " Compiled without libpng, zlib or PBMPLUS/NetPBM.\n");
76}
77
78
79/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
80
81int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
82{
83 static uch ppmline[256];
84 int maxval;
85
86
87 saved_infile = infile;
88
89 fgets(ppmline, 256, infile);
90 if (ppmline[0] != 'P' || ppmline[1] != '6') {
91 fprintf(stderr, "ERROR: not a PPM file\n");
92 return 1;
93 }
94 /* possible color types: P5 = grayscale (0), P6 = RGB (2), P8 = RGBA (6) */
95 if (ppmline[1] == '6') {
96 color_type = 2;
97 channels = 3;
98 } else if (ppmline[1] == '8') {
99 color_type = 6;
100 channels = 4;
101 } else /* if (ppmline[1] == '5') */ {
102 color_type = 0;
103 channels = 1;
104 }
105
106 do {
107 fgets(ppmline, 256, infile);
108 } while (ppmline[0] == '#');
109 sscanf(ppmline, "%lu %lu", &width, &height);
110
111 do {
112 fgets(ppmline, 256, infile);
113 } while (ppmline[0] == '#');
114 sscanf(ppmline, "%d", &maxval);
115 if (maxval != 255) {
116 fprintf(stderr, "ERROR: maxval = %d\n", maxval);
117 return 2;
118 }
119 bit_depth = 8;
120
121 *pWidth = width;
122 *pHeight = height;
123
124 return 0;
125}
126
127
128
129
130/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
131 * scales values to 8-bit if necessary */
132
133int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
134{
135 return 1;
136}
137
138
139
140
141/* display_exponent == LUT_exponent * CRT_exponent */
142
143uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
144{
145 ulg rowbytes;
146
147
148 /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
149 * transparency chunks to full alpha channel; strip 16-bit-per-sample
150 * images to 8 bits per sample; and convert grayscale to RGB[A] */
151
152 /* GRR WARNING: grayscale needs to be expanded and channels reset! */
153
154 *pRowbytes = rowbytes = channels*width;
155 *pChannels = channels;
156
157 if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
158 return NULL;
159 }
160
161 Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height));
162
163
164 /* now we can go ahead and just read the whole image */
165
166 fread(image_data, 1L, rowbytes*height, saved_infile);
167
168
169 return image_data;
170}
171
172
173void readpng_cleanup(int free_image_data)
174{
175 if (free_image_data && image_data) {
176 free(image_data);
177 image_data = NULL;
178 }
179}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-win.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-win.c
new file mode 100644
index 0000000..1c22282
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-win.c
@@ -0,0 +1,728 @@
1/*---------------------------------------------------------------------------
2
3 rpng - simple PNG display program rpng-win.c
4
5 This program decodes and displays PNG images, with gamma correction and
6 optionally with a user-specified background color (in case the image has
7 transparency). It is very nearly the most basic PNG viewer possible.
8 This version is for 32-bit Windows; it may compile under 16-bit Windows
9 with a little tweaking (or maybe not).
10
11 to do:
12 - handle quoted command-line args (especially filenames with spaces)
13 - have minimum window width: oh well
14 - use %.1023s to simplify truncation of title-bar string?
15
16 ---------------------------------------------------------------------------
17
18 Changelog:
19 - 1.00: initial public release
20 - 1.01: modified to allow abbreviated options; fixed long/ulong mis-
21 match; switched to png_jmpbuf() macro
22 - 1.02: added extra set of parentheses to png_jmpbuf() macro; fixed
23 command-line parsing bug
24 - 1.10: enabled "message window"/console (thanks to David Geldreich)
25 - 2.00: dual-licensed (added GNU GPL)
26 - 2.01: fixed improper display of usage screen on PNG error(s)
27
28 ---------------------------------------------------------------------------
29
30 Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
31
32 This software is provided "as is," without warranty of any kind,
33 express or implied. In no event shall the author or contributors
34 be held liable for any damages arising in any way from the use of
35 this software.
36
37 The contents of this file are DUAL-LICENSED. You may modify and/or
38 redistribute this software according to the terms of one of the
39 following two licenses (at your option):
40
41
42 LICENSE 1 ("BSD-like with advertising clause"):
43
44 Permission is granted to anyone to use this software for any purpose,
45 including commercial applications, and to alter it and redistribute
46 it freely, subject to the following restrictions:
47
48 1. Redistributions of source code must retain the above copyright
49 notice, disclaimer, and this list of conditions.
50 2. Redistributions in binary form must reproduce the above copyright
51 notice, disclaimer, and this list of conditions in the documenta-
52 tion and/or other materials provided with the distribution.
53 3. All advertising materials mentioning features or use of this
54 software must display the following acknowledgment:
55
56 This product includes software developed by Greg Roelofs
57 and contributors for the book, "PNG: The Definitive Guide,"
58 published by O'Reilly and Associates.
59
60
61 LICENSE 2 (GNU GPL v2 or later):
62
63 This program is free software; you can redistribute it and/or modify
64 it under the terms of the GNU General Public License as published by
65 the Free Software Foundation; either version 2 of the License, or
66 (at your option) any later version.
67
68 This program is distributed in the hope that it will be useful,
69 but WITHOUT ANY WARRANTY; without even the implied warranty of
70 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71 GNU General Public License for more details.
72
73 You should have received a copy of the GNU General Public License
74 along with this program; if not, write to the Free Software Foundation,
75 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
76
77 ---------------------------------------------------------------------------*/
78
79#define PROGNAME "rpng-win"
80#define LONGNAME "Simple PNG Viewer for Windows"
81#define VERSION "2.01 of 16 March 2008"
82
83#include <stdio.h>
84#include <stdlib.h>
85#include <string.h>
86#include <time.h>
87#include <windows.h>
88#ifdef __CYGWIN__
89/* getch replacement. Turns out, we don't really need this,
90 * but leave it here if we ever enable any of the uses of
91 * _getch in the main code
92 */
93#include <unistd.h>
94#include <termio.h>
95#include <sys/ioctl.h>
96int repl_getch( void )
97{
98 char ch;
99 int fd = fileno(stdin);
100 struct termio old_tty, new_tty;
101
102 ioctl(fd, TCGETA, &old_tty);
103 new_tty = old_tty;
104 new_tty.c_lflag &= ~(ICANON | ECHO | ISIG);
105 ioctl(fd, TCSETA, &new_tty);
106 fread(&ch, 1, sizeof(ch), stdin);
107 ioctl(fd, TCSETA, &old_tty);
108
109 return ch;
110}
111#define _getch repl_getch
112#else
113#include <conio.h> /* only for _getch() */
114#endif
115
116/* #define DEBUG : this enables the Trace() macros */
117
118#include "readpng.h" /* typedefs, common macros, readpng prototypes */
119
120
121/* could just include png.h, but this macro is the only thing we need
122 * (name and typedefs changed to local versions); note that side effects
123 * only happen with alpha (which could easily be avoided with
124 * "ush acopy = (alpha);") */
125
126#define alpha_composite(composite, fg, alpha, bg) { \
127 ush temp = ((ush)(fg)*(ush)(alpha) + \
128 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
129 (composite) = (uch)((temp + (temp >> 8)) >> 8); \
130}
131
132
133/* local prototypes */
134static int rpng_win_create_window(HINSTANCE hInst, int showmode);
135static int rpng_win_display_image(void);
136static void rpng_win_cleanup(void);
137LRESULT CALLBACK rpng_win_wndproc(HWND, UINT, WPARAM, LPARAM);
138
139
140static char titlebar[1024];
141static char *progname = PROGNAME;
142static char *appname = LONGNAME;
143static char *filename;
144static FILE *infile;
145
146static char *bgstr;
147static uch bg_red=0, bg_green=0, bg_blue=0;
148
149static double display_exponent;
150
151static ulg image_width, image_height, image_rowbytes;
152static int image_channels;
153static uch *image_data;
154
155/* Windows-specific variables */
156static ulg wimage_rowbytes;
157static uch *dib;
158static uch *wimage_data;
159static BITMAPINFOHEADER *bmih;
160
161static HWND global_hwnd;
162
163
164
165
166int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode)
167{
168 char *args[1024]; /* arbitrary limit, but should suffice */
169 char *p, *q, **argv = args;
170 int argc = 0;
171 int rc, alen, flen;
172 int error = 0;
173 int have_bg = FALSE;
174 double LUT_exponent; /* just the lookup table */
175 double CRT_exponent = 2.2; /* just the monitor */
176 double default_display_exponent; /* whole display system */
177 MSG msg;
178
179
180 filename = (char *)NULL;
181
182#ifndef __CYGWIN__
183 /* First reenable console output, which normally goes to the bit bucket
184 * for windowed apps. Closing the console window will terminate the
185 * app. Thanks to David.Geldreich@realviz.com for supplying the magical
186 * incantation. */
187
188 AllocConsole();
189 freopen("CONOUT$", "a", stderr);
190 freopen("CONOUT$", "a", stdout);
191#endif
192
193
194 /* Next set the default value for our display-system exponent, i.e.,
195 * the product of the CRT exponent and the exponent corresponding to
196 * the frame-buffer's lookup table (LUT), if any. This is not an
197 * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
198 * ones), but it should cover 99% of the current possibilities. And
199 * yes, these ifdefs are completely wasted in a Windows program... */
200
201#if defined(NeXT)
202 LUT_exponent = 1.0 / 2.2;
203 /*
204 if (some_next_function_that_returns_gamma(&next_gamma))
205 LUT_exponent = 1.0 / next_gamma;
206 */
207#elif defined(sgi)
208 LUT_exponent = 1.0 / 1.7;
209 /* there doesn't seem to be any documented function to get the
210 * "gamma" value, so we do it the hard way */
211 infile = fopen("/etc/config/system.glGammaVal", "r");
212 if (infile) {
213 double sgi_gamma;
214
215 fgets(tmpline, 80, infile);
216 fclose(infile);
217 sgi_gamma = atof(tmpline);
218 if (sgi_gamma > 0.0)
219 LUT_exponent = 1.0 / sgi_gamma;
220 }
221#elif defined(Macintosh)
222 LUT_exponent = 1.8 / 2.61;
223 /*
224 if (some_mac_function_that_returns_gamma(&mac_gamma))
225 LUT_exponent = mac_gamma / 2.61;
226 */
227#else
228 LUT_exponent = 1.0; /* assume no LUT: most PCs */
229#endif
230
231 /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
232 default_display_exponent = LUT_exponent * CRT_exponent;
233
234
235 /* If the user has set the SCREEN_GAMMA environment variable as suggested
236 * (somewhat imprecisely) in the libpng documentation, use that; otherwise
237 * use the default value we just calculated. Either way, the user may
238 * override this via a command-line option. */
239
240 if ((p = getenv("SCREEN_GAMMA")) != NULL)
241 display_exponent = atof(p);
242 else
243 display_exponent = default_display_exponent;
244
245
246 /* Windows really hates command lines, so we have to set up our own argv.
247 * Note that we do NOT bother with quoted arguments here, so don't use
248 * filenames with spaces in 'em! */
249
250 argv[argc++] = PROGNAME;
251 p = cmd;
252 for (;;) {
253 if (*p == ' ')
254 while (*++p == ' ')
255 ;
256 /* now p points at the first non-space after some spaces */
257 if (*p == '\0')
258 break; /* nothing after the spaces: done */
259 argv[argc++] = q = p;
260 while (*q && *q != ' ')
261 ++q;
262 /* now q points at a space or the end of the string */
263 if (*q == '\0')
264 break; /* last argv already terminated; quit */
265 *q = '\0'; /* change space to terminator */
266 p = q + 1;
267 }
268 argv[argc] = NULL; /* terminate the argv array itself */
269
270
271 /* Now parse the command line for options and the PNG filename. */
272
273 while (*++argv && !error) {
274 if (!strncmp(*argv, "-gamma", 2)) {
275 if (!*++argv)
276 ++error;
277 else {
278 display_exponent = atof(*argv);
279 if (display_exponent <= 0.0)
280 ++error;
281 }
282 } else if (!strncmp(*argv, "-bgcolor", 2)) {
283 if (!*++argv)
284 ++error;
285 else {
286 bgstr = *argv;
287 if (strlen(bgstr) != 7 || bgstr[0] != '#')
288 ++error;
289 else
290 have_bg = TRUE;
291 }
292 } else {
293 if (**argv != '-') {
294 filename = *argv;
295 if (argv[1]) /* shouldn't be any more args after filename */
296 ++error;
297 } else
298 ++error; /* not expecting any other options */
299 }
300 }
301
302 if (!filename)
303 ++error;
304
305
306 /* print usage screen if any errors up to this point */
307
308 if (error) {
309#ifndef __CYGWIN__
310 int ch;
311#endif
312
313 fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname);
314 readpng_version_info();
315 fprintf(stderr, "\n"
316 "Usage: %s [-gamma exp] [-bgcolor bg] file.png\n"
317 " exp \ttransfer-function exponent (``gamma'') of the display\n"
318 "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
319 "\t\t to the product of the lookup-table exponent (varies)\n"
320 "\t\t and the CRT exponent (usually 2.2); must be positive\n"
321 " bg \tdesired background color in 7-character hex RGB format\n"
322 "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
323 "\t\t used with transparent images\n"
324 "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n"
325#ifndef __CYGWIN__
326 "Press Q or Esc to quit this usage screen.\n"
327#endif
328 "\n", PROGNAME, default_display_exponent);
329#ifndef __CYGWIN__
330 do
331 ch = _getch();
332 while (ch != 'q' && ch != 'Q' && ch != 0x1B);
333#endif
334 exit(1);
335 }
336
337
338 if (!(infile = fopen(filename, "rb"))) {
339 fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
340 ++error;
341 } else {
342 if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
343 switch (rc) {
344 case 1:
345 fprintf(stderr, PROGNAME
346 ": [%s] is not a PNG file: incorrect signature\n",
347 filename);
348 break;
349 case 2:
350 fprintf(stderr, PROGNAME
351 ": [%s] has bad IHDR (libpng longjmp)\n", filename);
352 break;
353 case 4:
354 fprintf(stderr, PROGNAME ": insufficient memory\n");
355 break;
356 default:
357 fprintf(stderr, PROGNAME
358 ": unknown readpng_init() error\n");
359 break;
360 }
361 ++error;
362 }
363 if (error)
364 fclose(infile);
365 }
366
367
368 if (error) {
369#ifndef __CYGWIN__
370 int ch;
371#endif
372
373 fprintf(stderr, PROGNAME ": aborting.\n");
374#ifndef __CYGWIN__
375 do
376 ch = _getch();
377 while (ch != 'q' && ch != 'Q' && ch != 0x1B);
378#endif
379 exit(2);
380 } else {
381 fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
382#ifndef __CYGWIN__
383 fprintf(stderr,
384 "\n [console window: closing this window will terminate %s]\n\n",
385 PROGNAME);
386#endif
387 }
388
389
390 /* set the title-bar string, but make sure buffer doesn't overflow */
391
392 alen = strlen(appname);
393 flen = strlen(filename);
394 if (alen + flen + 3 > 1023)
395 sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
396 else
397 sprintf(titlebar, "%s: %s", appname, filename);
398
399
400 /* if the user didn't specify a background color on the command line,
401 * check for one in the PNG file--if not, the initialized values of 0
402 * (black) will be used */
403
404 if (have_bg) {
405 unsigned r, g, b; /* this approach quiets compiler warnings */
406
407 sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
408 bg_red = (uch)r;
409 bg_green = (uch)g;
410 bg_blue = (uch)b;
411 } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
412 readpng_cleanup(TRUE);
413 fprintf(stderr, PROGNAME
414 ": libpng error while checking for background color\n");
415 exit(2);
416 }
417
418
419 /* do the basic Windows initialization stuff, make the window and fill it
420 * with the background color */
421
422 if (rpng_win_create_window(hInst, showmode))
423 exit(2);
424
425
426 /* decode the image, all at once */
427
428 Trace((stderr, "calling readpng_get_image()\n"))
429 image_data = readpng_get_image(display_exponent, &image_channels,
430 &image_rowbytes);
431 Trace((stderr, "done with readpng_get_image()\n"))
432
433
434 /* done with PNG file, so clean up to minimize memory usage (but do NOT
435 * nuke image_data!) */
436
437 readpng_cleanup(FALSE);
438 fclose(infile);
439
440 if (!image_data) {
441 fprintf(stderr, PROGNAME ": unable to decode PNG image\n");
442 exit(3);
443 }
444
445
446 /* display image (composite with background if requested) */
447
448 Trace((stderr, "calling rpng_win_display_image()\n"))
449 if (rpng_win_display_image()) {
450 free(image_data);
451 exit(4);
452 }
453 Trace((stderr, "done with rpng_win_display_image()\n"))
454
455
456 /* wait for the user to tell us when to quit */
457
458 printf(
459#ifndef __CYGWIN__
460 "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"
461#else
462 "Done. Press mouse button 1 (within image window) to quit.\n"
463#endif
464 );
465 fflush(stdout);
466
467 while (GetMessage(&msg, NULL, 0, 0)) {
468 TranslateMessage(&msg);
469 DispatchMessage(&msg);
470 }
471
472
473 /* OK, we're done: clean up all image and Windows resources and go away */
474
475 rpng_win_cleanup();
476
477 return msg.wParam;
478}
479
480
481
482
483
484static int rpng_win_create_window(HINSTANCE hInst, int showmode)
485{
486 uch *dest;
487 int extra_width, extra_height;
488 ulg i, j;
489 WNDCLASSEX wndclass;
490
491
492/*---------------------------------------------------------------------------
493 Allocate memory for the display-specific version of the image (round up
494 to multiple of 4 for Windows DIB).
495 ---------------------------------------------------------------------------*/
496
497 wimage_rowbytes = ((3*image_width + 3L) >> 2) << 2;
498
499 if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) +
500 wimage_rowbytes*image_height)))
501 {
502 return 4; /* fail */
503 }
504
505/*---------------------------------------------------------------------------
506 Initialize the DIB. Negative height means to use top-down BMP ordering
507 (must be uncompressed, but that's what we want). Bit count of 1, 4 or 8
508 implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values
509 directly => wimage_data begins immediately after BMP header.
510 ---------------------------------------------------------------------------*/
511
512 memset(dib, 0, sizeof(BITMAPINFOHEADER));
513 bmih = (BITMAPINFOHEADER *)dib;
514 bmih->biSize = sizeof(BITMAPINFOHEADER);
515 bmih->biWidth = image_width;
516 bmih->biHeight = -((long)image_height);
517 bmih->biPlanes = 1;
518 bmih->biBitCount = 24;
519 bmih->biCompression = 0;
520 wimage_data = dib + sizeof(BITMAPINFOHEADER);
521
522/*---------------------------------------------------------------------------
523 Fill in background color (black by default); data are in BGR order.
524 ---------------------------------------------------------------------------*/
525
526 for (j = 0; j < image_height; ++j) {
527 dest = wimage_data + j*wimage_rowbytes;
528 for (i = image_width; i > 0; --i) {
529 *dest++ = bg_blue;
530 *dest++ = bg_green;
531 *dest++ = bg_red;
532 }
533 }
534
535/*---------------------------------------------------------------------------
536 Set the window parameters.
537 ---------------------------------------------------------------------------*/
538
539 memset(&wndclass, 0, sizeof(wndclass));
540
541 wndclass.cbSize = sizeof(wndclass);
542 wndclass.style = CS_HREDRAW | CS_VREDRAW;
543 wndclass.lpfnWndProc = rpng_win_wndproc;
544 wndclass.hInstance = hInst;
545 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
546 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
547 wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
548 wndclass.lpszMenuName = NULL;
549 wndclass.lpszClassName = progname;
550 wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
551
552 RegisterClassEx(&wndclass);
553
554/*---------------------------------------------------------------------------
555 Finally, create the window.
556 ---------------------------------------------------------------------------*/
557
558 extra_width = 2*(GetSystemMetrics(SM_CXBORDER) +
559 GetSystemMetrics(SM_CXDLGFRAME));
560 extra_height = 2*(GetSystemMetrics(SM_CYBORDER) +
561 GetSystemMetrics(SM_CYDLGFRAME)) +
562 GetSystemMetrics(SM_CYCAPTION);
563
564 global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW,
565 CW_USEDEFAULT, CW_USEDEFAULT, image_width+extra_width,
566 image_height+extra_height, NULL, NULL, hInst, NULL);
567
568 ShowWindow(global_hwnd, showmode);
569 UpdateWindow(global_hwnd);
570
571 return 0;
572
573} /* end function rpng_win_create_window() */
574
575
576
577
578
579static int rpng_win_display_image()
580{
581 uch *src, *dest;
582 uch r, g, b, a;
583 ulg i, row, lastrow;
584 RECT rect;
585
586
587 Trace((stderr, "beginning display loop (image_channels == %d)\n",
588 image_channels))
589 Trace((stderr, "(width = %ld, rowbytes = %ld, wimage_rowbytes = %d)\n",
590 image_width, image_rowbytes, wimage_rowbytes))
591
592
593/*---------------------------------------------------------------------------
594 Blast image data to buffer. This whole routine takes place before the
595 message loop begins, so there's no real point in any pseudo-progressive
596 display...
597 ---------------------------------------------------------------------------*/
598
599 for (lastrow = row = 0; row < image_height; ++row) {
600 src = image_data + row*image_rowbytes;
601 dest = wimage_data + row*wimage_rowbytes;
602 if (image_channels == 3) {
603 for (i = image_width; i > 0; --i) {
604 r = *src++;
605 g = *src++;
606 b = *src++;
607 *dest++ = b;
608 *dest++ = g; /* note reverse order */
609 *dest++ = r;
610 }
611 } else /* if (image_channels == 4) */ {
612 for (i = image_width; i > 0; --i) {
613 r = *src++;
614 g = *src++;
615 b = *src++;
616 a = *src++;
617 if (a == 255) {
618 *dest++ = b;
619 *dest++ = g;
620 *dest++ = r;
621 } else if (a == 0) {
622 *dest++ = bg_blue;
623 *dest++ = bg_green;
624 *dest++ = bg_red;
625 } else {
626 /* this macro (copied from png.h) composites the
627 * foreground and background values and puts the
628 * result into the first argument; there are no
629 * side effects with the first argument */
630 alpha_composite(*dest++, b, a, bg_blue);
631 alpha_composite(*dest++, g, a, bg_green);
632 alpha_composite(*dest++, r, a, bg_red);
633 }
634 }
635 }
636 /* display after every 16 lines */
637 if (((row+1) & 0xf) == 0) {
638 rect.left = 0L;
639 rect.top = (LONG)lastrow;
640 rect.right = (LONG)image_width; /* possibly off by one? */
641 rect.bottom = (LONG)lastrow + 16L; /* possibly off by one? */
642 InvalidateRect(global_hwnd, &rect, FALSE);
643 UpdateWindow(global_hwnd); /* similar to XFlush() */
644 lastrow = row + 1;
645 }
646 }
647
648 Trace((stderr, "calling final image-flush routine\n"))
649 if (lastrow < image_height) {
650 rect.left = 0L;
651 rect.top = (LONG)lastrow;
652 rect.right = (LONG)image_width; /* possibly off by one? */
653 rect.bottom = (LONG)image_height; /* possibly off by one? */
654 InvalidateRect(global_hwnd, &rect, FALSE);
655 UpdateWindow(global_hwnd); /* similar to XFlush() */
656 }
657
658/*
659 last param determines whether or not background is wiped before paint
660 InvalidateRect(global_hwnd, NULL, TRUE);
661 UpdateWindow(global_hwnd);
662 */
663
664 return 0;
665}
666
667
668
669
670
671static void rpng_win_cleanup()
672{
673 if (image_data) {
674 free(image_data);
675 image_data = NULL;
676 }
677
678 if (dib) {
679 free(dib);
680 dib = NULL;
681 }
682}
683
684
685
686
687
688LRESULT CALLBACK rpng_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP)
689{
690 HDC hdc;
691 PAINTSTRUCT ps;
692 int rc;
693
694 switch (iMsg) {
695 case WM_CREATE:
696 /* one-time processing here, if any */
697 return 0;
698
699 case WM_PAINT:
700 hdc = BeginPaint(hwnd, &ps);
701 /* dest */
702 rc = StretchDIBits(hdc, 0, 0, image_width, image_height,
703 /* source */
704 0, 0, image_width, image_height,
705 wimage_data, (BITMAPINFO *)bmih,
706 /* iUsage: no clue */
707 0, SRCCOPY);
708 EndPaint(hwnd, &ps);
709 return 0;
710
711 /* wait for the user to tell us when to quit */
712 case WM_CHAR:
713 switch (wP) { /* only need one, so ignore repeat count */
714 case 'q':
715 case 'Q':
716 case 0x1B: /* Esc key */
717 PostQuitMessage(0);
718 }
719 return 0;
720
721 case WM_LBUTTONDOWN: /* another way of quitting */
722 case WM_DESTROY:
723 PostQuitMessage(0);
724 return 0;
725 }
726
727 return DefWindowProc(hwnd, iMsg, wP, lP);
728}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-x.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-x.c
new file mode 100644
index 0000000..fc8be88
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-x.c
@@ -0,0 +1,904 @@
1/*---------------------------------------------------------------------------
2
3 rpng - simple PNG display program rpng-x.c
4
5 This program decodes and displays PNG images, with gamma correction and
6 optionally with a user-specified background color (in case the image has
7 transparency). It is very nearly the most basic PNG viewer possible.
8 This version is for the X Window System (tested by author under Unix and
9 by Martin Zinser under OpenVMS; may work under OS/2 with some tweaking).
10
11 to do:
12 - 8-bit (colormapped) X support
13 - use %.1023s to simplify truncation of title-bar string?
14
15 ---------------------------------------------------------------------------
16
17 Changelog:
18 - 1.01: initial public release
19 - 1.02: modified to allow abbreviated options; fixed long/ulong mis-
20 match; switched to png_jmpbuf() macro
21 - 1.10: added support for non-default visuals; fixed X pixel-conversion
22 - 1.11: added extra set of parentheses to png_jmpbuf() macro; fixed
23 command-line parsing bug
24 - 1.12: fixed some small X memory leaks (thanks to François Petitjean)
25 - 1.13: fixed XFreeGC() crash bug (thanks to Patrick Welche)
26 - 1.14: added support for X resources (thanks to Gerhard Niklasch)
27 - 2.00: dual-licensed (added GNU GPL)
28 - 2.01: fixed improper display of usage screen on PNG error(s)
29
30 ---------------------------------------------------------------------------
31
32 Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
33
34 This software is provided "as is," without warranty of any kind,
35 express or implied. In no event shall the author or contributors
36 be held liable for any damages arising in any way from the use of
37 this software.
38
39 The contents of this file are DUAL-LICENSED. You may modify and/or
40 redistribute this software according to the terms of one of the
41 following two licenses (at your option):
42
43
44 LICENSE 1 ("BSD-like with advertising clause"):
45
46 Permission is granted to anyone to use this software for any purpose,
47 including commercial applications, and to alter it and redistribute
48 it freely, subject to the following restrictions:
49
50 1. Redistributions of source code must retain the above copyright
51 notice, disclaimer, and this list of conditions.
52 2. Redistributions in binary form must reproduce the above copyright
53 notice, disclaimer, and this list of conditions in the documenta-
54 tion and/or other materials provided with the distribution.
55 3. All advertising materials mentioning features or use of this
56 software must display the following acknowledgment:
57
58 This product includes software developed by Greg Roelofs
59 and contributors for the book, "PNG: The Definitive Guide,"
60 published by O'Reilly and Associates.
61
62
63 LICENSE 2 (GNU GPL v2 or later):
64
65 This program is free software; you can redistribute it and/or modify
66 it under the terms of the GNU General Public License as published by
67 the Free Software Foundation; either version 2 of the License, or
68 (at your option) any later version.
69
70 This program is distributed in the hope that it will be useful,
71 but WITHOUT ANY WARRANTY; without even the implied warranty of
72 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73 GNU General Public License for more details.
74
75 You should have received a copy of the GNU General Public License
76 along with this program; if not, write to the Free Software Foundation,
77 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
78
79 ---------------------------------------------------------------------------*/
80
81#define PROGNAME "rpng-x"
82#define LONGNAME "Simple PNG Viewer for X"
83#define VERSION "2.01 of 16 March 2008"
84#define RESNAME "rpng" /* our X resource application name */
85#define RESCLASS "Rpng" /* our X resource class name */
86
87#include <stdio.h>
88#include <stdlib.h>
89#include <string.h>
90#include <time.h>
91#include <X11/Xlib.h>
92#include <X11/Xutil.h>
93#include <X11/Xos.h>
94#include <X11/keysym.h>
95
96/* #define DEBUG : this enables the Trace() macros */
97
98#include "readpng.h" /* typedefs, common macros, readpng prototypes */
99
100
101/* could just include png.h, but this macro is the only thing we need
102 * (name and typedefs changed to local versions); note that side effects
103 * only happen with alpha (which could easily be avoided with
104 * "ush acopy = (alpha);") */
105
106#define alpha_composite(composite, fg, alpha, bg) { \
107 ush temp = ((ush)(fg)*(ush)(alpha) + \
108 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
109 (composite) = (uch)((temp + (temp >> 8)) >> 8); \
110}
111
112
113/* local prototypes */
114static int rpng_x_create_window(void);
115static int rpng_x_display_image(void);
116static void rpng_x_cleanup(void);
117static int rpng_x_msb(ulg u32val);
118
119
120static char titlebar[1024], *window_name = titlebar;
121static char *appname = LONGNAME;
122static char *icon_name = PROGNAME;
123static char *res_name = RESNAME;
124static char *res_class = RESCLASS;
125static char *filename;
126static FILE *infile;
127
128static char *bgstr;
129static uch bg_red=0, bg_green=0, bg_blue=0;
130
131static double display_exponent;
132
133static ulg image_width, image_height, image_rowbytes;
134static int image_channels;
135static uch *image_data;
136
137/* X-specific variables */
138static char *displayname;
139static XImage *ximage;
140static Display *display;
141static int depth;
142static Visual *visual;
143static XVisualInfo *visual_list;
144static int RShift, GShift, BShift;
145static ulg RMask, GMask, BMask;
146static Window window;
147static GC gc;
148static Colormap colormap;
149
150static int have_nondefault_visual = FALSE;
151static int have_colormap = FALSE;
152static int have_window = FALSE;
153static int have_gc = FALSE;
154/*
155ulg numcolors=0, pixels[256];
156ush reds[256], greens[256], blues[256];
157 */
158
159
160
161
162int main(int argc, char **argv)
163{
164#ifdef sgi
165 char tmpline[80];
166#endif
167 char *p;
168 int rc, alen, flen;
169 int error = 0;
170 int have_bg = FALSE;
171 double LUT_exponent; /* just the lookup table */
172 double CRT_exponent = 2.2; /* just the monitor */
173 double default_display_exponent; /* whole display system */
174 XEvent e;
175 KeySym k;
176
177
178 displayname = (char *)NULL;
179 filename = (char *)NULL;
180
181
182 /* First set the default value for our display-system exponent, i.e.,
183 * the product of the CRT exponent and the exponent corresponding to
184 * the frame-buffer's lookup table (LUT), if any. This is not an
185 * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
186 * ones), but it should cover 99% of the current possibilities. */
187
188#if defined(NeXT)
189 LUT_exponent = 1.0 / 2.2;
190 /*
191 if (some_next_function_that_returns_gamma(&next_gamma))
192 LUT_exponent = 1.0 / next_gamma;
193 */
194#elif defined(sgi)
195 LUT_exponent = 1.0 / 1.7;
196 /* there doesn't seem to be any documented function to get the
197 * "gamma" value, so we do it the hard way */
198 infile = fopen("/etc/config/system.glGammaVal", "r");
199 if (infile) {
200 double sgi_gamma;
201
202 fgets(tmpline, 80, infile);
203 fclose(infile);
204 sgi_gamma = atof(tmpline);
205 if (sgi_gamma > 0.0)
206 LUT_exponent = 1.0 / sgi_gamma;
207 }
208#elif defined(Macintosh)
209 LUT_exponent = 1.8 / 2.61;
210 /*
211 if (some_mac_function_that_returns_gamma(&mac_gamma))
212 LUT_exponent = mac_gamma / 2.61;
213 */
214#else
215 LUT_exponent = 1.0; /* assume no LUT: most PCs */
216#endif
217
218 /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
219 default_display_exponent = LUT_exponent * CRT_exponent;
220
221
222 /* If the user has set the SCREEN_GAMMA environment variable as suggested
223 * (somewhat imprecisely) in the libpng documentation, use that; otherwise
224 * use the default value we just calculated. Either way, the user may
225 * override this via a command-line option. */
226
227 if ((p = getenv("SCREEN_GAMMA")) != NULL)
228 display_exponent = atof(p);
229 else
230 display_exponent = default_display_exponent;
231
232
233 /* Now parse the command line for options and the PNG filename. */
234
235 while (*++argv && !error) {
236 if (!strncmp(*argv, "-display", 2)) {
237 if (!*++argv)
238 ++error;
239 else
240 displayname = *argv;
241 } else if (!strncmp(*argv, "-gamma", 2)) {
242 if (!*++argv)
243 ++error;
244 else {
245 display_exponent = atof(*argv);
246 if (display_exponent <= 0.0)
247 ++error;
248 }
249 } else if (!strncmp(*argv, "-bgcolor", 2)) {
250 if (!*++argv)
251 ++error;
252 else {
253 bgstr = *argv;
254 if (strlen(bgstr) != 7 || bgstr[0] != '#')
255 ++error;
256 else
257 have_bg = TRUE;
258 }
259 } else {
260 if (**argv != '-') {
261 filename = *argv;
262 if (argv[1]) /* shouldn't be any more args after filename */
263 ++error;
264 } else
265 ++error; /* not expecting any other options */
266 }
267 }
268
269 if (!filename)
270 ++error;
271
272
273 /* print usage screen if any errors up to this point */
274
275 if (error) {
276 fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
277 readpng_version_info();
278 fprintf(stderr, "\n"
279 "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n"
280 " xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
281 " exp \ttransfer-function exponent (``gamma'') of the display\n"
282 "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
283 "\t\t to the product of the lookup-table exponent (varies)\n"
284 "\t\t and the CRT exponent (usually 2.2); must be positive\n"
285 " bg \tdesired background color in 7-character hex RGB format\n"
286 "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
287 "\t\t used with transparent images\n"
288 "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
289 "is displayed) to quit.\n"
290 "\n", PROGNAME, default_display_exponent);
291 exit(1);
292 }
293
294
295 if (!(infile = fopen(filename, "rb"))) {
296 fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
297 ++error;
298 } else {
299 if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
300 switch (rc) {
301 case 1:
302 fprintf(stderr, PROGNAME
303 ": [%s] is not a PNG file: incorrect signature\n",
304 filename);
305 break;
306 case 2:
307 fprintf(stderr, PROGNAME
308 ": [%s] has bad IHDR (libpng longjmp)\n", filename);
309 break;
310 case 4:
311 fprintf(stderr, PROGNAME ": insufficient memory\n");
312 break;
313 default:
314 fprintf(stderr, PROGNAME
315 ": unknown readpng_init() error\n");
316 break;
317 }
318 ++error;
319 } else {
320 display = XOpenDisplay(displayname);
321 if (!display) {
322 readpng_cleanup(TRUE);
323 fprintf(stderr, PROGNAME ": can't open X display [%s]\n",
324 displayname? displayname : "default");
325 ++error;
326 }
327 }
328 if (error)
329 fclose(infile);
330 }
331
332
333 if (error) {
334 fprintf(stderr, PROGNAME ": aborting.\n");
335 exit(2);
336 }
337
338
339 /* set the title-bar string, but make sure buffer doesn't overflow */
340
341 alen = strlen(appname);
342 flen = strlen(filename);
343 if (alen + flen + 3 > 1023)
344 sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
345 else
346 sprintf(titlebar, "%s: %s", appname, filename);
347
348
349 /* if the user didn't specify a background color on the command line,
350 * check for one in the PNG file--if not, the initialized values of 0
351 * (black) will be used */
352
353 if (have_bg) {
354 unsigned r, g, b; /* this approach quiets compiler warnings */
355
356 sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
357 bg_red = (uch)r;
358 bg_green = (uch)g;
359 bg_blue = (uch)b;
360 } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
361 readpng_cleanup(TRUE);
362 fprintf(stderr, PROGNAME
363 ": libpng error while checking for background color\n");
364 exit(2);
365 }
366
367
368 /* do the basic X initialization stuff, make the window and fill it
369 * with the background color */
370
371 if (rpng_x_create_window())
372 exit(2);
373
374
375 /* decode the image, all at once */
376
377 Trace((stderr, "calling readpng_get_image()\n"))
378 image_data = readpng_get_image(display_exponent, &image_channels,
379 &image_rowbytes);
380 Trace((stderr, "done with readpng_get_image()\n"))
381
382
383 /* done with PNG file, so clean up to minimize memory usage (but do NOT
384 * nuke image_data!) */
385
386 readpng_cleanup(FALSE);
387 fclose(infile);
388
389 if (!image_data) {
390 fprintf(stderr, PROGNAME ": unable to decode PNG image\n");
391 exit(3);
392 }
393
394
395 /* display image (composite with background if requested) */
396
397 Trace((stderr, "calling rpng_x_display_image()\n"))
398 if (rpng_x_display_image()) {
399 free(image_data);
400 exit(4);
401 }
402 Trace((stderr, "done with rpng_x_display_image()\n"))
403
404
405 /* wait for the user to tell us when to quit */
406
407 printf(
408 "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
409 fflush(stdout);
410
411 do
412 XNextEvent(display, &e);
413 while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
414 !(e.type == KeyPress && /* v--- or 1 for shifted keys */
415 ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) ));
416
417
418 /* OK, we're done: clean up all image and X resources and go away */
419
420 rpng_x_cleanup();
421
422 return 0;
423}
424
425
426
427
428
429static int rpng_x_create_window(void)
430{
431 uch *xdata;
432 int need_colormap = FALSE;
433 int screen, pad;
434 ulg bg_pixel = 0L;
435 ulg attrmask;
436 Window root;
437 XEvent e;
438 XGCValues gcvalues;
439 XSetWindowAttributes attr;
440 XTextProperty windowName, *pWindowName = &windowName;
441 XTextProperty iconName, *pIconName = &iconName;
442 XVisualInfo visual_info;
443 XSizeHints *size_hints;
444 XWMHints *wm_hints;
445 XClassHint *class_hints;
446
447
448 screen = DefaultScreen(display);
449 depth = DisplayPlanes(display, screen);
450 root = RootWindow(display, screen);
451
452#ifdef DEBUG
453 XSynchronize(display, True);
454#endif
455
456#if 0
457/* GRR: add 8-bit support */
458 if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) {
459 fprintf(stderr,
460 "screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n",
461 depth);
462 return 2;
463 }
464
465 XMatchVisualInfo(display, screen, depth,
466 (depth == 8)? PseudoColor : TrueColor, &visual_info);
467 visual = visual_info.visual;
468#else
469 if (depth != 16 && depth != 24 && depth != 32) {
470 int visuals_matched = 0;
471
472 Trace((stderr, "default depth is %d: checking other visuals\n",
473 depth))
474
475 /* 24-bit first */
476 visual_info.screen = screen;
477 visual_info.depth = 24;
478 visual_list = XGetVisualInfo(display,
479 VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
480 if (visuals_matched == 0) {
481/* GRR: add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
482 fprintf(stderr, "default screen depth %d not supported, and no"
483 " 24-bit visuals found\n", depth);
484 return 2;
485 }
486 Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
487 visuals_matched))
488 visual = visual_list[0].visual;
489 depth = visual_list[0].depth;
490/*
491 colormap_size = visual_list[0].colormap_size;
492 visual_class = visual->class;
493 visualID = XVisualIDFromVisual(visual);
494 */
495 have_nondefault_visual = TRUE;
496 need_colormap = TRUE;
497 } else {
498 XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
499 visual = visual_info.visual;
500 }
501#endif
502
503 RMask = visual->red_mask;
504 GMask = visual->green_mask;
505 BMask = visual->blue_mask;
506
507/* GRR: add/check 8-bit support */
508 if (depth == 8 || need_colormap) {
509 colormap = XCreateColormap(display, root, visual, AllocNone);
510 if (!colormap) {
511 fprintf(stderr, "XCreateColormap() failed\n");
512 return 2;
513 }
514 have_colormap = TRUE;
515 }
516 if (depth == 15 || depth == 16) {
517 RShift = 15 - rpng_x_msb(RMask); /* these are right-shifts */
518 GShift = 15 - rpng_x_msb(GMask);
519 BShift = 15 - rpng_x_msb(BMask);
520 } else if (depth > 16) {
521#define NO_24BIT_MASKS
522#ifdef NO_24BIT_MASKS
523 RShift = rpng_x_msb(RMask) - 7; /* these are left-shifts */
524 GShift = rpng_x_msb(GMask) - 7;
525 BShift = rpng_x_msb(BMask) - 7;
526#else
527 RShift = 7 - rpng_x_msb(RMask); /* these are right-shifts, too */
528 GShift = 7 - rpng_x_msb(GMask);
529 BShift = 7 - rpng_x_msb(BMask);
530#endif
531 }
532 if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
533 fprintf(stderr, "rpng internal logic error: negative X shift(s)!\n");
534 return 2;
535 }
536
537/*---------------------------------------------------------------------------
538 Finally, create the window.
539 ---------------------------------------------------------------------------*/
540
541 attr.backing_store = Always;
542 attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
543 attrmask = CWBackingStore | CWEventMask;
544 if (have_nondefault_visual) {
545 attr.colormap = colormap;
546 attr.background_pixel = 0;
547 attr.border_pixel = 1;
548 attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
549 }
550
551 window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0,
552 depth, InputOutput, visual, attrmask, &attr);
553
554 if (window == None) {
555 fprintf(stderr, "XCreateWindow() failed\n");
556 return 2;
557 } else
558 have_window = TRUE;
559
560 if (depth == 8)
561 XSetWindowColormap(display, window, colormap);
562
563 if (!XStringListToTextProperty(&window_name, 1, pWindowName))
564 pWindowName = NULL;
565 if (!XStringListToTextProperty(&icon_name, 1, pIconName))
566 pIconName = NULL;
567
568 /* OK if any hints allocation fails; XSetWMProperties() allows NULLs */
569
570 if ((size_hints = XAllocSizeHints()) != NULL) {
571 /* window will not be resizable */
572 size_hints->flags = PMinSize | PMaxSize;
573 size_hints->min_width = size_hints->max_width = (int)image_width;
574 size_hints->min_height = size_hints->max_height = (int)image_height;
575 }
576
577 if ((wm_hints = XAllocWMHints()) != NULL) {
578 wm_hints->initial_state = NormalState;
579 wm_hints->input = True;
580 /* wm_hints->icon_pixmap = icon_pixmap; */
581 wm_hints->flags = StateHint | InputHint /* | IconPixmapHint */ ;
582 }
583
584 if ((class_hints = XAllocClassHint()) != NULL) {
585 class_hints->res_name = res_name;
586 class_hints->res_class = res_class;
587 }
588
589 XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
590 size_hints, wm_hints, class_hints);
591
592 /* various properties and hints no longer needed; free memory */
593 if (pWindowName)
594 XFree(pWindowName->value);
595 if (pIconName)
596 XFree(pIconName->value);
597 if (size_hints)
598 XFree(size_hints);
599 if (wm_hints)
600 XFree(wm_hints);
601 if (class_hints)
602 XFree(class_hints);
603
604 XMapWindow(display, window);
605
606 gc = XCreateGC(display, window, 0, &gcvalues);
607 have_gc = TRUE;
608
609/*---------------------------------------------------------------------------
610 Fill window with the specified background color.
611 ---------------------------------------------------------------------------*/
612
613 if (depth == 24 || depth == 32) {
614 bg_pixel = ((ulg)bg_red << RShift) |
615 ((ulg)bg_green << GShift) |
616 ((ulg)bg_blue << BShift);
617 } else if (depth == 16) {
618 bg_pixel = ((((ulg)bg_red << 8) >> RShift) & RMask) |
619 ((((ulg)bg_green << 8) >> GShift) & GMask) |
620 ((((ulg)bg_blue << 8) >> BShift) & BMask);
621 } else /* depth == 8 */ {
622
623 /* GRR: add 8-bit support */
624
625 }
626
627 XSetForeground(display, gc, bg_pixel);
628 XFillRectangle(display, window, gc, 0, 0, image_width, image_height);
629
630/*---------------------------------------------------------------------------
631 Wait for first Expose event to do any drawing, then flush.
632 ---------------------------------------------------------------------------*/
633
634 do
635 XNextEvent(display, &e);
636 while (e.type != Expose || e.xexpose.count);
637
638 XFlush(display);
639
640/*---------------------------------------------------------------------------
641 Allocate memory for the X- and display-specific version of the image.
642 ---------------------------------------------------------------------------*/
643
644 if (depth == 24 || depth == 32) {
645 xdata = (uch *)malloc(4*image_width*image_height);
646 pad = 32;
647 } else if (depth == 16) {
648 xdata = (uch *)malloc(2*image_width*image_height);
649 pad = 16;
650 } else /* depth == 8 */ {
651 xdata = (uch *)malloc(image_width*image_height);
652 pad = 8;
653 }
654
655 if (!xdata) {
656 fprintf(stderr, PROGNAME ": unable to allocate image memory\n");
657 return 4;
658 }
659
660 ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
661 (char *)xdata, image_width, image_height, pad, 0);
662
663 if (!ximage) {
664 fprintf(stderr, PROGNAME ": XCreateImage() failed\n");
665 free(xdata);
666 return 3;
667 }
668
669 /* to avoid testing the byte order every pixel (or doubling the size of
670 * the drawing routine with a giant if-test), we arbitrarily set the byte
671 * order to MSBFirst and let Xlib worry about inverting things on little-
672 * endian machines (like Linux/x86, old VAXen, etc.)--this is not the most
673 * efficient approach (the giant if-test would be better), but in the
674 * interest of clarity, we take the easy way out... */
675
676 ximage->byte_order = MSBFirst;
677
678 return 0;
679
680} /* end function rpng_x_create_window() */
681
682
683
684
685
686static int rpng_x_display_image(void)
687{
688 uch *src;
689 char *dest;
690 uch r, g, b, a;
691 ulg i, row, lastrow = 0;
692 ulg pixel;
693 int ximage_rowbytes = ximage->bytes_per_line;
694/* int bpp = ximage->bits_per_pixel; */
695
696
697 Trace((stderr, "beginning display loop (image_channels == %d)\n",
698 image_channels))
699 Trace((stderr, " (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n",
700 image_width, image_rowbytes, ximage_rowbytes))
701 Trace((stderr, " (bpp = %d)\n", ximage->bits_per_pixel))
702 Trace((stderr, " (byte_order = %s)\n", ximage->byte_order == MSBFirst?
703 "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown")))
704
705 if (depth == 24 || depth == 32) {
706 ulg red, green, blue;
707
708 for (lastrow = row = 0; row < image_height; ++row) {
709 src = image_data + row*image_rowbytes;
710 dest = ximage->data + row*ximage_rowbytes;
711 if (image_channels == 3) {
712 for (i = image_width; i > 0; --i) {
713 red = *src++;
714 green = *src++;
715 blue = *src++;
716#ifdef NO_24BIT_MASKS
717 pixel = (red << RShift) |
718 (green << GShift) |
719 (blue << BShift);
720 /* recall that we set ximage->byte_order = MSBFirst above */
721 /* GRR BUG: this assumes bpp == 32, but may be 24: */
722 *dest++ = (char)((pixel >> 24) & 0xff);
723 *dest++ = (char)((pixel >> 16) & 0xff);
724 *dest++ = (char)((pixel >> 8) & 0xff);
725 *dest++ = (char)( pixel & 0xff);
726#else
727 red = (RShift < 0)? red << (-RShift) : red >> RShift;
728 green = (GShift < 0)? green << (-GShift) : green >> GShift;
729 blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
730 pixel = (red & RMask) | (green & GMask) | (blue & BMask);
731 /* recall that we set ximage->byte_order = MSBFirst above */
732 *dest++ = (char)((pixel >> 24) & 0xff);
733 *dest++ = (char)((pixel >> 16) & 0xff);
734 *dest++ = (char)((pixel >> 8) & 0xff);
735 *dest++ = (char)( pixel & 0xff);
736#endif
737 }
738 } else /* if (image_channels == 4) */ {
739 for (i = image_width; i > 0; --i) {
740 r = *src++;
741 g = *src++;
742 b = *src++;
743 a = *src++;
744 if (a == 255) {
745 red = r;
746 green = g;
747 blue = b;
748 } else if (a == 0) {
749 red = bg_red;
750 green = bg_green;
751 blue = bg_blue;
752 } else {
753 /* this macro (from png.h) composites the foreground
754 * and background values and puts the result into the
755 * first argument */
756 alpha_composite(red, r, a, bg_red);
757 alpha_composite(green, g, a, bg_green);
758 alpha_composite(blue, b, a, bg_blue);
759 }
760 pixel = (red << RShift) |
761 (green << GShift) |
762 (blue << BShift);
763 /* recall that we set ximage->byte_order = MSBFirst above */
764 *dest++ = (char)((pixel >> 24) & 0xff);
765 *dest++ = (char)((pixel >> 16) & 0xff);
766 *dest++ = (char)((pixel >> 8) & 0xff);
767 *dest++ = (char)( pixel & 0xff);
768 }
769 }
770 /* display after every 16 lines */
771 if (((row+1) & 0xf) == 0) {
772 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
773 (int)lastrow, image_width, 16);
774 XFlush(display);
775 lastrow = row + 1;
776 }
777 }
778
779 } else if (depth == 16) {
780 ush red, green, blue;
781
782 for (lastrow = row = 0; row < image_height; ++row) {
783 src = image_data + row*image_rowbytes;
784 dest = ximage->data + row*ximage_rowbytes;
785 if (image_channels == 3) {
786 for (i = image_width; i > 0; --i) {
787 red = ((ush)(*src) << 8);
788 ++src;
789 green = ((ush)(*src) << 8);
790 ++src;
791 blue = ((ush)(*src) << 8);
792 ++src;
793 pixel = ((red >> RShift) & RMask) |
794 ((green >> GShift) & GMask) |
795 ((blue >> BShift) & BMask);
796 /* recall that we set ximage->byte_order = MSBFirst above */
797 *dest++ = (char)((pixel >> 8) & 0xff);
798 *dest++ = (char)( pixel & 0xff);
799 }
800 } else /* if (image_channels == 4) */ {
801 for (i = image_width; i > 0; --i) {
802 r = *src++;
803 g = *src++;
804 b = *src++;
805 a = *src++;
806 if (a == 255) {
807 red = ((ush)r << 8);
808 green = ((ush)g << 8);
809 blue = ((ush)b << 8);
810 } else if (a == 0) {
811 red = ((ush)bg_red << 8);
812 green = ((ush)bg_green << 8);
813 blue = ((ush)bg_blue << 8);
814 } else {
815 /* this macro (from png.h) composites the foreground
816 * and background values and puts the result back into
817 * the first argument (== fg byte here: safe) */
818 alpha_composite(r, r, a, bg_red);
819 alpha_composite(g, g, a, bg_green);
820 alpha_composite(b, b, a, bg_blue);
821 red = ((ush)r << 8);
822 green = ((ush)g << 8);
823 blue = ((ush)b << 8);
824 }
825 pixel = ((red >> RShift) & RMask) |
826 ((green >> GShift) & GMask) |
827 ((blue >> BShift) & BMask);
828 /* recall that we set ximage->byte_order = MSBFirst above */
829 *dest++ = (char)((pixel >> 8) & 0xff);
830 *dest++ = (char)( pixel & 0xff);
831 }
832 }
833 /* display after every 16 lines */
834 if (((row+1) & 0xf) == 0) {
835 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
836 (int)lastrow, image_width, 16);
837 XFlush(display);
838 lastrow = row + 1;
839 }
840 }
841
842 } else /* depth == 8 */ {
843
844 /* GRR: add 8-bit support */
845
846 }
847
848 Trace((stderr, "calling final XPutImage()\n"))
849 if (lastrow < image_height) {
850 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
851 (int)lastrow, image_width, image_height-lastrow);
852 XFlush(display);
853 }
854
855 return 0;
856}
857
858
859
860
861static void rpng_x_cleanup(void)
862{
863 if (image_data) {
864 free(image_data);
865 image_data = NULL;
866 }
867
868 if (ximage) {
869 if (ximage->data) {
870 free(ximage->data); /* we allocated it, so we free it */
871 ximage->data = (char *)NULL; /* instead of XDestroyImage() */
872 }
873 XDestroyImage(ximage);
874 ximage = NULL;
875 }
876
877 if (have_gc)
878 XFreeGC(display, gc);
879
880 if (have_window)
881 XDestroyWindow(display, window);
882
883 if (have_colormap)
884 XFreeColormap(display, colormap);
885
886 if (have_nondefault_visual)
887 XFree(visual_list);
888}
889
890
891
892
893
894static int rpng_x_msb(ulg u32val)
895{
896 int i;
897
898 for (i = 31; i >= 0; --i) {
899 if (u32val & 0x80000000L)
900 break;
901 u32val <<= 1;
902 }
903 return i;
904}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng2-win.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng2-win.c
new file mode 100644
index 0000000..2303b58
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng2-win.c
@@ -0,0 +1,1253 @@
1/*---------------------------------------------------------------------------
2
3 rpng2 - progressive-model PNG display program rpng2-win.c
4
5 This program decodes and displays PNG files progressively, as if it were
6 a web browser (though the front end is only set up to read from files).
7 It supports gamma correction, user-specified background colors, and user-
8 specified background patterns (for transparent images). This version is
9 for 32-bit Windows; it may compile under 16-bit Windows with a little
10 tweaking (or maybe not). Thanks to Adam Costello and Pieter S. van der
11 Meulen for the "diamond" and "radial waves" patterns, respectively.
12
13 to do (someday, maybe):
14 - handle quoted command-line args (especially filenames with spaces)
15 - finish resizable checkerboard-gradient (sizes 4-128?)
16 - use %.1023s to simplify truncation of title-bar string?
17 - have minimum window width: oh well
18
19 ---------------------------------------------------------------------------
20
21 Changelog:
22 - 1.01: initial public release
23 - 1.02: fixed cut-and-paste error in usage screen (oops...)
24 - 1.03: modified to allow abbreviated options
25 - 1.04: removed bogus extra argument from usage fprintf() [Glenn R-P?];
26 fixed command-line parsing bug
27 - 1.10: enabled "message window"/console (thanks to David Geldreich)
28 - 1.20: added runtime MMX-enabling/disabling and new -mmx* options
29 - 1.21: made minor tweak to usage screen to fit within 25-line console
30 - 1.22: added AMD64/EM64T support (__x86_64__)
31 - 2.00: dual-licensed (added GNU GPL)
32 - 2.01: fixed 64-bit typo in readpng2.c
33 - 2.02: fixed improper display of usage screen on PNG error(s); fixed
34 unexpected-EOF and file-read-error cases
35 - 2.03: removed runtime MMX-enabling/disabling and obsolete -mmx* options
36
37 ---------------------------------------------------------------------------
38
39 Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
40
41 This software is provided "as is," without warranty of any kind,
42 express or implied. In no event shall the author or contributors
43 be held liable for any damages arising in any way from the use of
44 this software.
45
46 The contents of this file are DUAL-LICENSED. You may modify and/or
47 redistribute this software according to the terms of one of the
48 following two licenses (at your option):
49
50
51 LICENSE 1 ("BSD-like with advertising clause"):
52
53 Permission is granted to anyone to use this software for any purpose,
54 including commercial applications, and to alter it and redistribute
55 it freely, subject to the following restrictions:
56
57 1. Redistributions of source code must retain the above copyright
58 notice, disclaimer, and this list of conditions.
59 2. Redistributions in binary form must reproduce the above copyright
60 notice, disclaimer, and this list of conditions in the documenta-
61 tion and/or other materials provided with the distribution.
62 3. All advertising materials mentioning features or use of this
63 software must display the following acknowledgment:
64
65 This product includes software developed by Greg Roelofs
66 and contributors for the book, "PNG: The Definitive Guide,"
67 published by O'Reilly and Associates.
68
69
70 LICENSE 2 (GNU GPL v2 or later):
71
72 This program is free software; you can redistribute it and/or modify
73 it under the terms of the GNU General Public License as published by
74 the Free Software Foundation; either version 2 of the License, or
75 (at your option) any later version.
76
77 This program is distributed in the hope that it will be useful,
78 but WITHOUT ANY WARRANTY; without even the implied warranty of
79 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80 GNU General Public License for more details.
81
82 You should have received a copy of the GNU General Public License
83 along with this program; if not, write to the Free Software Foundation,
84 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
85
86 ---------------------------------------------------------------------------*/
87
88#define PROGNAME "rpng2-win"
89#define LONGNAME "Progressive PNG Viewer for Windows"
90#define VERSION "2.02 of 16 March 2008"
91
92#include <stdio.h>
93#include <stdlib.h>
94#include <string.h>
95#include <setjmp.h> /* for jmpbuf declaration in readpng2.h */
96#include <time.h>
97#include <math.h> /* only for PvdM background code */
98#include <windows.h>
99#ifdef __CYGWIN__
100/* getch replacement. Turns out, we don't really need this,
101 * but leave it here if we ever enable any of the uses of
102 * _getch in the main code
103 */
104#include <unistd.h>
105#include <termio.h>
106#include <sys/ioctl.h>
107int repl_getch( void )
108{
109 char ch;
110 int fd = fileno(stdin);
111 struct termio old_tty, new_tty;
112
113 ioctl(fd, TCGETA, &old_tty);
114 new_tty = old_tty;
115 new_tty.c_lflag &= ~(ICANON | ECHO | ISIG);
116 ioctl(fd, TCSETA, &new_tty);
117 fread(&ch, 1, sizeof(ch), stdin);
118 ioctl(fd, TCSETA, &old_tty);
119
120 return ch;
121}
122#define _getch repl_getch
123#else
124#include <conio.h> /* only for _getch() */
125#endif
126
127/* all for PvdM background code: */
128#ifndef PI
129# define PI 3.141592653589793238
130#endif
131#define PI_2 (PI*0.5)
132#define INV_PI_360 (360.0 / PI)
133#define MAX(a,b) (a>b?a:b)
134#define MIN(a,b) (a<b?a:b)
135#define CLIP(a,min,max) MAX(min,MIN((a),max))
136#define ABS(a) ((a)<0?-(a):(a))
137#define CLIP8P(c) MAX(0,(MIN((c),255))) /* 8-bit pos. integer (uch) */
138#define ROUNDF(f) ((int)(f + 0.5))
139
140#define rgb1_max bg_freq
141#define rgb1_min bg_gray
142#define rgb2_max bg_bsat
143#define rgb2_min bg_brot
144
145/* #define DEBUG */ /* this enables the Trace() macros */
146
147#include "readpng2.h" /* typedefs, common macros, readpng2 prototypes */
148
149
150/* could just include png.h, but this macro is the only thing we need
151 * (name and typedefs changed to local versions); note that side effects
152 * only happen with alpha (which could easily be avoided with
153 * "ush acopy = (alpha);") */
154
155#define alpha_composite(composite, fg, alpha, bg) { \
156 ush temp = ((ush)(fg)*(ush)(alpha) + \
157 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
158 (composite) = (uch)((temp + (temp >> 8)) >> 8); \
159}
160
161
162#define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this
163 * block size corresponds roughly to a download
164 * speed 10% faster than theoretical 33.6K maximum
165 * (assuming 8 data bits, 1 stop bit and no other
166 * overhead) */
167
168/* local prototypes */
169static void rpng2_win_init(void);
170static int rpng2_win_create_window(void);
171static int rpng2_win_load_bg_image(void);
172static void rpng2_win_display_row(ulg row);
173static void rpng2_win_finish_display(void);
174static void rpng2_win_cleanup(void);
175LRESULT CALLBACK rpng2_win_wndproc(HWND, UINT, WPARAM, LPARAM);
176
177
178static char titlebar[1024];
179static char *progname = PROGNAME;
180static char *appname = LONGNAME;
181static char *filename;
182static FILE *infile;
183
184static mainprog_info rpng2_info;
185
186static uch inbuf[INBUFSIZE];
187static int incount;
188
189static int pat = 6; /* must be less than num_bgpat */
190static int bg_image = 0;
191static int bgscale = 16;
192static ulg bg_rowbytes;
193static uch *bg_data;
194
195static struct rgb_color {
196 uch r, g, b;
197} rgb[] = {
198 { 0, 0, 0}, /* 0: black */
199 {255, 255, 255}, /* 1: white */
200 {173, 132, 57}, /* 2: tan */
201 { 64, 132, 0}, /* 3: medium green */
202 {189, 117, 1}, /* 4: gold */
203 {253, 249, 1}, /* 5: yellow */
204 { 0, 0, 255}, /* 6: blue */
205 { 0, 0, 120}, /* 7: medium blue */
206 {255, 0, 255}, /* 8: magenta */
207 { 64, 0, 64}, /* 9: dark magenta */
208 {255, 0, 0}, /* 10: red */
209 { 64, 0, 0}, /* 11: dark red */
210 {255, 127, 0}, /* 12: orange */
211 {192, 96, 0}, /* 13: darker orange */
212 { 24, 60, 0}, /* 14: dark green-yellow */
213 { 85, 125, 200} /* 15: ice blue */
214};
215/* not used for now, but should be for error-checking:
216static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color);
217 */
218
219/*
220 This whole struct is a fairly cheesy way to keep the number of
221 command-line options to a minimum. The radial-waves background
222 type is a particularly poor fit to the integer elements of the
223 struct...but a few macros and a little fixed-point math will do
224 wonders for ya.
225
226 type bits:
227 F E D C B A 9 8 7 6 5 4 3 2 1 0
228 | | | | |
229 | | +-+-+-- 0 = sharp-edged checkerboard
230 | | 1 = soft diamonds
231 | | 2 = radial waves
232 | | 3-7 = undefined
233 | +-- gradient #2 inverted?
234 +-- alternating columns inverted?
235 */
236static struct background_pattern {
237 ush type;
238 int rgb1_max, rgb1_min; /* or bg_freq, bg_gray */
239 int rgb2_max, rgb2_min; /* or bg_bsat, bg_brot (both scaled by 10)*/
240} bg[] = {
241 {0+8, 2,0, 1,15}, /* checkered: tan/black vs. white/ice blue */
242 {0+24, 2,0, 1,0}, /* checkered: tan/black vs. white/black */
243 {0+8, 4,5, 0,2}, /* checkered: gold/yellow vs. black/tan */
244 {0+8, 4,5, 0,6}, /* checkered: gold/yellow vs. black/blue */
245 {0, 7,0, 8,9}, /* checkered: deep blue/black vs. magenta */
246 {0+8, 13,0, 5,14}, /* checkered: orange/black vs. yellow */
247 {0+8, 12,0, 10,11}, /* checkered: orange/black vs. red */
248 {1, 7,0, 8,0}, /* diamonds: deep blue/black vs. magenta */
249 {1, 12,0, 11,0}, /* diamonds: orange vs. dark red */
250 {1, 10,0, 7,0}, /* diamonds: red vs. medium blue */
251 {1, 4,0, 5,0}, /* diamonds: gold vs. yellow */
252 {1, 3,0, 0,0}, /* diamonds: medium green vs. black */
253 {2, 16, 100, 20, 0}, /* radial: ~hard radial color-beams */
254 {2, 18, 100, 10, 2}, /* radial: soft, curved radial color-beams */
255 {2, 16, 256, 100, 250}, /* radial: very tight spiral */
256 {2, 10000, 256, 11, 0} /* radial: dipole-moire' (almost fractal) */
257};
258static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern);
259
260
261/* Windows-specific global variables (could go in struct, but messy...) */
262static ulg wimage_rowbytes;
263static uch *dib;
264static uch *wimage_data;
265static BITMAPINFOHEADER *bmih;
266
267static HWND global_hwnd;
268static HINSTANCE global_hInst;
269static int global_showmode;
270
271
272
273
274int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode)
275{
276 char *args[1024]; /* arbitrary limit, but should suffice */
277 char **argv = args;
278 char *p, *q, *bgstr = NULL;
279 int argc = 0;
280 int rc, alen, flen;
281 int error = 0;
282 int timing = FALSE;
283 int have_bg = FALSE;
284 double LUT_exponent; /* just the lookup table */
285 double CRT_exponent = 2.2; /* just the monitor */
286 double default_display_exponent; /* whole display system */
287 MSG msg;
288
289
290 /* First initialize a few things, just to be sure--memset takes care of
291 * default background color (black), booleans (FALSE), pointers (NULL),
292 * etc. */
293
294 global_hInst = hInst;
295 global_showmode = showmode;
296 filename = (char *)NULL;
297 memset(&rpng2_info, 0, sizeof(mainprog_info));
298
299#ifndef __CYGWIN__
300 /* Next reenable console output, which normally goes to the bit bucket
301 * for windowed apps. Closing the console window will terminate the
302 * app. Thanks to David.Geldreich@realviz.com for supplying the magical
303 * incantation. */
304
305 AllocConsole();
306 freopen("CONOUT$", "a", stderr);
307 freopen("CONOUT$", "a", stdout);
308#endif
309
310 /* Set the default value for our display-system exponent, i.e., the
311 * product of the CRT exponent and the exponent corresponding to
312 * the frame-buffer's lookup table (LUT), if any. This is not an
313 * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
314 * ones), but it should cover 99% of the current possibilities. And
315 * yes, these ifdefs are completely wasted in a Windows program... */
316
317#if defined(NeXT)
318 /* third-party utilities can modify the default LUT exponent */
319 LUT_exponent = 1.0 / 2.2;
320 /*
321 if (some_next_function_that_returns_gamma(&next_gamma))
322 LUT_exponent = 1.0 / next_gamma;
323 */
324#elif defined(sgi)
325 LUT_exponent = 1.0 / 1.7;
326 /* there doesn't seem to be any documented function to
327 * get the "gamma" value, so we do it the hard way */
328 infile = fopen("/etc/config/system.glGammaVal", "r");
329 if (infile) {
330 double sgi_gamma;
331
332 fgets(tmpline, 80, infile);
333 fclose(infile);
334 sgi_gamma = atof(tmpline);
335 if (sgi_gamma > 0.0)
336 LUT_exponent = 1.0 / sgi_gamma;
337 }
338#elif defined(Macintosh)
339 LUT_exponent = 1.8 / 2.61;
340 /*
341 if (some_mac_function_that_returns_gamma(&mac_gamma))
342 LUT_exponent = mac_gamma / 2.61;
343 */
344#else
345 LUT_exponent = 1.0; /* assume no LUT: most PCs */
346#endif
347
348 /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
349 default_display_exponent = LUT_exponent * CRT_exponent;
350
351
352 /* If the user has set the SCREEN_GAMMA environment variable as suggested
353 * (somewhat imprecisely) in the libpng documentation, use that; otherwise
354 * use the default value we just calculated. Either way, the user may
355 * override this via a command-line option. */
356
357 if ((p = getenv("SCREEN_GAMMA")) != NULL)
358 rpng2_info.display_exponent = atof(p);
359 else
360 rpng2_info.display_exponent = default_display_exponent;
361
362
363 /* Windows really hates command lines, so we have to set up our own argv.
364 * Note that we do NOT bother with quoted arguments here, so don't use
365 * filenames with spaces in 'em! */
366
367 argv[argc++] = PROGNAME;
368 p = cmd;
369 for (;;) {
370 if (*p == ' ')
371 while (*++p == ' ')
372 ;
373 /* now p points at the first non-space after some spaces */
374 if (*p == '\0')
375 break; /* nothing after the spaces: done */
376 argv[argc++] = q = p;
377 while (*q && *q != ' ')
378 ++q;
379 /* now q points at a space or the end of the string */
380 if (*q == '\0')
381 break; /* last argv already terminated; quit */
382 *q = '\0'; /* change space to terminator */
383 p = q + 1;
384 }
385 argv[argc] = NULL; /* terminate the argv array itself */
386
387
388 /* Now parse the command line for options and the PNG filename. */
389
390 while (*++argv && !error) {
391 if (!strncmp(*argv, "-gamma", 2)) {
392 if (!*++argv)
393 ++error;
394 else {
395 rpng2_info.display_exponent = atof(*argv);
396 if (rpng2_info.display_exponent <= 0.0)
397 ++error;
398 }
399 } else if (!strncmp(*argv, "-bgcolor", 4)) {
400 if (!*++argv)
401 ++error;
402 else {
403 bgstr = *argv;
404 if (strlen(bgstr) != 7 || bgstr[0] != '#')
405 ++error;
406 else {
407 have_bg = TRUE;
408 bg_image = FALSE;
409 }
410 }
411 } else if (!strncmp(*argv, "-bgpat", 4)) {
412 if (!*++argv)
413 ++error;
414 else {
415 pat = atoi(*argv) - 1;
416 if (pat < 0 || pat >= num_bgpat)
417 ++error;
418 else {
419 bg_image = TRUE;
420 have_bg = FALSE;
421 }
422 }
423 } else if (!strncmp(*argv, "-timing", 2)) {
424 timing = TRUE;
425 } else {
426 if (**argv != '-') {
427 filename = *argv;
428 if (argv[1]) /* shouldn't be any more args after filename */
429 ++error;
430 } else
431 ++error; /* not expecting any other options */
432 }
433 }
434
435 if (!filename)
436 ++error;
437
438
439 /* print usage screen if any errors up to this point */
440
441 if (error) {
442#ifndef __CYGWIN__
443 int ch;
444#endif
445
446 fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname);
447 readpng2_version_info();
448 fprintf(stderr, "\n"
449 "Usage: %s [-gamma exp] [-bgcolor bg | -bgpat pat] [-timing]\n"
450 " %*s file.png\n\n"
451 " exp \ttransfer-function exponent (``gamma'') of the display\n"
452 "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
453 "\t\t to the product of the lookup-table exponent (varies)\n"
454 "\t\t and the CRT exponent (usually 2.2); must be positive\n"
455 " bg \tdesired background color in 7-character hex RGB format\n"
456 "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
457 "\t\t used with transparent images; overrides -bgpat option\n"
458 " pat \tdesired background pattern number (1-%d); used with\n"
459 "\t\t transparent images; overrides -bgcolor option\n"
460 " -timing\tenables delay for every block read, to simulate modem\n"
461 "\t\t download of image (~36 Kbps)\n"
462 "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n"
463#ifndef __CYGWIN__
464 "Press Q or Esc to quit this usage screen. ",
465#else
466 ,
467#endif
468 PROGNAME,
469#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) && \
470 !(defined(__CYGWIN__) || defined(__MINGW32__))
471 (int)strlen(PROGNAME), " ",
472#endif
473 (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat);
474 fflush(stderr);
475#ifndef __CYGWIN__
476 do
477 ch = _getch();
478 while (ch != 'q' && ch != 'Q' && ch != 0x1B);
479#endif
480 exit(1);
481 }
482
483
484 if (!(infile = fopen(filename, "rb"))) {
485 fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
486 ++error;
487 } else {
488 incount = fread(inbuf, 1, INBUFSIZE, infile);
489 if (incount < 8 || !readpng2_check_sig(inbuf, 8)) {
490 fprintf(stderr, PROGNAME
491 ": [%s] is not a PNG file: incorrect signature\n",
492 filename);
493 ++error;
494 } else if ((rc = readpng2_init(&rpng2_info)) != 0) {
495 switch (rc) {
496 case 2:
497 fprintf(stderr, PROGNAME
498 ": [%s] has bad IHDR (libpng longjmp)\n", filename);
499 break;
500 case 4:
501 fprintf(stderr, PROGNAME ": insufficient memory\n");
502 break;
503 default:
504 fprintf(stderr, PROGNAME
505 ": unknown readpng2_init() error\n");
506 break;
507 }
508 ++error;
509 }
510 if (error)
511 fclose(infile);
512 }
513
514
515 if (error) {
516#ifndef __CYGWIN__
517 int ch;
518#endif
519
520 fprintf(stderr, PROGNAME ": aborting.\n");
521#ifndef __CYGWIN__
522 do
523 ch = _getch();
524 while (ch != 'q' && ch != 'Q' && ch != 0x1B);
525#endif
526 exit(2);
527 } else {
528 fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
529#ifndef __CYGWIN__
530 fprintf(stderr,
531 "\n [console window: closing this window will terminate %s]\n\n",
532 PROGNAME);
533#endif
534 fflush(stderr);
535 }
536
537
538 /* set the title-bar string, but make sure buffer doesn't overflow */
539
540 alen = strlen(appname);
541 flen = strlen(filename);
542 if (alen + flen + 3 > 1023)
543 sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
544 else
545 sprintf(titlebar, "%s: %s", appname, filename);
546
547
548 /* set some final rpng2_info variables before entering main data loop */
549
550 if (have_bg) {
551 unsigned r, g, b; /* this approach quiets compiler warnings */
552
553 sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
554 rpng2_info.bg_red = (uch)r;
555 rpng2_info.bg_green = (uch)g;
556 rpng2_info.bg_blue = (uch)b;
557 } else
558 rpng2_info.need_bgcolor = TRUE;
559
560 rpng2_info.state = kPreInit;
561 rpng2_info.mainprog_init = rpng2_win_init;
562 rpng2_info.mainprog_display_row = rpng2_win_display_row;
563 rpng2_info.mainprog_finish_display = rpng2_win_finish_display;
564
565
566 /* OK, this is the fun part: call readpng2_decode_data() at the start of
567 * the loop to deal with our first buffer of data (read in above to verify
568 * that the file is a PNG image), then loop through the file and continue
569 * calling the same routine to handle each chunk of data. It in turn
570 * passes the data to libpng, which will invoke one or more of our call-
571 * backs as decoded data become available. We optionally call Sleep() for
572 * one second per iteration to simulate downloading the image via an analog
573 * modem. */
574
575 for (;;) {
576 Trace((stderr, "about to call readpng2_decode_data()\n"))
577 if (readpng2_decode_data(&rpng2_info, inbuf, incount))
578 ++error;
579 Trace((stderr, "done with readpng2_decode_data()\n"))
580
581 if (error || incount != INBUFSIZE || rpng2_info.state == kDone) {
582 if (rpng2_info.state == kDone) {
583 Trace((stderr, "done decoding PNG image\n"))
584 } else if (ferror(infile)) {
585 fprintf(stderr, PROGNAME
586 ": error while reading PNG image file\n");
587 exit(3);
588 } else if (feof(infile)) {
589 fprintf(stderr, PROGNAME ": end of file reached "
590 "(unexpectedly) while reading PNG image file\n");
591 exit(3);
592 } else /* if (error) */ {
593 /* will print error message below */
594 }
595 break;
596 }
597
598 if (timing)
599 Sleep(1000L);
600
601 incount = fread(inbuf, 1, INBUFSIZE, infile);
602 }
603
604
605 /* clean up PNG stuff and report any decoding errors */
606
607 fclose(infile);
608 Trace((stderr, "about to call readpng2_cleanup()\n"))
609 readpng2_cleanup(&rpng2_info);
610
611 if (error) {
612 fprintf(stderr, PROGNAME ": libpng error while decoding PNG image\n");
613 exit(3);
614 }
615
616
617 /* wait for the user to tell us when to quit */
618
619 while (GetMessage(&msg, NULL, 0, 0)) {
620 TranslateMessage(&msg);
621 DispatchMessage(&msg);
622 }
623
624
625 /* we're done: clean up all image and Windows resources and go away */
626
627 Trace((stderr, "about to call rpng2_win_cleanup()\n"))
628 rpng2_win_cleanup();
629
630 return msg.wParam;
631}
632
633
634
635
636
637/* this function is called by readpng2_info_callback() in readpng2.c, which
638 * in turn is called by libpng after all of the pre-IDAT chunks have been
639 * read and processed--i.e., we now have enough info to finish initializing */
640
641static void rpng2_win_init()
642{
643 ulg i;
644 ulg rowbytes = rpng2_info.rowbytes;
645
646 Trace((stderr, "beginning rpng2_win_init()\n"))
647 Trace((stderr, " rowbytes = %d\n", rpng2_info.rowbytes))
648 Trace((stderr, " width = %ld\n", rpng2_info.width))
649 Trace((stderr, " height = %ld\n", rpng2_info.height))
650
651 rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height);
652 if (!rpng2_info.image_data) {
653 readpng2_cleanup(&rpng2_info);
654 return;
655 }
656
657 rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *));
658 if (!rpng2_info.row_pointers) {
659 free(rpng2_info.image_data);
660 rpng2_info.image_data = NULL;
661 readpng2_cleanup(&rpng2_info);
662 return;
663 }
664
665 for (i = 0; i < rpng2_info.height; ++i)
666 rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes;
667
668/*---------------------------------------------------------------------------
669 Do the basic Windows initialization stuff, make the window, and fill it
670 with the user-specified, file-specified or default background color.
671 ---------------------------------------------------------------------------*/
672
673 if (rpng2_win_create_window()) {
674 readpng2_cleanup(&rpng2_info);
675 return;
676 }
677
678 rpng2_info.state = kWindowInit;
679}
680
681
682
683
684
685static int rpng2_win_create_window()
686{
687 uch bg_red = rpng2_info.bg_red;
688 uch bg_green = rpng2_info.bg_green;
689 uch bg_blue = rpng2_info.bg_blue;
690 uch *dest;
691 int extra_width, extra_height;
692 ulg i, j;
693 WNDCLASSEX wndclass;
694 RECT rect;
695
696
697/*---------------------------------------------------------------------------
698 Allocate memory for the display-specific version of the image (round up
699 to multiple of 4 for Windows DIB).
700 ---------------------------------------------------------------------------*/
701
702 wimage_rowbytes = ((3*rpng2_info.width + 3L) >> 2) << 2;
703
704 if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) +
705 wimage_rowbytes*rpng2_info.height)))
706 {
707 return 4; /* fail */
708 }
709
710/*---------------------------------------------------------------------------
711 Initialize the DIB. Negative height means to use top-down BMP ordering
712 (must be uncompressed, but that's what we want). Bit count of 1, 4 or 8
713 implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values
714 directly => wimage_data begins immediately after BMP header.
715 ---------------------------------------------------------------------------*/
716
717 memset(dib, 0, sizeof(BITMAPINFOHEADER));
718 bmih = (BITMAPINFOHEADER *)dib;
719 bmih->biSize = sizeof(BITMAPINFOHEADER);
720 bmih->biWidth = rpng2_info.width;
721 bmih->biHeight = -((long)rpng2_info.height);
722 bmih->biPlanes = 1;
723 bmih->biBitCount = 24;
724 bmih->biCompression = 0;
725 wimage_data = dib + sizeof(BITMAPINFOHEADER);
726
727/*---------------------------------------------------------------------------
728 Fill window with the specified background color (default is black), but
729 defer loading faked "background image" until window is displayed (may be
730 slow to compute). Data are in BGR order.
731 ---------------------------------------------------------------------------*/
732
733 if (bg_image) { /* just fill with black for now */
734 memset(wimage_data, 0, wimage_rowbytes*rpng2_info.height);
735 } else {
736 for (j = 0; j < rpng2_info.height; ++j) {
737 dest = wimage_data + j*wimage_rowbytes;
738 for (i = rpng2_info.width; i > 0; --i) {
739 *dest++ = bg_blue;
740 *dest++ = bg_green;
741 *dest++ = bg_red;
742 }
743 }
744 }
745
746/*---------------------------------------------------------------------------
747 Set the window parameters.
748 ---------------------------------------------------------------------------*/
749
750 memset(&wndclass, 0, sizeof(wndclass));
751
752 wndclass.cbSize = sizeof(wndclass);
753 wndclass.style = CS_HREDRAW | CS_VREDRAW;
754 wndclass.lpfnWndProc = rpng2_win_wndproc;
755 wndclass.hInstance = global_hInst;
756 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
757 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
758 wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
759 wndclass.lpszMenuName = NULL;
760 wndclass.lpszClassName = progname;
761 wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
762
763 RegisterClassEx(&wndclass);
764
765/*---------------------------------------------------------------------------
766 Finally, create the window.
767 ---------------------------------------------------------------------------*/
768
769 extra_width = 2*(GetSystemMetrics(SM_CXBORDER) +
770 GetSystemMetrics(SM_CXDLGFRAME));
771 extra_height = 2*(GetSystemMetrics(SM_CYBORDER) +
772 GetSystemMetrics(SM_CYDLGFRAME)) +
773 GetSystemMetrics(SM_CYCAPTION);
774
775 global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW,
776 CW_USEDEFAULT, CW_USEDEFAULT, rpng2_info.width+extra_width,
777 rpng2_info.height+extra_height, NULL, NULL, global_hInst, NULL);
778
779 ShowWindow(global_hwnd, global_showmode);
780 UpdateWindow(global_hwnd);
781
782/*---------------------------------------------------------------------------
783 Now compute the background image and display it. If it fails (memory
784 allocation), revert to a plain background color.
785 ---------------------------------------------------------------------------*/
786
787 if (bg_image) {
788 static const char *msg = "Computing background image...";
789 int x, y, len = strlen(msg);
790 HDC hdc = GetDC(global_hwnd);
791 TEXTMETRIC tm;
792
793 GetTextMetrics(hdc, &tm);
794 x = (rpng2_info.width - len*tm.tmAveCharWidth)/2;
795 y = (rpng2_info.height - tm.tmHeight)/2;
796 SetBkMode(hdc, TRANSPARENT);
797 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
798 /* this can still begin out of bounds even if x is positive (???): */
799 TextOut(hdc, ((x < 0)? 0 : x), ((y < 0)? 0 : y), msg, len);
800 ReleaseDC(global_hwnd, hdc);
801
802 rpng2_win_load_bg_image(); /* resets bg_image if fails */
803 }
804
805 if (!bg_image) {
806 for (j = 0; j < rpng2_info.height; ++j) {
807 dest = wimage_data + j*wimage_rowbytes;
808 for (i = rpng2_info.width; i > 0; --i) {
809 *dest++ = bg_blue;
810 *dest++ = bg_green;
811 *dest++ = bg_red;
812 }
813 }
814 }
815
816 rect.left = 0L;
817 rect.top = 0L;
818 rect.right = (LONG)rpng2_info.width; /* possibly off by one? */
819 rect.bottom = (LONG)rpng2_info.height; /* possibly off by one? */
820 InvalidateRect(global_hwnd, &rect, FALSE);
821 UpdateWindow(global_hwnd); /* similar to XFlush() */
822
823 return 0;
824
825} /* end function rpng2_win_create_window() */
826
827
828
829
830
831static int rpng2_win_load_bg_image()
832{
833 uch *src, *dest;
834 uch r1, r2, g1, g2, b1, b2;
835 uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
836 int k, hmax, max;
837 int xidx, yidx, yidx_max = (bgscale-1);
838 int even_odd_vert, even_odd_horiz, even_odd;
839 int invert_gradient2 = (bg[pat].type & 0x08);
840 int invert_column;
841 ulg i, row;
842
843/*---------------------------------------------------------------------------
844 Allocate buffer for fake background image to be used with transparent
845 images; if this fails, revert to plain background color.
846 ---------------------------------------------------------------------------*/
847
848 bg_rowbytes = 3 * rpng2_info.width;
849 bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height);
850 if (!bg_data) {
851 fprintf(stderr, PROGNAME
852 ": unable to allocate memory for background image\n");
853 bg_image = 0;
854 return 1;
855 }
856
857/*---------------------------------------------------------------------------
858 Vertical gradients (ramps) in NxN squares, alternating direction and
859 colors (N == bgscale).
860 ---------------------------------------------------------------------------*/
861
862 if ((bg[pat].type & 0x07) == 0) {
863 uch r1_min = rgb[bg[pat].rgb1_min].r;
864 uch g1_min = rgb[bg[pat].rgb1_min].g;
865 uch b1_min = rgb[bg[pat].rgb1_min].b;
866 uch r2_min = rgb[bg[pat].rgb2_min].r;
867 uch g2_min = rgb[bg[pat].rgb2_min].g;
868 uch b2_min = rgb[bg[pat].rgb2_min].b;
869 int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
870 int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
871 int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
872 int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
873 int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
874 int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
875
876 for (row = 0; row < rpng2_info.height; ++row) {
877 yidx = row % bgscale;
878 even_odd_vert = (row / bgscale) & 1;
879
880 r1 = r1_min + (r1_diff * yidx) / yidx_max;
881 g1 = g1_min + (g1_diff * yidx) / yidx_max;
882 b1 = b1_min + (b1_diff * yidx) / yidx_max;
883 r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
884 g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
885 b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
886
887 r2 = r2_min + (r2_diff * yidx) / yidx_max;
888 g2 = g2_min + (g2_diff * yidx) / yidx_max;
889 b2 = b2_min + (b2_diff * yidx) / yidx_max;
890 r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
891 g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
892 b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
893
894 dest = bg_data + row*bg_rowbytes;
895 for (i = 0; i < rpng2_info.width; ++i) {
896 even_odd_horiz = (i / bgscale) & 1;
897 even_odd = even_odd_vert ^ even_odd_horiz;
898 invert_column =
899 (even_odd_horiz && (bg[pat].type & 0x10));
900 if (even_odd == 0) { /* gradient #1 */
901 if (invert_column) {
902 *dest++ = r1_inv;
903 *dest++ = g1_inv;
904 *dest++ = b1_inv;
905 } else {
906 *dest++ = r1;
907 *dest++ = g1;
908 *dest++ = b1;
909 }
910 } else { /* gradient #2 */
911 if ((invert_column && invert_gradient2) ||
912 (!invert_column && !invert_gradient2))
913 {
914 *dest++ = r2; /* not inverted or */
915 *dest++ = g2; /* doubly inverted */
916 *dest++ = b2;
917 } else {
918 *dest++ = r2_inv;
919 *dest++ = g2_inv; /* singly inverted */
920 *dest++ = b2_inv;
921 }
922 }
923 }
924 }
925
926/*---------------------------------------------------------------------------
927 Soft gradient-diamonds with scale = bgscale. Code contributed by Adam
928 M. Costello.
929 ---------------------------------------------------------------------------*/
930
931 } else if ((bg[pat].type & 0x07) == 1) {
932
933 hmax = (bgscale-1)/2; /* half the max weight of a color */
934 max = 2*hmax; /* the max weight of a color */
935
936 r1 = rgb[bg[pat].rgb1_max].r;
937 g1 = rgb[bg[pat].rgb1_max].g;
938 b1 = rgb[bg[pat].rgb1_max].b;
939 r2 = rgb[bg[pat].rgb2_max].r;
940 g2 = rgb[bg[pat].rgb2_max].g;
941 b2 = rgb[bg[pat].rgb2_max].b;
942
943 for (row = 0; row < rpng2_info.height; ++row) {
944 yidx = row % bgscale;
945 if (yidx > hmax)
946 yidx = bgscale-1 - yidx;
947 dest = bg_data + row*bg_rowbytes;
948 for (i = 0; i < rpng2_info.width; ++i) {
949 xidx = i % bgscale;
950 if (xidx > hmax)
951 xidx = bgscale-1 - xidx;
952 k = xidx + yidx;
953 *dest++ = (k*r1 + (max-k)*r2) / max;
954 *dest++ = (k*g1 + (max-k)*g2) / max;
955 *dest++ = (k*b1 + (max-k)*b2) / max;
956 }
957 }
958
959/*---------------------------------------------------------------------------
960 Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
961 soids will equal bgscale?]. This one is slow but very cool. Code con-
962 tributed by Pieter S. van der Meulen (originally in Smalltalk).
963 ---------------------------------------------------------------------------*/
964
965 } else if ((bg[pat].type & 0x07) == 2) {
966 uch ch;
967 int ii, x, y, hw, hh, grayspot;
968 double freq, rotate, saturate, gray, intensity;
969 double angle=0.0, aoffset=0.0, maxDist, dist;
970 double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
971
972 fprintf(stderr, "%s: computing radial background...",
973 PROGNAME);
974 fflush(stderr);
975
976 hh = rpng2_info.height / 2;
977 hw = rpng2_info.width / 2;
978
979 /* variables for radial waves:
980 * aoffset: number of degrees to rotate hue [CURRENTLY NOT USED]
981 * freq: number of color beams originating from the center
982 * grayspot: size of the graying center area (anti-alias)
983 * rotate: rotation of the beams as a function of radius
984 * saturate: saturation of beams' shape azimuthally
985 */
986 angle = CLIP(angle, 0.0, 360.0);
987 grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
988 freq = MAX((double)bg[pat].bg_freq, 0.0);
989 saturate = (double)bg[pat].bg_bsat * 0.1;
990 rotate = (double)bg[pat].bg_brot * 0.1;
991 gray = 0.0;
992 intensity = 0.0;
993 maxDist = (double)((hw*hw) + (hh*hh));
994
995 for (row = 0; row < rpng2_info.height; ++row) {
996 y = row - hh;
997 dest = bg_data + row*bg_rowbytes;
998 for (i = 0; i < rpng2_info.width; ++i) {
999 x = i - hw;
1000 angle = (x == 0)? PI_2 : atan((double)y / (double)x);
1001 gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
1002 gray = MIN(1.0, gray);
1003 dist = (double)((x*x) + (y*y)) / maxDist;
1004 intensity = cos((angle+(rotate*dist*PI)) * freq) *
1005 gray * saturate;
1006 intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
1007 hue = (angle + PI) * INV_PI_360 + aoffset;
1008 s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
1009 s = MIN(MAX(s,0.0), 1.0);
1010 v = MIN(MAX(intensity,0.0), 1.0);
1011
1012 if (s == 0.0) {
1013 ch = (uch)(v * 255.0);
1014 *dest++ = ch;
1015 *dest++ = ch;
1016 *dest++ = ch;
1017 } else {
1018 if ((hue < 0.0) || (hue >= 360.0))
1019 hue -= (((int)(hue / 360.0)) * 360.0);
1020 hue /= 60.0;
1021 ii = (int)hue;
1022 f = hue - (double)ii;
1023 p = (1.0 - s) * v;
1024 q = (1.0 - (s * f)) * v;
1025 t = (1.0 - (s * (1.0 - f))) * v;
1026 if (ii == 0) { red = v; green = t; blue = p; }
1027 else if (ii == 1) { red = q; green = v; blue = p; }
1028 else if (ii == 2) { red = p; green = v; blue = t; }
1029 else if (ii == 3) { red = p; green = q; blue = v; }
1030 else if (ii == 4) { red = t; green = p; blue = v; }
1031 else if (ii == 5) { red = v; green = p; blue = q; }
1032 *dest++ = (uch)(red * 255.0);
1033 *dest++ = (uch)(green * 255.0);
1034 *dest++ = (uch)(blue * 255.0);
1035 }
1036 }
1037 }
1038 fprintf(stderr, "done.\n");
1039 fflush(stderr);
1040 }
1041
1042/*---------------------------------------------------------------------------
1043 Blast background image to display buffer before beginning PNG decode;
1044 calling function will handle invalidation and UpdateWindow() call.
1045 ---------------------------------------------------------------------------*/
1046
1047 for (row = 0; row < rpng2_info.height; ++row) {
1048 src = bg_data + row*bg_rowbytes;
1049 dest = wimage_data + row*wimage_rowbytes;
1050 for (i = rpng2_info.width; i > 0; --i) {
1051 r1 = *src++;
1052 g1 = *src++;
1053 b1 = *src++;
1054 *dest++ = b1;
1055 *dest++ = g1; /* note reverse order */
1056 *dest++ = r1;
1057 }
1058 }
1059
1060 return 0;
1061
1062} /* end function rpng2_win_load_bg_image() */
1063
1064
1065
1066
1067
1068static void rpng2_win_display_row(ulg row)
1069{
1070 uch bg_red = rpng2_info.bg_red;
1071 uch bg_green = rpng2_info.bg_green;
1072 uch bg_blue = rpng2_info.bg_blue;
1073 uch *src, *src2=NULL, *dest;
1074 uch r, g, b, a;
1075 ulg i;
1076 static int rows=0;
1077 static ulg firstrow;
1078
1079/*---------------------------------------------------------------------------
1080 rows and firstrow simply track how many rows (and which ones) have not
1081 yet been displayed; alternatively, we could call InvalidateRect() for
1082 every row and not bother with the records-keeping.
1083 ---------------------------------------------------------------------------*/
1084
1085 Trace((stderr, "beginning rpng2_win_display_row()\n"))
1086
1087 if (rows == 0)
1088 firstrow = row; /* first row not yet displayed */
1089
1090 ++rows; /* count of rows received but not yet displayed */
1091
1092/*---------------------------------------------------------------------------
1093 Aside from the use of the rpng2_info struct and the lack of an outer
1094 loop (over rows), this routine is identical to rpng_win_display_image()
1095 in the non-progressive version of the program.
1096 ---------------------------------------------------------------------------*/
1097
1098 src = rpng2_info.image_data + row*rpng2_info.rowbytes;
1099 if (bg_image)
1100 src2 = bg_data + row*bg_rowbytes;
1101 dest = wimage_data + row*wimage_rowbytes;
1102
1103 if (rpng2_info.channels == 3) {
1104 for (i = rpng2_info.width; i > 0; --i) {
1105 r = *src++;
1106 g = *src++;
1107 b = *src++;
1108 *dest++ = b;
1109 *dest++ = g; /* note reverse order */
1110 *dest++ = r;
1111 }
1112 } else /* if (rpng2_info.channels == 4) */ {
1113 for (i = rpng2_info.width; i > 0; --i) {
1114 r = *src++;
1115 g = *src++;
1116 b = *src++;
1117 a = *src++;
1118 if (bg_image) {
1119 bg_red = *src2++;
1120 bg_green = *src2++;
1121 bg_blue = *src2++;
1122 }
1123 if (a == 255) {
1124 *dest++ = b;
1125 *dest++ = g;
1126 *dest++ = r;
1127 } else if (a == 0) {
1128 *dest++ = bg_blue;
1129 *dest++ = bg_green;
1130 *dest++ = bg_red;
1131 } else {
1132 /* this macro (copied from png.h) composites the
1133 * foreground and background values and puts the
1134 * result into the first argument; there are no
1135 * side effects with the first argument */
1136 alpha_composite(*dest++, b, a, bg_blue);
1137 alpha_composite(*dest++, g, a, bg_green);
1138 alpha_composite(*dest++, r, a, bg_red);
1139 }
1140 }
1141 }
1142
1143/*---------------------------------------------------------------------------
1144 Display after every 16 rows or when on last row. (Region may include
1145 previously displayed lines due to interlacing--i.e., not contiguous.)
1146 ---------------------------------------------------------------------------*/
1147
1148 if ((rows & 0xf) == 0 || row == rpng2_info.height-1) {
1149 RECT rect;
1150
1151 rect.left = 0L;
1152 rect.top = (LONG)firstrow;
1153 rect.right = (LONG)rpng2_info.width; /* possibly off by one? */
1154 rect.bottom = (LONG)row + 1L; /* possibly off by one? */
1155 InvalidateRect(global_hwnd, &rect, FALSE);
1156 UpdateWindow(global_hwnd); /* similar to XFlush() */
1157 rows = 0;
1158 }
1159
1160} /* end function rpng2_win_display_row() */
1161
1162
1163
1164
1165
1166static void rpng2_win_finish_display()
1167{
1168 Trace((stderr, "beginning rpng2_win_finish_display()\n"))
1169
1170 /* last row has already been displayed by rpng2_win_display_row(), so
1171 * we have nothing to do here except set a flag and let the user know
1172 * that the image is done */
1173
1174 rpng2_info.state = kDone;
1175 printf(
1176#ifndef __CYGWIN__
1177 "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"
1178#else
1179 "Done. Press mouse button 1 (within image window) to quit.\n"
1180#endif
1181 );
1182 fflush(stdout);
1183}
1184
1185
1186
1187
1188
1189static void rpng2_win_cleanup()
1190{
1191 if (bg_image && bg_data) {
1192 free(bg_data);
1193 bg_data = NULL;
1194 }
1195
1196 if (rpng2_info.image_data) {
1197 free(rpng2_info.image_data);
1198 rpng2_info.image_data = NULL;
1199 }
1200
1201 if (rpng2_info.row_pointers) {
1202 free(rpng2_info.row_pointers);
1203 rpng2_info.row_pointers = NULL;
1204 }
1205
1206 if (dib) {
1207 free(dib);
1208 dib = NULL;
1209 }
1210}
1211
1212
1213
1214
1215
1216LRESULT CALLBACK rpng2_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP)
1217{
1218 HDC hdc;
1219 PAINTSTRUCT ps;
1220 int rc;
1221
1222 switch (iMsg) {
1223 case WM_CREATE:
1224 /* one-time processing here, if any */
1225 return 0;
1226
1227 case WM_PAINT:
1228 hdc = BeginPaint(hwnd, &ps);
1229 rc = StretchDIBits(hdc, 0, 0, rpng2_info.width, rpng2_info.height,
1230 0, 0, rpng2_info.width, rpng2_info.height,
1231 wimage_data, (BITMAPINFO *)bmih,
1232 0, SRCCOPY);
1233 EndPaint(hwnd, &ps);
1234 return 0;
1235
1236 /* wait for the user to tell us when to quit */
1237 case WM_CHAR:
1238 switch (wP) { /* only need one, so ignore repeat count */
1239 case 'q':
1240 case 'Q':
1241 case 0x1B: /* Esc key */
1242 PostQuitMessage(0);
1243 }
1244 return 0;
1245
1246 case WM_LBUTTONDOWN: /* another way of quitting */
1247 case WM_DESTROY:
1248 PostQuitMessage(0);
1249 return 0;
1250 }
1251
1252 return DefWindowProc(hwnd, iMsg, wP, lP);
1253}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng2-x.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng2-x.c
new file mode 100644
index 0000000..6c687db
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng2-x.c
@@ -0,0 +1,2107 @@
1/*---------------------------------------------------------------------------
2
3 rpng2 - progressive-model PNG display program rpng2-x.c
4
5 This program decodes and displays PNG files progressively, as if it were
6 a web browser (though the front end is only set up to read from files).
7 It supports gamma correction, user-specified background colors, and user-
8 specified background patterns (for transparent images). This version is
9 for the X Window System (tested by the author under Unix and by Martin
10 Zinser under OpenVMS; may work under OS/2 with a little tweaking).
11
12 Thanks to Adam Costello and Pieter S. van der Meulen for the "diamond"
13 and "radial waves" patterns, respectively.
14
15 to do (someday, maybe):
16 - fix expose/redraw code: don't draw entire row if only part exposed
17 - 8-bit (colormapped) X support
18 - finish resizable checkerboard-gradient (sizes 4-128?)
19 - use %.1023s to simplify truncation of title-bar string?
20
21 ---------------------------------------------------------------------------
22
23 Changelog:
24 - 1.01: initial public release
25 - 1.02: modified to allow abbreviated options; fixed char/uchar mismatch
26 - 1.10: added support for non-default visuals; fixed X pixel-conversion
27 - 1.11: added -usleep option for demos; fixed command-line parsing bug
28 - 1.12: added -pause option for demos and testing
29 - 1.20: added runtime MMX-enabling/disabling and new -mmx* options
30 - 1.21: fixed some small X memory leaks (thanks to François Petitjean)
31 - 1.22: fixed XFreeGC() crash bug (thanks to Patrick Welche)
32 - 1.23: added -bgpat 0 mode (std white/gray checkerboard, 8x8 squares)
33 - 1.30: added -loop option for -bgpat (ifdef FEATURE_LOOP); fixed bpp =
34 24; added support for X resources (thanks to Gerhard Niklasch)
35 - 1.31: added code to skip unused chunks (thanks to Glenn Randers-Pehrson)
36 - 1.32: added AMD64/EM64T support (__x86_64__); added basic expose/redraw
37 handling
38 - 2.00: dual-licensed (added GNU GPL)
39 - 2.01: fixed 64-bit typo in readpng2.c; fixed -pause usage description
40 - 2.02: fixed improper display of usage screen on PNG error(s); fixed
41 unexpected-EOF and file-read-error cases; fixed Trace() cut-and-
42 paste bugs
43 - 2.03: deleted runtime MMX-enabling/disabling and obsolete -mmx* options
44
45 ---------------------------------------------------------------------------
46
47 Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
48
49 This software is provided "as is," without warranty of any kind,
50 express or implied. In no event shall the author or contributors
51 be held liable for any damages arising in any way from the use of
52 this software.
53
54 The contents of this file are DUAL-LICENSED. You may modify and/or
55 redistribute this software according to the terms of one of the
56 following two licenses (at your option):
57
58
59 LICENSE 1 ("BSD-like with advertising clause"):
60
61 Permission is granted to anyone to use this software for any purpose,
62 including commercial applications, and to alter it and redistribute
63 it freely, subject to the following restrictions:
64
65 1. Redistributions of source code must retain the above copyright
66 notice, disclaimer, and this list of conditions.
67 2. Redistributions in binary form must reproduce the above copyright
68 notice, disclaimer, and this list of conditions in the documenta-
69 tion and/or other materials provided with the distribution.
70 3. All advertising materials mentioning features or use of this
71 software must display the following acknowledgment:
72
73 This product includes software developed by Greg Roelofs
74 and contributors for the book, "PNG: The Definitive Guide,"
75 published by O'Reilly and Associates.
76
77
78 LICENSE 2 (GNU GPL v2 or later):
79
80 This program is free software; you can redistribute it and/or modify
81 it under the terms of the GNU General Public License as published by
82 the Free Software Foundation; either version 2 of the License, or
83 (at your option) any later version.
84
85 This program is distributed in the hope that it will be useful,
86 but WITHOUT ANY WARRANTY; without even the implied warranty of
87 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88 GNU General Public License for more details.
89
90 You should have received a copy of the GNU General Public License
91 along with this program; if not, write to the Free Software Foundation,
92 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
93
94 ---------------------------------------------------------------------------*/
95
96#define PROGNAME "rpng2-x"
97#define LONGNAME "Progressive PNG Viewer for X"
98#define VERSION "2.03 of 25 February 2010"
99#define RESNAME "rpng2" /* our X resource application name */
100#define RESCLASS "Rpng" /* our X resource class name */
101
102#include <stdio.h>
103#include <stdlib.h>
104#include <ctype.h>
105#include <string.h>
106#include <setjmp.h> /* for jmpbuf declaration in readpng2.h */
107#include <time.h>
108#include <math.h> /* only for PvdM background code */
109#include <X11/Xlib.h>
110#include <X11/Xutil.h>
111#include <X11/Xos.h>
112#include <X11/keysym.h> /* defines XK_* macros */
113
114#ifdef VMS
115# include <unistd.h>
116#endif
117
118/* all for PvdM background code: */
119#ifndef PI
120# define PI 3.141592653589793238
121#endif
122#define PI_2 (PI*0.5)
123#define INV_PI_360 (360.0 / PI)
124#define MAX(a,b) (a>b?a:b)
125#define MIN(a,b) (a<b?a:b)
126#define CLIP(a,min,max) MAX(min,MIN((a),max))
127#define ABS(a) ((a)<0?-(a):(a))
128#define CLIP8P(c) MAX(0,(MIN((c),255))) /* 8-bit pos. integer (uch) */
129#define ROUNDF(f) ((int)(f + 0.5))
130
131#define QUIT(e,k) ((e.type == ButtonPress && e.xbutton.button == Button1) || \
132 (e.type == KeyPress && /* v--- or 1 for shifted keys */ \
133 ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape)))
134
135#define NO_24BIT_MASKS /* undef case not fully written--only for redisplay() */
136
137#define rgb1_max bg_freq
138#define rgb1_min bg_gray
139#define rgb2_max bg_bsat
140#define rgb2_min bg_brot
141
142/* #define DEBUG */ /* this enables the Trace() macros */
143
144#include "readpng2.h" /* typedefs, common macros, readpng2 prototypes */
145
146
147/* could just include png.h, but this macro is the only thing we need
148 * (name and typedefs changed to local versions); note that side effects
149 * only happen with alpha (which could easily be avoided with
150 * "ush acopy = (alpha);") */
151
152#define alpha_composite(composite, fg, alpha, bg) { \
153 ush temp = ((ush)(fg)*(ush)(alpha) + \
154 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
155 (composite) = (uch)((temp + (temp >> 8)) >> 8); \
156}
157
158
159#define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this
160 * block size corresponds roughly to a download
161 * speed 10% faster than theoretical 33.6K maximum
162 * (assuming 8 data bits, 1 stop bit and no other
163 * overhead) */
164
165/* local prototypes */
166static void rpng2_x_init (void);
167static int rpng2_x_create_window (void);
168static int rpng2_x_load_bg_image (void);
169static void rpng2_x_display_row (ulg row);
170static void rpng2_x_finish_display (void);
171static void rpng2_x_redisplay_image (ulg startcol, ulg startrow,
172 ulg width, ulg height);
173#ifdef FEATURE_LOOP
174static void rpng2_x_reload_bg_image (void);
175static int is_number (char *p);
176#endif
177static void rpng2_x_cleanup (void);
178static int rpng2_x_msb (ulg u32val);
179
180
181static char titlebar[1024], *window_name = titlebar;
182static char *appname = LONGNAME;
183static char *icon_name = PROGNAME;
184static char *res_name = RESNAME;
185static char *res_class = RESCLASS;
186static char *filename;
187static FILE *infile;
188
189static mainprog_info rpng2_info;
190
191static uch inbuf[INBUFSIZE];
192static int incount;
193
194static int pat = 6; /* must be less than num_bgpat */
195static int bg_image = 0;
196static int bgscale, bgscale_default = 16;
197static ulg bg_rowbytes;
198static uch *bg_data;
199
200int pause_after_pass = FALSE;
201int demo_timing = FALSE;
202ulg usleep_duration = 0L;
203
204static struct rgb_color {
205 uch r, g, b;
206} rgb[] = {
207 { 0, 0, 0}, /* 0: black */
208 {255, 255, 255}, /* 1: white */
209 {173, 132, 57}, /* 2: tan */
210 { 64, 132, 0}, /* 3: medium green */
211 {189, 117, 1}, /* 4: gold */
212 {253, 249, 1}, /* 5: yellow */
213 { 0, 0, 255}, /* 6: blue */
214 { 0, 0, 120}, /* 7: medium blue */
215 {255, 0, 255}, /* 8: magenta */
216 { 64, 0, 64}, /* 9: dark magenta */
217 {255, 0, 0}, /* 10: red */
218 { 64, 0, 0}, /* 11: dark red */
219 {255, 127, 0}, /* 12: orange */
220 {192, 96, 0}, /* 13: darker orange */
221 { 24, 60, 0}, /* 14: dark green-yellow */
222 { 85, 125, 200}, /* 15: ice blue */
223 {192, 192, 192} /* 16: Netscape/Mosaic gray */
224};
225/* not used for now, but should be for error-checking:
226static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color);
227 */
228
229/*
230 This whole struct is a fairly cheesy way to keep the number of
231 command-line options to a minimum. The radial-waves background
232 type is a particularly poor fit to the integer elements of the
233 struct...but a few macros and a little fixed-point math will do
234 wonders for ya.
235
236 type bits:
237 F E D C B A 9 8 7 6 5 4 3 2 1 0
238 | | | | |
239 | | +-+-+-- 0 = sharp-edged checkerboard
240 | | 1 = soft diamonds
241 | | 2 = radial waves
242 | | 3-7 = undefined
243 | +-- gradient #2 inverted?
244 +-- alternating columns inverted?
245 */
246static struct background_pattern {
247 ush type;
248 int rgb1_max, rgb1_min; /* or bg_freq, bg_gray */
249 int rgb2_max, rgb2_min; /* or bg_bsat, bg_brot (both scaled by 10)*/
250} bg[] = {
251 {0, 1,1, 16,16}, /* checkered: white vs. light gray (basic) */
252 {0+8, 2,0, 1,15}, /* checkered: tan/black vs. white/ice blue */
253 {0+24, 2,0, 1,0}, /* checkered: tan/black vs. white/black */
254 {0+8, 4,5, 0,2}, /* checkered: gold/yellow vs. black/tan */
255 {0+8, 4,5, 0,6}, /* checkered: gold/yellow vs. black/blue */
256 {0, 7,0, 8,9}, /* checkered: deep blue/black vs. magenta */
257 {0+8, 13,0, 5,14}, /* checkered: orange/black vs. yellow */
258 {0+8, 12,0, 10,11}, /* checkered: orange/black vs. red */
259 {1, 7,0, 8,0}, /* diamonds: deep blue/black vs. magenta */
260 {1, 12,0, 11,0}, /* diamonds: orange vs. dark red */
261 {1, 10,0, 7,0}, /* diamonds: red vs. medium blue */
262 {1, 4,0, 5,0}, /* diamonds: gold vs. yellow */
263 {1, 3,0, 0,0}, /* diamonds: medium green vs. black */
264 {2, 16, 100, 20, 0}, /* radial: ~hard radial color-beams */
265 {2, 18, 100, 10, 2}, /* radial: soft, curved radial color-beams */
266 {2, 16, 256, 100, 250}, /* radial: very tight spiral */
267 {2, 10000, 256, 11, 0} /* radial: dipole-moire' (almost fractal) */
268};
269static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern);
270
271
272/* X-specific variables */
273static char *displayname;
274static XImage *ximage;
275static Display *display;
276static int depth;
277static Visual *visual;
278static XVisualInfo *visual_list;
279static int RShift, GShift, BShift;
280static ulg RMask, GMask, BMask;
281static Window window;
282static GC gc;
283static Colormap colormap;
284
285static int have_nondefault_visual = FALSE;
286static int have_colormap = FALSE;
287static int have_window = FALSE;
288static int have_gc = FALSE;
289
290
291
292
293int main(int argc, char **argv)
294{
295#ifdef sgi
296 char tmpline[80];
297#endif
298 char *p, *bgstr = NULL;
299 int rc, alen, flen;
300 int error = 0;
301 int timing = FALSE;
302 int have_bg = FALSE;
303#ifdef FEATURE_LOOP
304 int loop = FALSE;
305 long loop_interval = -1; /* seconds (100,000 max) */
306#endif
307 double LUT_exponent; /* just the lookup table */
308 double CRT_exponent = 2.2; /* just the monitor */
309 double default_display_exponent; /* whole display system */
310 XEvent e;
311 KeySym k;
312
313
314 /* First initialize a few things, just to be sure--memset takes care of
315 * default background color (black), booleans (FALSE), pointers (NULL),
316 * etc. */
317
318 displayname = (char *)NULL;
319 filename = (char *)NULL;
320 memset(&rpng2_info, 0, sizeof(mainprog_info));
321
322
323 /* Set the default value for our display-system exponent, i.e., the
324 * product of the CRT exponent and the exponent corresponding to
325 * the frame-buffer's lookup table (LUT), if any. This is not an
326 * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
327 * ones), but it should cover 99% of the current possibilities. */
328
329#if defined(NeXT)
330 /* third-party utilities can modify the default LUT exponent */
331 LUT_exponent = 1.0 / 2.2;
332 /*
333 if (some_next_function_that_returns_gamma(&next_gamma))
334 LUT_exponent = 1.0 / next_gamma;
335 */
336#elif defined(sgi)
337 LUT_exponent = 1.0 / 1.7;
338 /* there doesn't seem to be any documented function to
339 * get the "gamma" value, so we do it the hard way */
340 infile = fopen("/etc/config/system.glGammaVal", "r");
341 if (infile) {
342 double sgi_gamma;
343
344 fgets(tmpline, 80, infile);
345 fclose(infile);
346 sgi_gamma = atof(tmpline);
347 if (sgi_gamma > 0.0)
348 LUT_exponent = 1.0 / sgi_gamma;
349 }
350#elif defined(Macintosh)
351 LUT_exponent = 1.8 / 2.61;
352 /*
353 if (some_mac_function_that_returns_gamma(&mac_gamma))
354 LUT_exponent = mac_gamma / 2.61;
355 */
356#else
357 LUT_exponent = 1.0; /* assume no LUT: most PCs */
358#endif
359
360 /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
361 default_display_exponent = LUT_exponent * CRT_exponent;
362
363
364 /* If the user has set the SCREEN_GAMMA environment variable as suggested
365 * (somewhat imprecisely) in the libpng documentation, use that; otherwise
366 * use the default value we just calculated. Either way, the user may
367 * override this via a command-line option. */
368
369 if ((p = getenv("SCREEN_GAMMA")) != NULL)
370 rpng2_info.display_exponent = atof(p);
371 else
372 rpng2_info.display_exponent = default_display_exponent;
373
374
375 /* Now parse the command line for options and the PNG filename. */
376
377 while (*++argv && !error) {
378 if (!strncmp(*argv, "-display", 2)) {
379 if (!*++argv)
380 ++error;
381 else
382 displayname = *argv;
383 } else if (!strncmp(*argv, "-gamma", 2)) {
384 if (!*++argv)
385 ++error;
386 else {
387 rpng2_info.display_exponent = atof(*argv);
388 if (rpng2_info.display_exponent <= 0.0)
389 ++error;
390 }
391 } else if (!strncmp(*argv, "-bgcolor", 4)) {
392 if (!*++argv)
393 ++error;
394 else {
395 bgstr = *argv;
396 if (strlen(bgstr) != 7 || bgstr[0] != '#')
397 ++error;
398 else {
399 have_bg = TRUE;
400 bg_image = FALSE;
401 }
402 }
403 } else if (!strncmp(*argv, "-bgpat", 4)) {
404 if (!*++argv)
405 ++error;
406 else {
407 pat = atoi(*argv);
408 if (pat >= 0 && pat < num_bgpat) {
409 bg_image = TRUE;
410 have_bg = FALSE;
411 } else
412 ++error;
413 }
414 } else if (!strncmp(*argv, "-usleep", 2)) {
415 if (!*++argv)
416 ++error;
417 else {
418 usleep_duration = (ulg)atol(*argv);
419 demo_timing = TRUE;
420 }
421 } else if (!strncmp(*argv, "-pause", 2)) {
422 pause_after_pass = TRUE;
423 } else if (!strncmp(*argv, "-timing", 2)) {
424 timing = TRUE;
425#ifdef FEATURE_LOOP
426 } else if (!strncmp(*argv, "-loop", 2)) {
427 loop = TRUE;
428 if (!argv[1] || !is_number(argv[1]))
429 loop_interval = 2;
430 else {
431 ++argv;
432 loop_interval = atol(*argv);
433 if (loop_interval < 0)
434 loop_interval = 2;
435 else if (loop_interval > 100000) /* bit more than one day */
436 loop_interval = 100000;
437 }
438#endif
439 } else {
440 if (**argv != '-') {
441 filename = *argv;
442 if (argv[1]) /* shouldn't be any more args after filename */
443 ++error;
444 } else
445 ++error; /* not expecting any other options */
446 }
447 }
448
449 if (!filename)
450 ++error;
451
452
453 /* print usage screen if any errors up to this point */
454
455 if (error) {
456 fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname);
457 readpng2_version_info();
458 fprintf(stderr, "\n"
459 "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg | -bgpat pat]\n"
460#ifdef FEATURE_LOOP
461 " %*s [-usleep dur | -timing] [-pause] [-loop [sec]] file.png\n\n"
462#else
463 " %*s [-usleep dur | -timing] [-pause] file.png\n\n"
464#endif
465 " xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
466 " exp \ttransfer-function exponent (``gamma'') of the display\n"
467 "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
468 "\t\t to the product of the lookup-table exponent (varies)\n"
469 "\t\t and the CRT exponent (usually 2.2); must be positive\n"
470 " bg \tdesired background color in 7-character hex RGB format\n"
471 "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
472 "\t\t used with transparent images; overrides -bgpat\n"
473 " pat \tdesired background pattern number (0-%d); used with\n"
474 "\t\t transparent images; overrides -bgcolor\n"
475#ifdef FEATURE_LOOP
476 " -loop\tloops through background images after initial display\n"
477 "\t\t is complete (depends on -bgpat)\n"
478 " sec \tseconds to display each background image (default = 2)\n"
479#endif
480 " dur \tduration in microseconds to wait after displaying each\n"
481 "\t\t row (for demo purposes)\n"
482 " -timing\tenables delay for every block read, to simulate modem\n"
483 "\t\t download of image (~36 Kbps)\n"
484 " -pause\tpauses after displaying each pass until mouse clicked\n"
485 "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
486 "is displayed) to quit.\n"
487 "\n", PROGNAME,
488 (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat-1);
489 exit(1);
490 }
491
492
493 if (!(infile = fopen(filename, "rb"))) {
494 fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
495 ++error;
496 } else {
497 incount = fread(inbuf, 1, INBUFSIZE, infile);
498 if (incount < 8 || !readpng2_check_sig(inbuf, 8)) {
499 fprintf(stderr, PROGNAME
500 ": [%s] is not a PNG file: incorrect signature\n",
501 filename);
502 ++error;
503 } else if ((rc = readpng2_init(&rpng2_info)) != 0) {
504 switch (rc) {
505 case 2:
506 fprintf(stderr, PROGNAME
507 ": [%s] has bad IHDR (libpng longjmp)\n", filename);
508 break;
509 case 4:
510 fprintf(stderr, PROGNAME ": insufficient memory\n");
511 break;
512 default:
513 fprintf(stderr, PROGNAME
514 ": unknown readpng2_init() error\n");
515 break;
516 }
517 ++error;
518 } else {
519 Trace((stderr, "about to call XOpenDisplay()\n"))
520 display = XOpenDisplay(displayname);
521 if (!display) {
522 readpng2_cleanup(&rpng2_info);
523 fprintf(stderr, PROGNAME ": can't open X display [%s]\n",
524 displayname? displayname : "default");
525 ++error;
526 }
527 }
528 if (error)
529 fclose(infile);
530 }
531
532
533 if (error) {
534 fprintf(stderr, PROGNAME ": aborting.\n");
535 exit(2);
536 }
537
538
539 /* set the title-bar string, but make sure buffer doesn't overflow */
540
541 alen = strlen(appname);
542 flen = strlen(filename);
543 if (alen + flen + 3 > 1023)
544 sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
545 else
546 sprintf(titlebar, "%s: %s", appname, filename);
547
548
549 /* set some final rpng2_info variables before entering main data loop */
550
551 if (have_bg) {
552 unsigned r, g, b; /* this approach quiets compiler warnings */
553
554 sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
555 rpng2_info.bg_red = (uch)r;
556 rpng2_info.bg_green = (uch)g;
557 rpng2_info.bg_blue = (uch)b;
558 } else
559 rpng2_info.need_bgcolor = TRUE;
560
561 rpng2_info.state = kPreInit;
562 rpng2_info.mainprog_init = rpng2_x_init;
563 rpng2_info.mainprog_display_row = rpng2_x_display_row;
564 rpng2_info.mainprog_finish_display = rpng2_x_finish_display;
565
566
567 /* OK, this is the fun part: call readpng2_decode_data() at the start of
568 * the loop to deal with our first buffer of data (read in above to verify
569 * that the file is a PNG image), then loop through the file and continue
570 * calling the same routine to handle each chunk of data. It in turn
571 * passes the data to libpng, which will invoke one or more of our call-
572 * backs as decoded data become available. We optionally call sleep() for
573 * one second per iteration to simulate downloading the image via an analog
574 * modem. */
575
576 for (;;) {
577 Trace((stderr, "about to call readpng2_decode_data()\n"))
578 if (readpng2_decode_data(&rpng2_info, inbuf, incount))
579 ++error;
580 Trace((stderr, "done with readpng2_decode_data()\n"))
581
582 if (error || incount != INBUFSIZE || rpng2_info.state == kDone) {
583 if (rpng2_info.state == kDone) {
584 Trace((stderr, "done decoding PNG image\n"))
585 } else if (ferror(infile)) {
586 fprintf(stderr, PROGNAME
587 ": error while reading PNG image file\n");
588 exit(3);
589 } else if (feof(infile)) {
590 fprintf(stderr, PROGNAME ": end of file reached "
591 "(unexpectedly) while reading PNG image file\n");
592 exit(3);
593 } else /* if (error) */ {
594 /* will print error message below */
595 }
596 break;
597 }
598
599 if (timing)
600 sleep(1);
601
602 incount = fread(inbuf, 1, INBUFSIZE, infile);
603 }
604
605
606 /* clean up PNG stuff and report any decoding errors */
607
608 fclose(infile);
609 Trace((stderr, "about to call readpng2_cleanup()\n"))
610 readpng2_cleanup(&rpng2_info);
611
612 if (error) {
613 fprintf(stderr, PROGNAME ": libpng error while decoding PNG image\n");
614 exit(3);
615 }
616
617
618#ifdef FEATURE_LOOP
619
620 if (loop && bg_image) {
621 Trace((stderr, "entering -loop loop (FEATURE_LOOP)\n"))
622 for (;;) {
623 int i, use_sleep;
624 struct timeval now, then;
625
626 /* get current time and add loop_interval to get target time */
627 if (gettimeofday(&then, NULL) == 0) {
628 then.tv_sec += loop_interval;
629 use_sleep = FALSE;
630 } else
631 use_sleep = TRUE;
632
633 /* do quick check for a quit event but don't wait for it */
634 /* GRR BUG: should also check for Expose events and redraw... */
635 if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, &e))
636 if (QUIT(e,k))
637 break;
638
639 /* generate next background image */
640 if (++pat >= num_bgpat)
641 pat = 0;
642 rpng2_x_reload_bg_image();
643
644 /* wait for timeout, using whatever means are available */
645 if (use_sleep || gettimeofday(&now, NULL) != 0) {
646 for (i = loop_interval; i > 0; --i) {
647 sleep(1);
648 /* GRR BUG: also need to check for Expose (and redraw!) */
649 if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask,
650 &e) && QUIT(e,k))
651 break;
652 }
653 } else {
654 /* Y2038 BUG! */
655 if (now.tv_sec < then.tv_sec ||
656 (now.tv_sec == then.tv_sec && now.tv_usec < then.tv_usec))
657 {
658 int quit = FALSE;
659 long seconds_to_go = then.tv_sec - now.tv_sec;
660 long usleep_usec;
661
662 /* basically chew up most of remaining loop-interval with
663 * calls to sleep(1) interleaved with checks for quit
664 * events, but also recalc time-to-go periodically; when
665 * done, clean up any remaining time with usleep() call
666 * (could also use SIGALRM, but signals are a pain...) */
667 while (seconds_to_go-- > 1) {
668 int seconds_done = 0;
669
670 for (i = seconds_to_go; i > 0 && !quit; --i) {
671 sleep(1);
672 /* GRR BUG: need to check for Expose and redraw */
673 if (XCheckMaskEvent(display, KeyPressMask |
674 ButtonPressMask, &e) && QUIT(e,k))
675 quit = TRUE;
676 if (++seconds_done > 1000)
677 break; /* time to redo seconds_to_go meas. */
678 }
679 if (quit)
680 break;
681
682 /* OK, more than 1000 seconds since last check:
683 * correct the time-to-go measurement for drift */
684 if (gettimeofday(&now, NULL) == 0) {
685 if (now.tv_sec >= then.tv_sec)
686 break;
687 seconds_to_go = then.tv_sec - now.tv_sec;
688 } else
689 ++seconds_to_go; /* restore what we subtracted */
690 }
691 if (quit)
692 break; /* breaks outer do-loop, skips redisplay */
693
694 /* since difference between "now" and "then" is already
695 * eaten up to within a couple of seconds, don't need to
696 * worry about overflow--but might have overshot (neg.) */
697 if (gettimeofday(&now, NULL) == 0) {
698 usleep_usec = 1000000L*(then.tv_sec - now.tv_sec) +
699 then.tv_usec - now.tv_usec;
700 if (usleep_usec > 0)
701 usleep((ulg)usleep_usec);
702 }
703 }
704 }
705
706 /* composite image against new background and display (note that
707 * we do not take into account the time spent doing this...) */
708 rpng2_x_redisplay_image (0, 0, rpng2_info.width, rpng2_info.height);
709 }
710
711 } else /* FALL THROUGH and do the normal thing */
712
713#endif /* FEATURE_LOOP */
714
715 /* wait for the user to tell us when to quit */
716
717 if (rpng2_info.state >= kWindowInit) {
718 Trace((stderr, "entering final wait-for-quit-event loop\n"))
719 do {
720 XNextEvent(display, &e);
721 if (e.type == Expose) {
722 XExposeEvent *ex = (XExposeEvent *)&e;
723 rpng2_x_redisplay_image (ex->x, ex->y, ex->width, ex->height);
724 }
725 } while (!QUIT(e,k));
726 } else {
727 fprintf(stderr, PROGNAME ": init callback never called: probable "
728 "libpng error while decoding PNG metadata\n");
729 exit(4);
730 }
731
732
733 /* we're done: clean up all image and X resources and go away */
734
735 Trace((stderr, "about to call rpng2_x_cleanup()\n"))
736 rpng2_x_cleanup();
737
738 return 0;
739}
740
741
742
743
744
745/* this function is called by readpng2_info_callback() in readpng2.c, which
746 * in turn is called by libpng after all of the pre-IDAT chunks have been
747 * read and processed--i.e., we now have enough info to finish initializing */
748
749static void rpng2_x_init(void)
750{
751 ulg i;
752 ulg rowbytes = rpng2_info.rowbytes;
753
754 Trace((stderr, "beginning rpng2_x_init()\n"))
755 Trace((stderr, " rowbytes = %d\n", rpng2_info.rowbytes))
756 Trace((stderr, " width = %ld\n", rpng2_info.width))
757 Trace((stderr, " height = %ld\n", rpng2_info.height))
758
759 rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height);
760 if (!rpng2_info.image_data) {
761 readpng2_cleanup(&rpng2_info);
762 return;
763 }
764
765 rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *));
766 if (!rpng2_info.row_pointers) {
767 free(rpng2_info.image_data);
768 rpng2_info.image_data = NULL;
769 readpng2_cleanup(&rpng2_info);
770 return;
771 }
772
773 for (i = 0; i < rpng2_info.height; ++i)
774 rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes;
775
776
777 /* do the basic X initialization stuff, make the window, and fill it with
778 * the user-specified, file-specified or default background color or
779 * pattern */
780
781 if (rpng2_x_create_window()) {
782
783 /* GRR TEMPORARY HACK: this is fundamentally no different from cases
784 * above; libpng should call our error handler to longjmp() back to us
785 * when png_ptr goes away. If we/it segfault instead, seems like a
786 * libpng bug... */
787
788 /* we're here via libpng callback, so if window fails, clean and bail */
789 readpng2_cleanup(&rpng2_info);
790 rpng2_x_cleanup();
791 exit(2);
792 }
793
794 rpng2_info.state = kWindowInit;
795}
796
797
798
799
800
801static int rpng2_x_create_window(void)
802{
803 ulg bg_red = rpng2_info.bg_red;
804 ulg bg_green = rpng2_info.bg_green;
805 ulg bg_blue = rpng2_info.bg_blue;
806 ulg bg_pixel = 0L;
807 ulg attrmask;
808 int need_colormap = FALSE;
809 int screen, pad;
810 uch *xdata;
811 Window root;
812 XEvent e;
813 XGCValues gcvalues;
814 XSetWindowAttributes attr;
815 XTextProperty windowName, *pWindowName = &windowName;
816 XTextProperty iconName, *pIconName = &iconName;
817 XVisualInfo visual_info;
818 XSizeHints *size_hints;
819 XWMHints *wm_hints;
820 XClassHint *class_hints;
821
822
823 Trace((stderr, "beginning rpng2_x_create_window()\n"))
824
825 screen = DefaultScreen(display);
826 depth = DisplayPlanes(display, screen);
827 root = RootWindow(display, screen);
828
829#ifdef DEBUG
830 XSynchronize(display, True);
831#endif
832
833 if (depth != 16 && depth != 24 && depth != 32) {
834 int visuals_matched = 0;
835
836 Trace((stderr, "default depth is %d: checking other visuals\n",
837 depth))
838
839 /* 24-bit first */
840 visual_info.screen = screen;
841 visual_info.depth = 24;
842 visual_list = XGetVisualInfo(display,
843 VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
844 if (visuals_matched == 0) {
845/* GRR: add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
846 fprintf(stderr, "default screen depth %d not supported, and no"
847 " 24-bit visuals found\n", depth);
848 return 2;
849 }
850 Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
851 visuals_matched))
852 visual = visual_list[0].visual;
853 depth = visual_list[0].depth;
854/*
855 colormap_size = visual_list[0].colormap_size;
856 visual_class = visual->class;
857 visualID = XVisualIDFromVisual(visual);
858 */
859 have_nondefault_visual = TRUE;
860 need_colormap = TRUE;
861 } else {
862 XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
863 visual = visual_info.visual;
864 }
865
866 RMask = visual->red_mask;
867 GMask = visual->green_mask;
868 BMask = visual->blue_mask;
869
870/* GRR: add/check 8-bit support */
871 if (depth == 8 || need_colormap) {
872 colormap = XCreateColormap(display, root, visual, AllocNone);
873 if (!colormap) {
874 fprintf(stderr, "XCreateColormap() failed\n");
875 return 2;
876 }
877 have_colormap = TRUE;
878 if (depth == 8)
879 bg_image = FALSE; /* gradient just wastes palette entries */
880 }
881 if (depth == 15 || depth == 16) {
882 RShift = 15 - rpng2_x_msb(RMask); /* these are right-shifts */
883 GShift = 15 - rpng2_x_msb(GMask);
884 BShift = 15 - rpng2_x_msb(BMask);
885 } else if (depth > 16) {
886 RShift = rpng2_x_msb(RMask) - 7; /* these are left-shifts */
887 GShift = rpng2_x_msb(GMask) - 7;
888 BShift = rpng2_x_msb(BMask) - 7;
889 }
890 if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
891 fprintf(stderr, "rpng2 internal logic error: negative X shift(s)!\n");
892 return 2;
893 }
894
895/*---------------------------------------------------------------------------
896 Finally, create the window.
897 ---------------------------------------------------------------------------*/
898
899 attr.backing_store = Always;
900 attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
901 attrmask = CWBackingStore | CWEventMask;
902 if (have_nondefault_visual) {
903 attr.colormap = colormap;
904 attr.background_pixel = 0;
905 attr.border_pixel = 1;
906 attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
907 }
908
909 window = XCreateWindow(display, root, 0, 0, rpng2_info.width,
910 rpng2_info.height, 0, depth, InputOutput, visual, attrmask, &attr);
911
912 if (window == None) {
913 fprintf(stderr, "XCreateWindow() failed\n");
914 return 2;
915 } else
916 have_window = TRUE;
917
918 if (depth == 8)
919 XSetWindowColormap(display, window, colormap);
920
921 if (!XStringListToTextProperty(&window_name, 1, pWindowName))
922 pWindowName = NULL;
923 if (!XStringListToTextProperty(&icon_name, 1, pIconName))
924 pIconName = NULL;
925
926 /* OK if either hints allocation fails; XSetWMProperties() allows NULLs */
927
928 if ((size_hints = XAllocSizeHints()) != NULL) {
929 /* window will not be resizable */
930 size_hints->flags = PMinSize | PMaxSize;
931 size_hints->min_width = size_hints->max_width = (int)rpng2_info.width;
932 size_hints->min_height = size_hints->max_height =
933 (int)rpng2_info.height;
934 }
935
936 if ((wm_hints = XAllocWMHints()) != NULL) {
937 wm_hints->initial_state = NormalState;
938 wm_hints->input = True;
939 /* wm_hints->icon_pixmap = icon_pixmap; */
940 wm_hints->flags = StateHint | InputHint /* | IconPixmapHint */ ;
941 }
942
943 if ((class_hints = XAllocClassHint()) != NULL) {
944 class_hints->res_name = res_name;
945 class_hints->res_class = res_class;
946 }
947
948 XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
949 size_hints, wm_hints, class_hints);
950
951 /* various properties and hints no longer needed; free memory */
952 if (pWindowName)
953 XFree(pWindowName->value);
954 if (pIconName)
955 XFree(pIconName->value);
956 if (size_hints)
957 XFree(size_hints);
958 if (wm_hints)
959 XFree(wm_hints);
960 if (class_hints)
961 XFree(class_hints);
962
963 XMapWindow(display, window);
964
965 gc = XCreateGC(display, window, 0, &gcvalues);
966 have_gc = TRUE;
967
968/*---------------------------------------------------------------------------
969 Allocate memory for the X- and display-specific version of the image.
970 ---------------------------------------------------------------------------*/
971
972 if (depth == 24 || depth == 32) {
973 xdata = (uch *)malloc(4*rpng2_info.width*rpng2_info.height);
974 pad = 32;
975 } else if (depth == 16) {
976 xdata = (uch *)malloc(2*rpng2_info.width*rpng2_info.height);
977 pad = 16;
978 } else /* depth == 8 */ {
979 xdata = (uch *)malloc(rpng2_info.width*rpng2_info.height);
980 pad = 8;
981 }
982
983 if (!xdata) {
984 fprintf(stderr, PROGNAME ": unable to allocate image memory\n");
985 return 4;
986 }
987
988 ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
989 (char *)xdata, rpng2_info.width, rpng2_info.height, pad, 0);
990
991 if (!ximage) {
992 fprintf(stderr, PROGNAME ": XCreateImage() failed\n");
993 free(xdata);
994 return 3;
995 }
996
997 /* to avoid testing the byte order every pixel (or doubling the size of
998 * the drawing routine with a giant if-test), we arbitrarily set the byte
999 * order to MSBFirst and let Xlib worry about inverting things on little-
1000 * endian machines (e.g., Linux/x86, old VAXen, etc.)--this is not the
1001 * most efficient approach (the giant if-test would be better), but in
1002 * the interest of clarity, we'll take the easy way out... */
1003
1004 ximage->byte_order = MSBFirst;
1005
1006/*---------------------------------------------------------------------------
1007 Fill window with the specified background color (default is black) or
1008 faked "background image" (but latter is disabled if 8-bit; gradients
1009 just waste palette entries).
1010 ---------------------------------------------------------------------------*/
1011
1012 if (bg_image)
1013 rpng2_x_load_bg_image(); /* resets bg_image if fails */
1014
1015 if (!bg_image) {
1016 if (depth == 24 || depth == 32) {
1017 bg_pixel = (bg_red << RShift) |
1018 (bg_green << GShift) |
1019 (bg_blue << BShift);
1020 } else if (depth == 16) {
1021 bg_pixel = (((bg_red << 8) >> RShift) & RMask) |
1022 (((bg_green << 8) >> GShift) & GMask) |
1023 (((bg_blue << 8) >> BShift) & BMask);
1024 } else /* depth == 8 */ {
1025
1026 /* GRR: add 8-bit support */
1027
1028 }
1029 XSetForeground(display, gc, bg_pixel);
1030 XFillRectangle(display, window, gc, 0, 0, rpng2_info.width,
1031 rpng2_info.height);
1032 }
1033
1034/*---------------------------------------------------------------------------
1035 Wait for first Expose event to do any drawing, then flush and return.
1036 ---------------------------------------------------------------------------*/
1037
1038 do
1039 XNextEvent(display, &e);
1040 while (e.type != Expose || e.xexpose.count);
1041
1042 XFlush(display);
1043
1044 return 0;
1045
1046} /* end function rpng2_x_create_window() */
1047
1048
1049
1050
1051
1052static int rpng2_x_load_bg_image(void)
1053{
1054 uch *src;
1055 char *dest;
1056 uch r1, r2, g1, g2, b1, b2;
1057 uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
1058 int k, hmax, max;
1059 int xidx, yidx, yidx_max;
1060 int even_odd_vert, even_odd_horiz, even_odd;
1061 int invert_gradient2 = (bg[pat].type & 0x08);
1062 int invert_column;
1063 int ximage_rowbytes = ximage->bytes_per_line;
1064 ulg i, row;
1065 ulg pixel;
1066
1067/*---------------------------------------------------------------------------
1068 Allocate buffer for fake background image to be used with transparent
1069 images; if this fails, revert to plain background color.
1070 ---------------------------------------------------------------------------*/
1071
1072 bg_rowbytes = 3 * rpng2_info.width;
1073 bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height);
1074 if (!bg_data) {
1075 fprintf(stderr, PROGNAME
1076 ": unable to allocate memory for background image\n");
1077 bg_image = 0;
1078 return 1;
1079 }
1080
1081 bgscale = (pat == 0)? 8 : bgscale_default;
1082 yidx_max = bgscale - 1;
1083
1084/*---------------------------------------------------------------------------
1085 Vertical gradients (ramps) in NxN squares, alternating direction and
1086 colors (N == bgscale).
1087 ---------------------------------------------------------------------------*/
1088
1089 if ((bg[pat].type & 0x07) == 0) {
1090 uch r1_min = rgb[bg[pat].rgb1_min].r;
1091 uch g1_min = rgb[bg[pat].rgb1_min].g;
1092 uch b1_min = rgb[bg[pat].rgb1_min].b;
1093 uch r2_min = rgb[bg[pat].rgb2_min].r;
1094 uch g2_min = rgb[bg[pat].rgb2_min].g;
1095 uch b2_min = rgb[bg[pat].rgb2_min].b;
1096 int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
1097 int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
1098 int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
1099 int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
1100 int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
1101 int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
1102
1103 for (row = 0; row < rpng2_info.height; ++row) {
1104 yidx = (int)(row % bgscale);
1105 even_odd_vert = (int)((row / bgscale) & 1);
1106
1107 r1 = r1_min + (r1_diff * yidx) / yidx_max;
1108 g1 = g1_min + (g1_diff * yidx) / yidx_max;
1109 b1 = b1_min + (b1_diff * yidx) / yidx_max;
1110 r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
1111 g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
1112 b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
1113
1114 r2 = r2_min + (r2_diff * yidx) / yidx_max;
1115 g2 = g2_min + (g2_diff * yidx) / yidx_max;
1116 b2 = b2_min + (b2_diff * yidx) / yidx_max;
1117 r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
1118 g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
1119 b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
1120
1121 dest = (char *)bg_data + row*bg_rowbytes;
1122 for (i = 0; i < rpng2_info.width; ++i) {
1123 even_odd_horiz = (int)((i / bgscale) & 1);
1124 even_odd = even_odd_vert ^ even_odd_horiz;
1125 invert_column =
1126 (even_odd_horiz && (bg[pat].type & 0x10));
1127 if (even_odd == 0) { /* gradient #1 */
1128 if (invert_column) {
1129 *dest++ = r1_inv;
1130 *dest++ = g1_inv;
1131 *dest++ = b1_inv;
1132 } else {
1133 *dest++ = r1;
1134 *dest++ = g1;
1135 *dest++ = b1;
1136 }
1137 } else { /* gradient #2 */
1138 if ((invert_column && invert_gradient2) ||
1139 (!invert_column && !invert_gradient2))
1140 {
1141 *dest++ = r2; /* not inverted or */
1142 *dest++ = g2; /* doubly inverted */
1143 *dest++ = b2;
1144 } else {
1145 *dest++ = r2_inv;
1146 *dest++ = g2_inv; /* singly inverted */
1147 *dest++ = b2_inv;
1148 }
1149 }
1150 }
1151 }
1152
1153/*---------------------------------------------------------------------------
1154 Soft gradient-diamonds with scale = bgscale. Code contributed by Adam
1155 M. Costello.
1156 ---------------------------------------------------------------------------*/
1157
1158 } else if ((bg[pat].type & 0x07) == 1) {
1159
1160 hmax = (bgscale-1)/2; /* half the max weight of a color */
1161 max = 2*hmax; /* the max weight of a color */
1162
1163 r1 = rgb[bg[pat].rgb1_max].r;
1164 g1 = rgb[bg[pat].rgb1_max].g;
1165 b1 = rgb[bg[pat].rgb1_max].b;
1166 r2 = rgb[bg[pat].rgb2_max].r;
1167 g2 = rgb[bg[pat].rgb2_max].g;
1168 b2 = rgb[bg[pat].rgb2_max].b;
1169
1170 for (row = 0; row < rpng2_info.height; ++row) {
1171 yidx = (int)(row % bgscale);
1172 if (yidx > hmax)
1173 yidx = bgscale-1 - yidx;
1174 dest = (char *)bg_data + row*bg_rowbytes;
1175 for (i = 0; i < rpng2_info.width; ++i) {
1176 xidx = (int)(i % bgscale);
1177 if (xidx > hmax)
1178 xidx = bgscale-1 - xidx;
1179 k = xidx + yidx;
1180 *dest++ = (k*r1 + (max-k)*r2) / max;
1181 *dest++ = (k*g1 + (max-k)*g2) / max;
1182 *dest++ = (k*b1 + (max-k)*b2) / max;
1183 }
1184 }
1185
1186/*---------------------------------------------------------------------------
1187 Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
1188 soids will equal bgscale?]. This one is slow but very cool. Code con-
1189 tributed by Pieter S. van der Meulen (originally in Smalltalk).
1190 ---------------------------------------------------------------------------*/
1191
1192 } else if ((bg[pat].type & 0x07) == 2) {
1193 uch ch;
1194 int ii, x, y, hw, hh, grayspot;
1195 double freq, rotate, saturate, gray, intensity;
1196 double angle=0.0, aoffset=0.0, maxDist, dist;
1197 double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
1198
1199 fprintf(stderr, "%s: computing radial background...",
1200 PROGNAME);
1201 fflush(stderr);
1202
1203 hh = (int)(rpng2_info.height / 2);
1204 hw = (int)(rpng2_info.width / 2);
1205
1206 /* variables for radial waves:
1207 * aoffset: number of degrees to rotate hue [CURRENTLY NOT USED]
1208 * freq: number of color beams originating from the center
1209 * grayspot: size of the graying center area (anti-alias)
1210 * rotate: rotation of the beams as a function of radius
1211 * saturate: saturation of beams' shape azimuthally
1212 */
1213 angle = CLIP(angle, 0.0, 360.0);
1214 grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
1215 freq = MAX((double)bg[pat].bg_freq, 0.0);
1216 saturate = (double)bg[pat].bg_bsat * 0.1;
1217 rotate = (double)bg[pat].bg_brot * 0.1;
1218 gray = 0.0;
1219 intensity = 0.0;
1220 maxDist = (double)((hw*hw) + (hh*hh));
1221
1222 for (row = 0; row < rpng2_info.height; ++row) {
1223 y = (int)(row - hh);
1224 dest = (char *)bg_data + row*bg_rowbytes;
1225 for (i = 0; i < rpng2_info.width; ++i) {
1226 x = (int)(i - hw);
1227 angle = (x == 0)? PI_2 : atan((double)y / (double)x);
1228 gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
1229 gray = MIN(1.0, gray);
1230 dist = (double)((x*x) + (y*y)) / maxDist;
1231 intensity = cos((angle+(rotate*dist*PI)) * freq) *
1232 gray * saturate;
1233 intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
1234 hue = (angle + PI) * INV_PI_360 + aoffset;
1235 s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
1236 s = MIN(MAX(s,0.0), 1.0);
1237 v = MIN(MAX(intensity,0.0), 1.0);
1238
1239 if (s == 0.0) {
1240 ch = (uch)(v * 255.0);
1241 *dest++ = ch;
1242 *dest++ = ch;
1243 *dest++ = ch;
1244 } else {
1245 if ((hue < 0.0) || (hue >= 360.0))
1246 hue -= (((int)(hue / 360.0)) * 360.0);
1247 hue /= 60.0;
1248 ii = (int)hue;
1249 f = hue - (double)ii;
1250 p = (1.0 - s) * v;
1251 q = (1.0 - (s * f)) * v;
1252 t = (1.0 - (s * (1.0 - f))) * v;
1253 if (ii == 0) { red = v; green = t; blue = p; }
1254 else if (ii == 1) { red = q; green = v; blue = p; }
1255 else if (ii == 2) { red = p; green = v; blue = t; }
1256 else if (ii == 3) { red = p; green = q; blue = v; }
1257 else if (ii == 4) { red = t; green = p; blue = v; }
1258 else if (ii == 5) { red = v; green = p; blue = q; }
1259 *dest++ = (uch)(red * 255.0);
1260 *dest++ = (uch)(green * 255.0);
1261 *dest++ = (uch)(blue * 255.0);
1262 }
1263 }
1264 }
1265 fprintf(stderr, "done.\n");
1266 fflush(stderr);
1267 }
1268
1269/*---------------------------------------------------------------------------
1270 Blast background image to display buffer before beginning PNG decode.
1271 ---------------------------------------------------------------------------*/
1272
1273 if (depth == 24 || depth == 32) {
1274 ulg red, green, blue;
1275 int bpp = ximage->bits_per_pixel;
1276
1277 for (row = 0; row < rpng2_info.height; ++row) {
1278 src = bg_data + row*bg_rowbytes;
1279 dest = ximage->data + row*ximage_rowbytes;
1280 if (bpp == 32) { /* slightly optimized version */
1281 for (i = rpng2_info.width; i > 0; --i) {
1282 red = *src++;
1283 green = *src++;
1284 blue = *src++;
1285 pixel = (red << RShift) |
1286 (green << GShift) |
1287 (blue << BShift);
1288 /* recall that we set ximage->byte_order = MSBFirst above */
1289 *dest++ = (char)((pixel >> 24) & 0xff);
1290 *dest++ = (char)((pixel >> 16) & 0xff);
1291 *dest++ = (char)((pixel >> 8) & 0xff);
1292 *dest++ = (char)( pixel & 0xff);
1293 }
1294 } else {
1295 for (i = rpng2_info.width; i > 0; --i) {
1296 red = *src++;
1297 green = *src++;
1298 blue = *src++;
1299 pixel = (red << RShift) |
1300 (green << GShift) |
1301 (blue << BShift);
1302 /* recall that we set ximage->byte_order = MSBFirst above */
1303 /* GRR BUG? this assumes bpp == 24 & bits are packed low */
1304 /* (probably need to use RShift, RMask, etc.) */
1305 *dest++ = (char)((pixel >> 16) & 0xff);
1306 *dest++ = (char)((pixel >> 8) & 0xff);
1307 *dest++ = (char)( pixel & 0xff);
1308 }
1309 }
1310 }
1311
1312 } else if (depth == 16) {
1313 ush red, green, blue;
1314
1315 for (row = 0; row < rpng2_info.height; ++row) {
1316 src = bg_data + row*bg_rowbytes;
1317 dest = ximage->data + row*ximage_rowbytes;
1318 for (i = rpng2_info.width; i > 0; --i) {
1319 red = ((ush)(*src) << 8); ++src;
1320 green = ((ush)(*src) << 8); ++src;
1321 blue = ((ush)(*src) << 8); ++src;
1322 pixel = ((red >> RShift) & RMask) |
1323 ((green >> GShift) & GMask) |
1324 ((blue >> BShift) & BMask);
1325 /* recall that we set ximage->byte_order = MSBFirst above */
1326 *dest++ = (char)((pixel >> 8) & 0xff);
1327 *dest++ = (char)( pixel & 0xff);
1328 }
1329 }
1330
1331 } else /* depth == 8 */ {
1332
1333 /* GRR: add 8-bit support */
1334
1335 }
1336
1337 XPutImage(display, window, gc, ximage, 0, 0, 0, 0, rpng2_info.width,
1338 rpng2_info.height);
1339
1340 return 0;
1341
1342} /* end function rpng2_x_load_bg_image() */
1343
1344
1345
1346
1347
1348static void rpng2_x_display_row(ulg row)
1349{
1350 uch bg_red = rpng2_info.bg_red;
1351 uch bg_green = rpng2_info.bg_green;
1352 uch bg_blue = rpng2_info.bg_blue;
1353 uch *src, *src2=NULL;
1354 char *dest;
1355 uch r, g, b, a;
1356 int ximage_rowbytes = ximage->bytes_per_line;
1357 ulg i, pixel;
1358 static int rows=0, prevpass=(-1);
1359 static ulg firstrow;
1360
1361/*---------------------------------------------------------------------------
1362 rows and firstrow simply track how many rows (and which ones) have not
1363 yet been displayed; alternatively, we could call XPutImage() for every
1364 row and not bother with the records-keeping.
1365 ---------------------------------------------------------------------------*/
1366
1367 Trace((stderr, "beginning rpng2_x_display_row()\n"))
1368
1369 if (rpng2_info.pass != prevpass) {
1370 if (pause_after_pass && rpng2_info.pass > 0) {
1371 XEvent e;
1372 KeySym k;
1373
1374 fprintf(stderr,
1375 "%s: end of pass %d of 7; click in image window to continue\n",
1376 PROGNAME, prevpass + 1);
1377 do
1378 XNextEvent(display, &e);
1379 while (!QUIT(e,k));
1380 }
1381 fprintf(stderr, "%s: pass %d of 7\r", PROGNAME, rpng2_info.pass + 1);
1382 fflush(stderr);
1383 prevpass = rpng2_info.pass;
1384 }
1385
1386 if (rows == 0)
1387 firstrow = row; /* first row that is not yet displayed */
1388
1389 ++rows; /* count of rows received but not yet displayed */
1390
1391/*---------------------------------------------------------------------------
1392 Aside from the use of the rpng2_info struct, the lack of an outer loop
1393 (over rows) and moving the XPutImage() call outside the "if (depth)"
1394 tests, this routine is identical to rpng_x_display_image() in the non-
1395 progressive version of the program.
1396 ---------------------------------------------------------------------------*/
1397
1398 if (depth == 24 || depth == 32) {
1399 ulg red, green, blue;
1400 int bpp = ximage->bits_per_pixel;
1401
1402 src = rpng2_info.image_data + row*rpng2_info.rowbytes;
1403 if (bg_image)
1404 src2 = bg_data + row*bg_rowbytes;
1405 dest = ximage->data + row*ximage_rowbytes;
1406 if (rpng2_info.channels == 3) {
1407 for (i = rpng2_info.width; i > 0; --i) {
1408 red = *src++;
1409 green = *src++;
1410 blue = *src++;
1411 pixel = (red << RShift) |
1412 (green << GShift) |
1413 (blue << BShift);
1414 /* recall that we set ximage->byte_order = MSBFirst above */
1415 if (bpp == 32) {
1416 *dest++ = (char)((pixel >> 24) & 0xff);
1417 *dest++ = (char)((pixel >> 16) & 0xff);
1418 *dest++ = (char)((pixel >> 8) & 0xff);
1419 *dest++ = (char)( pixel & 0xff);
1420 } else {
1421 /* GRR BUG? this assumes bpp == 24 & bits are packed low */
1422 /* (probably need to use RShift, RMask, etc.) */
1423 *dest++ = (char)((pixel >> 16) & 0xff);
1424 *dest++ = (char)((pixel >> 8) & 0xff);
1425 *dest++ = (char)( pixel & 0xff);
1426 }
1427 }
1428 } else /* if (rpng2_info.channels == 4) */ {
1429 for (i = rpng2_info.width; i > 0; --i) {
1430 r = *src++;
1431 g = *src++;
1432 b = *src++;
1433 a = *src++;
1434 if (bg_image) {
1435 bg_red = *src2++;
1436 bg_green = *src2++;
1437 bg_blue = *src2++;
1438 }
1439 if (a == 255) {
1440 red = r;
1441 green = g;
1442 blue = b;
1443 } else if (a == 0) {
1444 red = bg_red;
1445 green = bg_green;
1446 blue = bg_blue;
1447 } else {
1448 /* this macro (from png.h) composites the foreground
1449 * and background values and puts the result into the
1450 * first argument */
1451 alpha_composite(red, r, a, bg_red);
1452 alpha_composite(green, g, a, bg_green);
1453 alpha_composite(blue, b, a, bg_blue);
1454 }
1455 pixel = (red << RShift) |
1456 (green << GShift) |
1457 (blue << BShift);
1458 /* recall that we set ximage->byte_order = MSBFirst above */
1459 if (bpp == 32) {
1460 *dest++ = (char)((pixel >> 24) & 0xff);
1461 *dest++ = (char)((pixel >> 16) & 0xff);
1462 *dest++ = (char)((pixel >> 8) & 0xff);
1463 *dest++ = (char)( pixel & 0xff);
1464 } else {
1465 /* GRR BUG? this assumes bpp == 24 & bits are packed low */
1466 /* (probably need to use RShift, RMask, etc.) */
1467 *dest++ = (char)((pixel >> 16) & 0xff);
1468 *dest++ = (char)((pixel >> 8) & 0xff);
1469 *dest++ = (char)( pixel & 0xff);
1470 }
1471 }
1472 }
1473
1474 } else if (depth == 16) {
1475 ush red, green, blue;
1476
1477 src = rpng2_info.row_pointers[row];
1478 if (bg_image)
1479 src2 = bg_data + row*bg_rowbytes;
1480 dest = ximage->data + row*ximage_rowbytes;
1481 if (rpng2_info.channels == 3) {
1482 for (i = rpng2_info.width; i > 0; --i) {
1483 red = ((ush)(*src) << 8);
1484 ++src;
1485 green = ((ush)(*src) << 8);
1486 ++src;
1487 blue = ((ush)(*src) << 8);
1488 ++src;
1489 pixel = ((red >> RShift) & RMask) |
1490 ((green >> GShift) & GMask) |
1491 ((blue >> BShift) & BMask);
1492 /* recall that we set ximage->byte_order = MSBFirst above */
1493 *dest++ = (char)((pixel >> 8) & 0xff);
1494 *dest++ = (char)( pixel & 0xff);
1495 }
1496 } else /* if (rpng2_info.channels == 4) */ {
1497 for (i = rpng2_info.width; i > 0; --i) {
1498 r = *src++;
1499 g = *src++;
1500 b = *src++;
1501 a = *src++;
1502 if (bg_image) {
1503 bg_red = *src2++;
1504 bg_green = *src2++;
1505 bg_blue = *src2++;
1506 }
1507 if (a == 255) {
1508 red = ((ush)r << 8);
1509 green = ((ush)g << 8);
1510 blue = ((ush)b << 8);
1511 } else if (a == 0) {
1512 red = ((ush)bg_red << 8);
1513 green = ((ush)bg_green << 8);
1514 blue = ((ush)bg_blue << 8);
1515 } else {
1516 /* this macro (from png.h) composites the foreground
1517 * and background values and puts the result back into
1518 * the first argument (== fg byte here: safe) */
1519 alpha_composite(r, r, a, bg_red);
1520 alpha_composite(g, g, a, bg_green);
1521 alpha_composite(b, b, a, bg_blue);
1522 red = ((ush)r << 8);
1523 green = ((ush)g << 8);
1524 blue = ((ush)b << 8);
1525 }
1526 pixel = ((red >> RShift) & RMask) |
1527 ((green >> GShift) & GMask) |
1528 ((blue >> BShift) & BMask);
1529 /* recall that we set ximage->byte_order = MSBFirst above */
1530 *dest++ = (char)((pixel >> 8) & 0xff);
1531 *dest++ = (char)( pixel & 0xff);
1532 }
1533 }
1534
1535 } else /* depth == 8 */ {
1536
1537 /* GRR: add 8-bit support */
1538
1539 }
1540
1541
1542/*---------------------------------------------------------------------------
1543 Display after every 16 rows or when on one of last two rows. (Region
1544 may include previously displayed lines due to interlacing--i.e., not
1545 contiguous. Also, second-to-last row is final one in interlaced images
1546 with odd number of rows.) For demos, flush (and delay) after every 16th
1547 row so "sparse" passes don't go twice as fast.
1548 ---------------------------------------------------------------------------*/
1549
1550 if (demo_timing && (row - firstrow >= 16 || row >= rpng2_info.height-2)) {
1551 XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0,
1552 (int)firstrow, rpng2_info.width, row - firstrow + 1);
1553 XFlush(display);
1554 rows = 0;
1555 usleep(usleep_duration);
1556 } else
1557 if (!demo_timing && ((rows & 0xf) == 0 || row >= rpng2_info.height-2)) {
1558 XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0,
1559 (int)firstrow, rpng2_info.width, row - firstrow + 1);
1560 XFlush(display);
1561 rows = 0;
1562 }
1563
1564}
1565
1566
1567
1568
1569
1570static void rpng2_x_finish_display(void)
1571{
1572 Trace((stderr, "beginning rpng2_x_finish_display()\n"))
1573
1574 /* last row has already been displayed by rpng2_x_display_row(), so we
1575 * have nothing to do here except set a flag and let the user know that
1576 * the image is done */
1577
1578 rpng2_info.state = kDone;
1579 printf(
1580 "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
1581 fflush(stdout);
1582}
1583
1584
1585
1586
1587
1588static void rpng2_x_redisplay_image(ulg startcol, ulg startrow,
1589 ulg width, ulg height)
1590{
1591 uch bg_red = rpng2_info.bg_red;
1592 uch bg_green = rpng2_info.bg_green;
1593 uch bg_blue = rpng2_info.bg_blue;
1594 uch *src, *src2=NULL;
1595 char *dest;
1596 uch r, g, b, a;
1597 ulg i, row, lastrow = 0;
1598 ulg pixel;
1599 int ximage_rowbytes = ximage->bytes_per_line;
1600
1601
1602 Trace((stderr, "beginning display loop (image_channels == %d)\n",
1603 rpng2_info.channels))
1604 Trace((stderr, " (width = %ld, rowbytes = %d, ximage_rowbytes = %d)\n",
1605 rpng2_info.width, rpng2_info.rowbytes, ximage_rowbytes))
1606 Trace((stderr, " (bpp = %d)\n", ximage->bits_per_pixel))
1607 Trace((stderr, " (byte_order = %s)\n", ximage->byte_order == MSBFirst?
1608 "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown")))
1609
1610/*---------------------------------------------------------------------------
1611 Aside from the use of the rpng2_info struct and of src2 (for background
1612 image), this routine is identical to rpng_x_display_image() in the non-
1613 progressive version of the program--for the simple reason that redisplay
1614 of the image against a new background happens after the image is fully
1615 decoded and therefore is, by definition, non-progressive.
1616 ---------------------------------------------------------------------------*/
1617
1618 if (depth == 24 || depth == 32) {
1619 ulg red, green, blue;
1620 int bpp = ximage->bits_per_pixel;
1621
1622 for (lastrow = row = startrow; row < startrow+height; ++row) {
1623 src = rpng2_info.image_data + row*rpng2_info.rowbytes;
1624 if (bg_image)
1625 src2 = bg_data + row*bg_rowbytes;
1626 dest = ximage->data + row*ximage_rowbytes;
1627 if (rpng2_info.channels == 3) {
1628 for (i = rpng2_info.width; i > 0; --i) {
1629 red = *src++;
1630 green = *src++;
1631 blue = *src++;
1632#ifdef NO_24BIT_MASKS
1633 pixel = (red << RShift) |
1634 (green << GShift) |
1635 (blue << BShift);
1636 /* recall that we set ximage->byte_order = MSBFirst above */
1637 if (bpp == 32) {
1638 *dest++ = (char)((pixel >> 24) & 0xff);
1639 *dest++ = (char)((pixel >> 16) & 0xff);
1640 *dest++ = (char)((pixel >> 8) & 0xff);
1641 *dest++ = (char)( pixel & 0xff);
1642 } else {
1643 /* this assumes bpp == 24 & bits are packed low */
1644 /* (probably need to use RShift, RMask, etc.) */
1645 *dest++ = (char)((pixel >> 16) & 0xff);
1646 *dest++ = (char)((pixel >> 8) & 0xff);
1647 *dest++ = (char)( pixel & 0xff);
1648 }
1649#else
1650 red = (RShift < 0)? red << (-RShift) : red >> RShift;
1651 green = (GShift < 0)? green << (-GShift) : green >> GShift;
1652 blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
1653 pixel = (red & RMask) | (green & GMask) | (blue & BMask);
1654 /* recall that we set ximage->byte_order = MSBFirst above */
1655 if (bpp == 32) {
1656 *dest++ = (char)((pixel >> 24) & 0xff);
1657 *dest++ = (char)((pixel >> 16) & 0xff);
1658 *dest++ = (char)((pixel >> 8) & 0xff);
1659 *dest++ = (char)( pixel & 0xff);
1660 } else {
1661 /* GRR BUG */
1662 /* this assumes bpp == 24 & bits are packed low */
1663 /* (probably need to use RShift/RMask/etc. here, too) */
1664 *dest++ = (char)((pixel >> 16) & 0xff);
1665 *dest++ = (char)((pixel >> 8) & 0xff);
1666 *dest++ = (char)( pixel & 0xff);
1667 }
1668#endif
1669 }
1670
1671 } else /* if (rpng2_info.channels == 4) */ {
1672 for (i = rpng2_info.width; i > 0; --i) {
1673 r = *src++;
1674 g = *src++;
1675 b = *src++;
1676 a = *src++;
1677 if (bg_image) {
1678 bg_red = *src2++;
1679 bg_green = *src2++;
1680 bg_blue = *src2++;
1681 }
1682 if (a == 255) {
1683 red = r;
1684 green = g;
1685 blue = b;
1686 } else if (a == 0) {
1687 red = bg_red;
1688 green = bg_green;
1689 blue = bg_blue;
1690 } else {
1691 /* this macro (from png.h) composites the foreground
1692 * and background values and puts the result into the
1693 * first argument */
1694 alpha_composite(red, r, a, bg_red);
1695 alpha_composite(green, g, a, bg_green);
1696 alpha_composite(blue, b, a, bg_blue);
1697 }
1698#ifdef NO_24BIT_MASKS
1699 pixel = (red << RShift) |
1700 (green << GShift) |
1701 (blue << BShift);
1702 /* recall that we set ximage->byte_order = MSBFirst above */
1703 if (bpp == 32) {
1704 *dest++ = (char)((pixel >> 24) & 0xff);
1705 *dest++ = (char)((pixel >> 16) & 0xff);
1706 *dest++ = (char)((pixel >> 8) & 0xff);
1707 *dest++ = (char)( pixel & 0xff);
1708 } else {
1709 /* this assumes bpp == 24 & bits are packed low */
1710 /* (probably need to use RShift, RMask, etc.) */
1711 *dest++ = (char)((pixel >> 16) & 0xff);
1712 *dest++ = (char)((pixel >> 8) & 0xff);
1713 *dest++ = (char)( pixel & 0xff);
1714 }
1715#else
1716 red = (RShift < 0)? red << (-RShift) : red >> RShift;
1717 green = (GShift < 0)? green << (-GShift) : green >> GShift;
1718 blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
1719 pixel = (red & RMask) | (green & GMask) | (blue & BMask);
1720 /* recall that we set ximage->byte_order = MSBFirst above */
1721 if (bpp == 32) {
1722 *dest++ = (char)((pixel >> 24) & 0xff);
1723 *dest++ = (char)((pixel >> 16) & 0xff);
1724 *dest++ = (char)((pixel >> 8) & 0xff);
1725 *dest++ = (char)( pixel & 0xff);
1726 } else {
1727 /* GRR BUG */
1728 /* this assumes bpp == 24 & bits are packed low */
1729 /* (probably need to use RShift/RMask/etc. here, too) */
1730 *dest++ = (char)((pixel >> 16) & 0xff);
1731 *dest++ = (char)((pixel >> 8) & 0xff);
1732 *dest++ = (char)( pixel & 0xff);
1733 }
1734#endif
1735 }
1736 }
1737 /* display after every 16 lines */
1738 if (((row+1) & 0xf) == 0) {
1739 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
1740 (int)lastrow, rpng2_info.width, 16);
1741 XFlush(display);
1742 lastrow = row + 1;
1743 }
1744 }
1745
1746 } else if (depth == 16) {
1747 ush red, green, blue;
1748
1749 for (lastrow = row = startrow; row < startrow+height; ++row) {
1750 src = rpng2_info.row_pointers[row];
1751 if (bg_image)
1752 src2 = bg_data + row*bg_rowbytes;
1753 dest = ximage->data + row*ximage_rowbytes;
1754 if (rpng2_info.channels == 3) {
1755 for (i = rpng2_info.width; i > 0; --i) {
1756 red = ((ush)(*src) << 8);
1757 ++src;
1758 green = ((ush)(*src) << 8);
1759 ++src;
1760 blue = ((ush)(*src) << 8);
1761 ++src;
1762 pixel = ((red >> RShift) & RMask) |
1763 ((green >> GShift) & GMask) |
1764 ((blue >> BShift) & BMask);
1765 /* recall that we set ximage->byte_order = MSBFirst above */
1766 *dest++ = (char)((pixel >> 8) & 0xff);
1767 *dest++ = (char)( pixel & 0xff);
1768 }
1769 } else /* if (rpng2_info.channels == 4) */ {
1770 for (i = rpng2_info.width; i > 0; --i) {
1771 r = *src++;
1772 g = *src++;
1773 b = *src++;
1774 a = *src++;
1775 if (bg_image) {
1776 bg_red = *src2++;
1777 bg_green = *src2++;
1778 bg_blue = *src2++;
1779 }
1780 if (a == 255) {
1781 red = ((ush)r << 8);
1782 green = ((ush)g << 8);
1783 blue = ((ush)b << 8);
1784 } else if (a == 0) {
1785 red = ((ush)bg_red << 8);
1786 green = ((ush)bg_green << 8);
1787 blue = ((ush)bg_blue << 8);
1788 } else {
1789 /* this macro (from png.h) composites the foreground
1790 * and background values and puts the result back into
1791 * the first argument (== fg byte here: safe) */
1792 alpha_composite(r, r, a, bg_red);
1793 alpha_composite(g, g, a, bg_green);
1794 alpha_composite(b, b, a, bg_blue);
1795 red = ((ush)r << 8);
1796 green = ((ush)g << 8);
1797 blue = ((ush)b << 8);
1798 }
1799 pixel = ((red >> RShift) & RMask) |
1800 ((green >> GShift) & GMask) |
1801 ((blue >> BShift) & BMask);
1802 /* recall that we set ximage->byte_order = MSBFirst above */
1803 *dest++ = (char)((pixel >> 8) & 0xff);
1804 *dest++ = (char)( pixel & 0xff);
1805 }
1806 }
1807 /* display after every 16 lines */
1808 if (((row+1) & 0xf) == 0) {
1809 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
1810 (int)lastrow, rpng2_info.width, 16);
1811 XFlush(display);
1812 lastrow = row + 1;
1813 }
1814 }
1815
1816 } else /* depth == 8 */ {
1817
1818 /* GRR: add 8-bit support */
1819
1820 }
1821
1822 Trace((stderr, "calling final XPutImage()\n"))
1823 if (lastrow < startrow+height) {
1824 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
1825 (int)lastrow, rpng2_info.width, rpng2_info.height-lastrow);
1826 XFlush(display);
1827 }
1828
1829} /* end function rpng2_x_redisplay_image() */
1830
1831
1832
1833
1834
1835#ifdef FEATURE_LOOP
1836
1837static void rpng2_x_reload_bg_image(void)
1838{
1839 char *dest;
1840 uch r1, r2, g1, g2, b1, b2;
1841 uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
1842 int k, hmax, max;
1843 int xidx, yidx, yidx_max;
1844 int even_odd_vert, even_odd_horiz, even_odd;
1845 int invert_gradient2 = (bg[pat].type & 0x08);
1846 int invert_column;
1847 ulg i, row;
1848
1849
1850 bgscale = (pat == 0)? 8 : bgscale_default;
1851 yidx_max = bgscale - 1;
1852
1853/*---------------------------------------------------------------------------
1854 Vertical gradients (ramps) in NxN squares, alternating direction and
1855 colors (N == bgscale).
1856 ---------------------------------------------------------------------------*/
1857
1858 if ((bg[pat].type & 0x07) == 0) {
1859 uch r1_min = rgb[bg[pat].rgb1_min].r;
1860 uch g1_min = rgb[bg[pat].rgb1_min].g;
1861 uch b1_min = rgb[bg[pat].rgb1_min].b;
1862 uch r2_min = rgb[bg[pat].rgb2_min].r;
1863 uch g2_min = rgb[bg[pat].rgb2_min].g;
1864 uch b2_min = rgb[bg[pat].rgb2_min].b;
1865 int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
1866 int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
1867 int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
1868 int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
1869 int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
1870 int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
1871
1872 for (row = 0; row < rpng2_info.height; ++row) {
1873 yidx = (int)(row % bgscale);
1874 even_odd_vert = (int)((row / bgscale) & 1);
1875
1876 r1 = r1_min + (r1_diff * yidx) / yidx_max;
1877 g1 = g1_min + (g1_diff * yidx) / yidx_max;
1878 b1 = b1_min + (b1_diff * yidx) / yidx_max;
1879 r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
1880 g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
1881 b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
1882
1883 r2 = r2_min + (r2_diff * yidx) / yidx_max;
1884 g2 = g2_min + (g2_diff * yidx) / yidx_max;
1885 b2 = b2_min + (b2_diff * yidx) / yidx_max;
1886 r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
1887 g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
1888 b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
1889
1890 dest = (char *)bg_data + row*bg_rowbytes;
1891 for (i = 0; i < rpng2_info.width; ++i) {
1892 even_odd_horiz = (int)((i / bgscale) & 1);
1893 even_odd = even_odd_vert ^ even_odd_horiz;
1894 invert_column =
1895 (even_odd_horiz && (bg[pat].type & 0x10));
1896 if (even_odd == 0) { /* gradient #1 */
1897 if (invert_column) {
1898 *dest++ = r1_inv;
1899 *dest++ = g1_inv;
1900 *dest++ = b1_inv;
1901 } else {
1902 *dest++ = r1;
1903 *dest++ = g1;
1904 *dest++ = b1;
1905 }
1906 } else { /* gradient #2 */
1907 if ((invert_column && invert_gradient2) ||
1908 (!invert_column && !invert_gradient2))
1909 {
1910 *dest++ = r2; /* not inverted or */
1911 *dest++ = g2; /* doubly inverted */
1912 *dest++ = b2;
1913 } else {
1914 *dest++ = r2_inv;
1915 *dest++ = g2_inv; /* singly inverted */
1916 *dest++ = b2_inv;
1917 }
1918 }
1919 }
1920 }
1921
1922/*---------------------------------------------------------------------------
1923 Soft gradient-diamonds with scale = bgscale. Code contributed by Adam
1924 M. Costello.
1925 ---------------------------------------------------------------------------*/
1926
1927 } else if ((bg[pat].type & 0x07) == 1) {
1928
1929 hmax = (bgscale-1)/2; /* half the max weight of a color */
1930 max = 2*hmax; /* the max weight of a color */
1931
1932 r1 = rgb[bg[pat].rgb1_max].r;
1933 g1 = rgb[bg[pat].rgb1_max].g;
1934 b1 = rgb[bg[pat].rgb1_max].b;
1935 r2 = rgb[bg[pat].rgb2_max].r;
1936 g2 = rgb[bg[pat].rgb2_max].g;
1937 b2 = rgb[bg[pat].rgb2_max].b;
1938
1939 for (row = 0; row < rpng2_info.height; ++row) {
1940 yidx = (int)(row % bgscale);
1941 if (yidx > hmax)
1942 yidx = bgscale-1 - yidx;
1943 dest = (char *)bg_data + row*bg_rowbytes;
1944 for (i = 0; i < rpng2_info.width; ++i) {
1945 xidx = (int)(i % bgscale);
1946 if (xidx > hmax)
1947 xidx = bgscale-1 - xidx;
1948 k = xidx + yidx;
1949 *dest++ = (k*r1 + (max-k)*r2) / max;
1950 *dest++ = (k*g1 + (max-k)*g2) / max;
1951 *dest++ = (k*b1 + (max-k)*b2) / max;
1952 }
1953 }
1954
1955/*---------------------------------------------------------------------------
1956 Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
1957 soids will equal bgscale?]. This one is slow but very cool. Code con-
1958 tributed by Pieter S. van der Meulen (originally in Smalltalk).
1959 ---------------------------------------------------------------------------*/
1960
1961 } else if ((bg[pat].type & 0x07) == 2) {
1962 uch ch;
1963 int ii, x, y, hw, hh, grayspot;
1964 double freq, rotate, saturate, gray, intensity;
1965 double angle=0.0, aoffset=0.0, maxDist, dist;
1966 double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
1967
1968 hh = (int)(rpng2_info.height / 2);
1969 hw = (int)(rpng2_info.width / 2);
1970
1971 /* variables for radial waves:
1972 * aoffset: number of degrees to rotate hue [CURRENTLY NOT USED]
1973 * freq: number of color beams originating from the center
1974 * grayspot: size of the graying center area (anti-alias)
1975 * rotate: rotation of the beams as a function of radius
1976 * saturate: saturation of beams' shape azimuthally
1977 */
1978 angle = CLIP(angle, 0.0, 360.0);
1979 grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
1980 freq = MAX((double)bg[pat].bg_freq, 0.0);
1981 saturate = (double)bg[pat].bg_bsat * 0.1;
1982 rotate = (double)bg[pat].bg_brot * 0.1;
1983 gray = 0.0;
1984 intensity = 0.0;
1985 maxDist = (double)((hw*hw) + (hh*hh));
1986
1987 for (row = 0; row < rpng2_info.height; ++row) {
1988 y = (int)(row - hh);
1989 dest = (char *)bg_data + row*bg_rowbytes;
1990 for (i = 0; i < rpng2_info.width; ++i) {
1991 x = (int)(i - hw);
1992 angle = (x == 0)? PI_2 : atan((double)y / (double)x);
1993 gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
1994 gray = MIN(1.0, gray);
1995 dist = (double)((x*x) + (y*y)) / maxDist;
1996 intensity = cos((angle+(rotate*dist*PI)) * freq) *
1997 gray * saturate;
1998 intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
1999 hue = (angle + PI) * INV_PI_360 + aoffset;
2000 s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
2001 s = MIN(MAX(s,0.0), 1.0);
2002 v = MIN(MAX(intensity,0.0), 1.0);
2003
2004 if (s == 0.0) {
2005 ch = (uch)(v * 255.0);
2006 *dest++ = ch;
2007 *dest++ = ch;
2008 *dest++ = ch;
2009 } else {
2010 if ((hue < 0.0) || (hue >= 360.0))
2011 hue -= (((int)(hue / 360.0)) * 360.0);
2012 hue /= 60.0;
2013 ii = (int)hue;
2014 f = hue - (double)ii;
2015 p = (1.0 - s) * v;
2016 q = (1.0 - (s * f)) * v;
2017 t = (1.0 - (s * (1.0 - f))) * v;
2018 if (ii == 0) { red = v; green = t; blue = p; }
2019 else if (ii == 1) { red = q; green = v; blue = p; }
2020 else if (ii == 2) { red = p; green = v; blue = t; }
2021 else if (ii == 3) { red = p; green = q; blue = v; }
2022 else if (ii == 4) { red = t; green = p; blue = v; }
2023 else if (ii == 5) { red = v; green = p; blue = q; }
2024 *dest++ = (uch)(red * 255.0);
2025 *dest++ = (uch)(green * 255.0);
2026 *dest++ = (uch)(blue * 255.0);
2027 }
2028 }
2029 }
2030 }
2031
2032} /* end function rpng2_x_reload_bg_image() */
2033
2034
2035
2036
2037
2038static int is_number(char *p)
2039{
2040 while (*p) {
2041 if (!isdigit(*p))
2042 return FALSE;
2043 ++p;
2044 }
2045 return TRUE;
2046}
2047
2048#endif /* FEATURE_LOOP */
2049
2050
2051
2052
2053
2054static void rpng2_x_cleanup(void)
2055{
2056 if (bg_image && bg_data) {
2057 free(bg_data);
2058 bg_data = NULL;
2059 }
2060
2061 if (rpng2_info.image_data) {
2062 free(rpng2_info.image_data);
2063 rpng2_info.image_data = NULL;
2064 }
2065
2066 if (rpng2_info.row_pointers) {
2067 free(rpng2_info.row_pointers);
2068 rpng2_info.row_pointers = NULL;
2069 }
2070
2071 if (ximage) {
2072 if (ximage->data) {
2073 free(ximage->data); /* we allocated it, so we free it */
2074 ximage->data = (char *)NULL; /* instead of XDestroyImage() */
2075 }
2076 XDestroyImage(ximage);
2077 ximage = NULL;
2078 }
2079
2080 if (have_gc)
2081 XFreeGC(display, gc);
2082
2083 if (have_window)
2084 XDestroyWindow(display, window);
2085
2086 if (have_colormap)
2087 XFreeColormap(display, colormap);
2088
2089 if (have_nondefault_visual)
2090 XFree(visual_list);
2091}
2092
2093
2094
2095
2096
2097static int rpng2_x_msb(ulg u32val)
2098{
2099 int i;
2100
2101 for (i = 31; i >= 0; --i) {
2102 if (u32val & 0x80000000L)
2103 break;
2104 u32val <<= 1;
2105 }
2106 return i;
2107}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/toucan.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/toucan.png
new file mode 100644
index 0000000..03960d4
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/toucan.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/wpng.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/wpng.c
new file mode 100644
index 0000000..30372a3
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/wpng.c
@@ -0,0 +1,853 @@
1/*---------------------------------------------------------------------------
2
3 wpng - simple PNG-writing program wpng.c
4
5 This program converts certain NetPBM binary files (grayscale and RGB,
6 maxval = 255) to PNG. Non-interlaced PNGs are written progressively;
7 interlaced PNGs are read and written in one memory-intensive blast.
8
9 Thanks to Jean-loup Gailly for providing the necessary trick to read
10 interactive text from the keyboard while stdin is redirected. Thanks
11 to Cosmin Truta for Cygwin fixes.
12
13 NOTE: includes provisional support for PNM type "8" (portable alphamap)
14 images, presumed to be a 32-bit interleaved RGBA format; no pro-
15 vision for possible interleaved grayscale+alpha (16-bit) format.
16 THIS IS UNLIKELY TO BECOME AN OFFICIAL NETPBM ALPHA FORMAT!
17
18 to do:
19 - delete output file if quit before calling any writepng routines
20 - process backspace with -text option under DOS/Win? (currently get ^H)
21
22 ---------------------------------------------------------------------------
23
24 Changelog:
25 - 1.01: initial public release
26 - 1.02: modified to allow abbreviated options
27 - 1.03: removed extraneous character from usage screen; fixed bug in
28 command-line parsing
29 - 1.04: fixed DOS/OS2/Win32 detection, including partial Cygwin fix
30 (see http://home.att.net/~perlspinr/diffs/GregBook_cygwin.diff)
31 - 2.00: dual-licensed (added GNU GPL)
32
33 [REPORTED BUG (win32 only): "contrib/gregbook/wpng.c - cmd line
34 dose not work! In order to do something useful I needed to redirect
35 both input and output, with cygwin and with bcc32 as well. Under
36 Linux, the same wpng appears to work fine. I don't know what is
37 the problem."]
38
39 ---------------------------------------------------------------------------
40
41 Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
42
43 This software is provided "as is," without warranty of any kind,
44 express or implied. In no event shall the author or contributors
45 be held liable for any damages arising in any way from the use of
46 this software.
47
48 The contents of this file are DUAL-LICENSED. You may modify and/or
49 redistribute this software according to the terms of one of the
50 following two licenses (at your option):
51
52
53 LICENSE 1 ("BSD-like with advertising clause"):
54
55 Permission is granted to anyone to use this software for any purpose,
56 including commercial applications, and to alter it and redistribute
57 it freely, subject to the following restrictions:
58
59 1. Redistributions of source code must retain the above copyright
60 notice, disclaimer, and this list of conditions.
61 2. Redistributions in binary form must reproduce the above copyright
62 notice, disclaimer, and this list of conditions in the documenta-
63 tion and/or other materials provided with the distribution.
64 3. All advertising materials mentioning features or use of this
65 software must display the following acknowledgment:
66
67 This product includes software developed by Greg Roelofs
68 and contributors for the book, "PNG: The Definitive Guide,"
69 published by O'Reilly and Associates.
70
71
72 LICENSE 2 (GNU GPL v2 or later):
73
74 This program is free software; you can redistribute it and/or modify
75 it under the terms of the GNU General Public License as published by
76 the Free Software Foundation; either version 2 of the License, or
77 (at your option) any later version.
78
79 This program is distributed in the hope that it will be useful,
80 but WITHOUT ANY WARRANTY; without even the implied warranty of
81 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82 GNU General Public License for more details.
83
84 You should have received a copy of the GNU General Public License
85 along with this program; if not, write to the Free Software Foundation,
86 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
87
88 ---------------------------------------------------------------------------*/
89
90#define PROGNAME "wpng"
91#define VERSION "2.00 of 2 June 2007"
92#define APPNAME "Simple PGM/PPM/PAM to PNG Converter"
93
94#if defined(__MSDOS__) || defined(__OS2__)
95# define DOS_OS2_W32
96#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
97# ifndef __GNUC__ /* treat Win32 native ports of gcc as Unix environments */
98# define DOS_OS2_W32
99# endif
100#endif
101
102#include <stdio.h>
103#include <stdlib.h>
104#include <string.h>
105#include <setjmp.h> /* for jmpbuf declaration in writepng.h */
106#include <time.h>
107
108#ifdef DOS_OS2_W32
109# include <io.h> /* for isatty(), setmode() prototypes */
110# include <fcntl.h> /* O_BINARY for fdopen() without text translation */
111# ifdef __EMX__
112# ifndef getch
113# define getch() _read_kbd(0, 1, 0) /* need getche() */
114# endif
115# else /* !__EMX__ */
116# ifdef __GO32__
117# include <pc.h>
118# define getch() getkey() /* GRR: need getche() */
119# else
120# include <conio.h> /* for getche() console input */
121# endif
122# endif /* ?__EMX__ */
123# define FGETS(buf,len,stream) dos_kbd_gets(buf,len)
124#else
125# include <unistd.h> /* for isatty() prototype */
126# define FGETS fgets
127#endif
128
129/* #define DEBUG : this enables the Trace() macros */
130
131/* #define FORBID_LATIN1_CTRL : this requires the user to re-enter any
132 text that includes control characters discouraged by the PNG spec; text
133 that includes an escape character (27) must be re-entered regardless */
134
135#include "writepng.h" /* typedefs, common macros, writepng prototypes */
136
137
138
139/* local prototypes */
140
141static int wpng_isvalid_latin1(uch *p, int len);
142static void wpng_cleanup(void);
143
144#ifdef DOS_OS2_W32
145 static char *dos_kbd_gets(char *buf, int len);
146#endif
147
148
149
150static mainprog_info wpng_info; /* lone global */
151
152
153
154int main(int argc, char **argv)
155{
156#ifndef DOS_OS2_W32
157 FILE *keybd;
158#endif
159#ifdef sgi
160 FILE *tmpfile; /* or we could just use keybd, since no overlap */
161 char tmpline[80];
162#endif
163 char *inname = NULL, outname[256];
164 char *p, pnmchar, pnmline[256];
165 char *bgstr, *textbuf = NULL;
166 ulg rowbytes;
167 int rc, len = 0;
168 int error = 0;
169 int text = FALSE;
170 int maxval;
171 double LUT_exponent; /* just the lookup table */
172 double CRT_exponent = 2.2; /* just the monitor */
173 double default_display_exponent; /* whole display system */
174 double default_gamma = 0.0;
175
176
177 wpng_info.infile = NULL;
178 wpng_info.outfile = NULL;
179 wpng_info.image_data = NULL;
180 wpng_info.row_pointers = NULL;
181 wpng_info.filter = FALSE;
182 wpng_info.interlaced = FALSE;
183 wpng_info.have_bg = FALSE;
184 wpng_info.have_time = FALSE;
185 wpng_info.have_text = 0;
186 wpng_info.gamma = 0.0;
187
188
189 /* First get the default value for our display-system exponent, i.e.,
190 * the product of the CRT exponent and the exponent corresponding to
191 * the frame-buffer's lookup table (LUT), if any. If the PNM image
192 * looks correct on the user's display system, its file gamma is the
193 * inverse of this value. (Note that this is not an exhaustive list
194 * of LUT values--e.g., OpenStep has a lot of weird ones--but it should
195 * cover 99% of the current possibilities. This section must ensure
196 * that default_display_exponent is positive.) */
197
198#if defined(NeXT)
199 /* third-party utilities can modify the default LUT exponent */
200 LUT_exponent = 1.0 / 2.2;
201 /*
202 if (some_next_function_that_returns_gamma(&next_gamma))
203 LUT_exponent = 1.0 / next_gamma;
204 */
205#elif defined(sgi)
206 LUT_exponent = 1.0 / 1.7;
207 /* there doesn't seem to be any documented function to
208 * get the "gamma" value, so we do it the hard way */
209 tmpfile = fopen("/etc/config/system.glGammaVal", "r");
210 if (tmpfile) {
211 double sgi_gamma;
212
213 fgets(tmpline, 80, tmpfile);
214 fclose(tmpfile);
215 sgi_gamma = atof(tmpline);
216 if (sgi_gamma > 0.0)
217 LUT_exponent = 1.0 / sgi_gamma;
218 }
219#elif defined(Macintosh)
220 LUT_exponent = 1.8 / 2.61;
221 /*
222 if (some_mac_function_that_returns_gamma(&mac_gamma))
223 LUT_exponent = mac_gamma / 2.61;
224 */
225#else
226 LUT_exponent = 1.0; /* assume no LUT: most PCs */
227#endif
228
229 /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
230 default_display_exponent = LUT_exponent * CRT_exponent;
231
232
233 /* If the user has set the SCREEN_GAMMA environment variable as suggested
234 * (somewhat imprecisely) in the libpng documentation, use that; otherwise
235 * use the default value we just calculated. Either way, the user may
236 * override this via a command-line option. */
237
238 if ((p = getenv("SCREEN_GAMMA")) != NULL) {
239 double exponent = atof(p);
240
241 if (exponent > 0.0)
242 default_gamma = 1.0 / exponent;
243 }
244
245 if (default_gamma == 0.0)
246 default_gamma = 1.0 / default_display_exponent;
247
248
249 /* Now parse the command line for options and the PNM filename. */
250
251 while (*++argv && !error) {
252 if (!strncmp(*argv, "-i", 2)) {
253 wpng_info.interlaced = TRUE;
254 } else if (!strncmp(*argv, "-time", 3)) {
255 wpng_info.modtime = time(NULL);
256 wpng_info.have_time = TRUE;
257 } else if (!strncmp(*argv, "-text", 3)) {
258 text = TRUE;
259 } else if (!strncmp(*argv, "-gamma", 2)) {
260 if (!*++argv)
261 ++error;
262 else {
263 wpng_info.gamma = atof(*argv);
264 if (wpng_info.gamma <= 0.0)
265 ++error;
266 else if (wpng_info.gamma > 1.01)
267 fprintf(stderr, PROGNAME
268 " warning: file gammas are usually less than 1.0\n");
269 }
270 } else if (!strncmp(*argv, "-bgcolor", 4)) {
271 if (!*++argv)
272 ++error;
273 else {
274 bgstr = *argv;
275 if (strlen(bgstr) != 7 || bgstr[0] != '#')
276 ++error;
277 else {
278 unsigned r, g, b; /* this way quiets compiler warnings */
279
280 sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
281 wpng_info.bg_red = (uch)r;
282 wpng_info.bg_green = (uch)g;
283 wpng_info.bg_blue = (uch)b;
284 wpng_info.have_bg = TRUE;
285 }
286 }
287 } else {
288 if (**argv != '-') {
289 inname = *argv;
290 if (argv[1]) /* shouldn't be any more args after filename */
291 ++error;
292 } else
293 ++error; /* not expecting any other options */
294 }
295 }
296
297
298 /* open the input and output files, or register an error and abort */
299
300 if (!inname) {
301 if (isatty(0)) {
302 fprintf(stderr, PROGNAME
303 ": must give input filename or provide image data via stdin\n");
304 ++error;
305 } else {
306#ifdef DOS_OS2_W32
307 /* some buggy C libraries require BOTH setmode() and fdopen(bin) */
308 setmode(fileno(stdin), O_BINARY);
309 setmode(fileno(stdout), O_BINARY);
310#endif
311 if ((wpng_info.infile = fdopen(fileno(stdin), "rb")) == NULL) {
312 fprintf(stderr, PROGNAME
313 ": unable to reopen stdin in binary mode\n");
314 ++error;
315 } else
316 if ((wpng_info.outfile = fdopen(fileno(stdout), "wb")) == NULL) {
317 fprintf(stderr, PROGNAME
318 ": unable to reopen stdout in binary mode\n");
319 fclose(wpng_info.infile);
320 ++error;
321 } else
322 wpng_info.filter = TRUE;
323 }
324 } else if ((len = strlen(inname)) > 250) {
325 fprintf(stderr, PROGNAME ": input filename is too long [%d chars]\n",
326 len);
327 ++error;
328 } else if (!(wpng_info.infile = fopen(inname, "rb"))) {
329 fprintf(stderr, PROGNAME ": can't open input file [%s]\n", inname);
330 ++error;
331 }
332
333 if (!error) {
334 fgets(pnmline, 256, wpng_info.infile);
335 if (pnmline[0] != 'P' || ((pnmchar = pnmline[1]) != '5' &&
336 pnmchar != '6' && pnmchar != '8'))
337 {
338 fprintf(stderr, PROGNAME
339 ": input file [%s] is not a binary PGM, PPM or PAM file\n",
340 inname);
341 ++error;
342 } else {
343 wpng_info.pnmtype = (int)(pnmchar - '0');
344 if (wpng_info.pnmtype != 8)
345 wpng_info.have_bg = FALSE; /* no need for bg if opaque */
346 do {
347 fgets(pnmline, 256, wpng_info.infile); /* lose any comments */
348 } while (pnmline[0] == '#');
349 sscanf(pnmline, "%ld %ld", &wpng_info.width, &wpng_info.height);
350 do {
351 fgets(pnmline, 256, wpng_info.infile); /* more comment lines */
352 } while (pnmline[0] == '#');
353 sscanf(pnmline, "%d", &maxval);
354 if (wpng_info.width <= 0L || wpng_info.height <= 0L ||
355 maxval != 255)
356 {
357 fprintf(stderr, PROGNAME
358 ": only positive width/height, maxval == 255 allowed \n");
359 ++error;
360 }
361 wpng_info.sample_depth = 8; /* <==> maxval 255 */
362
363 if (!wpng_info.filter) {
364 /* make outname from inname */
365 if ((p = strrchr(inname, '.')) == NULL ||
366 (p - inname) != (len - 4))
367 {
368 strcpy(outname, inname);
369 strcpy(outname+len, ".png");
370 } else {
371 len -= 4;
372 strncpy(outname, inname, len);
373 strcpy(outname+len, ".png");
374 }
375 /* check if outname already exists; if not, open */
376 if ((wpng_info.outfile = fopen(outname, "rb")) != NULL) {
377 fprintf(stderr, PROGNAME ": output file exists [%s]\n",
378 outname);
379 fclose(wpng_info.outfile);
380 ++error;
381 } else if (!(wpng_info.outfile = fopen(outname, "wb"))) {
382 fprintf(stderr, PROGNAME ": can't open output file [%s]\n",
383 outname);
384 ++error;
385 }
386 }
387 }
388 if (error) {
389 fclose(wpng_info.infile);
390 wpng_info.infile = NULL;
391 if (wpng_info.filter) {
392 fclose(wpng_info.outfile);
393 wpng_info.outfile = NULL;
394 }
395 }
396 }
397
398
399 /* if we had any errors, print usage and die horrible death...arrr! */
400
401 if (error) {
402 fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, APPNAME);
403 writepng_version_info();
404 fprintf(stderr, "\n"
405"Usage: %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] pnmfile\n"
406"or: ... | %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] | ...\n"
407 " exp \ttransfer-function exponent (``gamma'') of the image in\n"
408 "\t\t floating-point format (e.g., ``%.5f''); if image looks\n"
409 "\t\t correct on given display system, image gamma is equal to\n"
410 "\t\t inverse of display-system exponent, i.e., 1 / (LUT * CRT)\n"
411 "\t\t (where LUT = lookup-table exponent and CRT = CRT exponent;\n"
412 "\t\t first varies, second is usually 2.2, all are positive)\n"
413 " bg \tdesired background color for alpha-channel images, in\n"
414 "\t\t 7-character hex RGB format (e.g., ``#ff7700'' for orange:\n"
415 "\t\t same as HTML colors)\n"
416 " -text\tprompt interactively for text info (tEXt chunks)\n"
417 " -time\tinclude a tIME chunk (last modification time)\n"
418 " -interlace\twrite interlaced PNG image\n"
419 "\n"
420"pnmfile or stdin must be a binary PGM (`P5'), PPM (`P6') or (extremely\n"
421"unofficial and unsupported!) PAM (`P8') file. Currently it is required\n"
422"to have maxval == 255 (i.e., no scaling). If pnmfile is specified, it\n"
423"is converted to the corresponding PNG file with the same base name but a\n"
424"``.png'' extension; files read from stdin are converted and sent to stdout.\n"
425"The conversion is progressive (low memory usage) unless interlacing is\n"
426"requested; in that case the whole image will be buffered in memory and\n"
427"written in one call.\n"
428 "\n", PROGNAME, PROGNAME, default_gamma);
429 exit(1);
430 }
431
432
433 /* prepare the text buffers for libpng's use; note that even though
434 * PNG's png_text struct includes a length field, we don't have to fill
435 * it out */
436
437 if (text &&
438#ifndef DOS_OS2_W32
439 (keybd = fdopen(fileno(stderr), "r")) != NULL &&
440#endif
441 (textbuf = (char *)malloc((5 + 9)*75)) != NULL)
442 {
443 int i, valid, result;
444
445 fprintf(stderr,
446 "Enter text info (no more than 72 characters per line);\n");
447 fprintf(stderr, "to skip a field, hit the <Enter> key.\n");
448 /* note: just <Enter> leaves len == 1 */
449
450 do {
451 valid = TRUE;
452 p = textbuf + TEXT_TITLE_OFFSET;
453 fprintf(stderr, " Title: ");
454 fflush(stderr);
455 if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
456 if (p[len-1] == '\n')
457 p[--len] = '\0';
458 wpng_info.title = p;
459 wpng_info.have_text |= TEXT_TITLE;
460 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
461 fprintf(stderr, " " PROGNAME " warning: character code"
462 " %u is %sdiscouraged by the PNG\n specification "
463 "[first occurrence was at character position #%d]\n",
464 (unsigned)p[result], (p[result] == 27)? "strongly " : "",
465 result+1);
466 fflush(stderr);
467#ifdef FORBID_LATIN1_CTRL
468 wpng_info.have_text &= ~TEXT_TITLE;
469 valid = FALSE;
470#else
471 if (p[result] == 27) { /* escape character */
472 wpng_info.have_text &= ~TEXT_TITLE;
473 valid = FALSE;
474 }
475#endif
476 }
477 }
478 } while (!valid);
479
480 do {
481 valid = TRUE;
482 p = textbuf + TEXT_AUTHOR_OFFSET;
483 fprintf(stderr, " Author: ");
484 fflush(stderr);
485 if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
486 if (p[len-1] == '\n')
487 p[--len] = '\0';
488 wpng_info.author = p;
489 wpng_info.have_text |= TEXT_AUTHOR;
490 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
491 fprintf(stderr, " " PROGNAME " warning: character code"
492 " %u is %sdiscouraged by the PNG\n specification "
493 "[first occurrence was at character position #%d]\n",
494 (unsigned)p[result], (p[result] == 27)? "strongly " : "",
495 result+1);
496 fflush(stderr);
497#ifdef FORBID_LATIN1_CTRL
498 wpng_info.have_text &= ~TEXT_AUTHOR;
499 valid = FALSE;
500#else
501 if (p[result] == 27) { /* escape character */
502 wpng_info.have_text &= ~TEXT_AUTHOR;
503 valid = FALSE;
504 }
505#endif
506 }
507 }
508 } while (!valid);
509
510 do {
511 valid = TRUE;
512 p = textbuf + TEXT_DESC_OFFSET;
513 fprintf(stderr, " Description (up to 9 lines):\n");
514 for (i = 1; i < 10; ++i) {
515 fprintf(stderr, " [%d] ", i);
516 fflush(stderr);
517 if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1)
518 p += len; /* now points at NULL; char before is newline */
519 else
520 break;
521 }
522 if ((len = p - (textbuf + TEXT_DESC_OFFSET)) > 1) {
523 if (p[-1] == '\n') {
524 p[-1] = '\0';
525 --len;
526 }
527 wpng_info.desc = textbuf + TEXT_DESC_OFFSET;
528 wpng_info.have_text |= TEXT_DESC;
529 p = textbuf + TEXT_DESC_OFFSET;
530 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
531 fprintf(stderr, " " PROGNAME " warning: character code"
532 " %u is %sdiscouraged by the PNG\n specification "
533 "[first occurrence was at character position #%d]\n",
534 (unsigned)p[result], (p[result] == 27)? "strongly " : "",
535 result+1);
536 fflush(stderr);
537#ifdef FORBID_LATIN1_CTRL
538 wpng_info.have_text &= ~TEXT_DESC;
539 valid = FALSE;
540#else
541 if (p[result] == 27) { /* escape character */
542 wpng_info.have_text &= ~TEXT_DESC;
543 valid = FALSE;
544 }
545#endif
546 }
547 }
548 } while (!valid);
549
550 do {
551 valid = TRUE;
552 p = textbuf + TEXT_COPY_OFFSET;
553 fprintf(stderr, " Copyright: ");
554 fflush(stderr);
555 if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
556 if (p[len-1] == '\n')
557 p[--len] = '\0';
558 wpng_info.copyright = p;
559 wpng_info.have_text |= TEXT_COPY;
560 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
561 fprintf(stderr, " " PROGNAME " warning: character code"
562 " %u is %sdiscouraged by the PNG\n specification "
563 "[first occurrence was at character position #%d]\n",
564 (unsigned)p[result], (p[result] == 27)? "strongly " : "",
565 result+1);
566 fflush(stderr);
567#ifdef FORBID_LATIN1_CTRL
568 wpng_info.have_text &= ~TEXT_COPY;
569 valid = FALSE;
570#else
571 if (p[result] == 27) { /* escape character */
572 wpng_info.have_text &= ~TEXT_COPY;
573 valid = FALSE;
574 }
575#endif
576 }
577 }
578 } while (!valid);
579
580 do {
581 valid = TRUE;
582 p = textbuf + TEXT_EMAIL_OFFSET;
583 fprintf(stderr, " E-mail: ");
584 fflush(stderr);
585 if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
586 if (p[len-1] == '\n')
587 p[--len] = '\0';
588 wpng_info.email = p;
589 wpng_info.have_text |= TEXT_EMAIL;
590 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
591 fprintf(stderr, " " PROGNAME " warning: character code"
592 " %u is %sdiscouraged by the PNG\n specification "
593 "[first occurrence was at character position #%d]\n",
594 (unsigned)p[result], (p[result] == 27)? "strongly " : "",
595 result+1);
596 fflush(stderr);
597#ifdef FORBID_LATIN1_CTRL
598 wpng_info.have_text &= ~TEXT_EMAIL;
599 valid = FALSE;
600#else
601 if (p[result] == 27) { /* escape character */
602 wpng_info.have_text &= ~TEXT_EMAIL;
603 valid = FALSE;
604 }
605#endif
606 }
607 }
608 } while (!valid);
609
610 do {
611 valid = TRUE;
612 p = textbuf + TEXT_URL_OFFSET;
613 fprintf(stderr, " URL: ");
614 fflush(stderr);
615 if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
616 if (p[len-1] == '\n')
617 p[--len] = '\0';
618 wpng_info.url = p;
619 wpng_info.have_text |= TEXT_URL;
620 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
621 fprintf(stderr, " " PROGNAME " warning: character code"
622 " %u is %sdiscouraged by the PNG\n specification "
623 "[first occurrence was at character position #%d]\n",
624 (unsigned)p[result], (p[result] == 27)? "strongly " : "",
625 result+1);
626 fflush(stderr);
627#ifdef FORBID_LATIN1_CTRL
628 wpng_info.have_text &= ~TEXT_URL;
629 valid = FALSE;
630#else
631 if (p[result] == 27) { /* escape character */
632 wpng_info.have_text &= ~TEXT_URL;
633 valid = FALSE;
634 }
635#endif
636 }
637 }
638 } while (!valid);
639
640#ifndef DOS_OS2_W32
641 fclose(keybd);
642#endif
643
644 } else if (text) {
645 fprintf(stderr, PROGNAME ": unable to allocate memory for text\n");
646 text = FALSE;
647 wpng_info.have_text = 0;
648 }
649
650
651 /* allocate libpng stuff, initialize transformations, write pre-IDAT data */
652
653 if ((rc = writepng_init(&wpng_info)) != 0) {
654 switch (rc) {
655 case 2:
656 fprintf(stderr, PROGNAME
657 ": libpng initialization problem (longjmp)\n");
658 break;
659 case 4:
660 fprintf(stderr, PROGNAME ": insufficient memory\n");
661 break;
662 case 11:
663 fprintf(stderr, PROGNAME
664 ": internal logic error (unexpected PNM type)\n");
665 break;
666 default:
667 fprintf(stderr, PROGNAME
668 ": unknown writepng_init() error\n");
669 break;
670 }
671 exit(rc);
672 }
673
674
675 /* free textbuf, since it's a completely local variable and all text info
676 * has just been written to the PNG file */
677
678 if (text && textbuf) {
679 free(textbuf);
680 textbuf = NULL;
681 }
682
683
684 /* calculate rowbytes on basis of image type; note that this becomes much
685 * more complicated if we choose to support PBM type, ASCII PNM types, or
686 * 16-bit-per-sample binary data [currently not an official NetPBM type] */
687
688 if (wpng_info.pnmtype == 5)
689 rowbytes = wpng_info.width;
690 else if (wpng_info.pnmtype == 6)
691 rowbytes = wpng_info.width * 3;
692 else /* if (wpng_info.pnmtype == 8) */
693 rowbytes = wpng_info.width * 4;
694
695
696 /* read and write the image, either in its entirety (if writing interlaced
697 * PNG) or row by row (if non-interlaced) */
698
699 fprintf(stderr, "Encoding image data...\n");
700 fflush(stderr);
701
702 if (wpng_info.interlaced) {
703 long i;
704 ulg bytes;
705 ulg image_bytes = rowbytes * wpng_info.height; /* overflow? */
706
707 wpng_info.image_data = (uch *)malloc(image_bytes);
708 wpng_info.row_pointers = (uch **)malloc(wpng_info.height*sizeof(uch *));
709 if (wpng_info.image_data == NULL || wpng_info.row_pointers == NULL) {
710 fprintf(stderr, PROGNAME ": insufficient memory for image data\n");
711 writepng_cleanup(&wpng_info);
712 wpng_cleanup();
713 exit(5);
714 }
715 for (i = 0; i < wpng_info.height; ++i)
716 wpng_info.row_pointers[i] = wpng_info.image_data + i*rowbytes;
717 bytes = fread(wpng_info.image_data, 1, image_bytes, wpng_info.infile);
718 if (bytes != image_bytes) {
719 fprintf(stderr, PROGNAME ": expected %lu bytes, got %lu bytes\n",
720 image_bytes, bytes);
721 fprintf(stderr, " (continuing anyway)\n");
722 }
723 if (writepng_encode_image(&wpng_info) != 0) {
724 fprintf(stderr, PROGNAME
725 ": libpng problem (longjmp) while writing image data\n");
726 writepng_cleanup(&wpng_info);
727 wpng_cleanup();
728 exit(2);
729 }
730
731 } else /* not interlaced: write progressively (row by row) */ {
732 long j;
733 ulg bytes;
734
735 wpng_info.image_data = (uch *)malloc(rowbytes);
736 if (wpng_info.image_data == NULL) {
737 fprintf(stderr, PROGNAME ": insufficient memory for row data\n");
738 writepng_cleanup(&wpng_info);
739 wpng_cleanup();
740 exit(5);
741 }
742 error = 0;
743 for (j = wpng_info.height; j > 0L; --j) {
744 bytes = fread(wpng_info.image_data, 1, rowbytes, wpng_info.infile);
745 if (bytes != rowbytes) {
746 fprintf(stderr, PROGNAME
747 ": expected %lu bytes, got %lu bytes (row %ld)\n", rowbytes,
748 bytes, wpng_info.height-j);
749 ++error;
750 break;
751 }
752 if (writepng_encode_row(&wpng_info) != 0) {
753 fprintf(stderr, PROGNAME
754 ": libpng problem (longjmp) while writing row %ld\n",
755 wpng_info.height-j);
756 ++error;
757 break;
758 }
759 }
760 if (error) {
761 writepng_cleanup(&wpng_info);
762 wpng_cleanup();
763 exit(2);
764 }
765 if (writepng_encode_finish(&wpng_info) != 0) {
766 fprintf(stderr, PROGNAME ": error on final libpng call\n");
767 writepng_cleanup(&wpng_info);
768 wpng_cleanup();
769 exit(2);
770 }
771 }
772
773
774 /* OK, we're done (successfully): clean up all resources and quit */
775
776 fprintf(stderr, "Done.\n");
777 fflush(stderr);
778
779 writepng_cleanup(&wpng_info);
780 wpng_cleanup();
781
782 return 0;
783}
784
785
786
787
788
789static int wpng_isvalid_latin1(uch *p, int len)
790{
791 int i, result = -1;
792
793 for (i = 0; i < len; ++i) {
794 if (p[i] == 10 || (p[i] > 31 && p[i] < 127) || p[i] > 160)
795 continue; /* character is completely OK */
796 if (result < 0 || (p[result] != 27 && p[i] == 27))
797 result = i; /* mark location of first questionable one */
798 } /* or of first escape character (bad) */
799
800 return result;
801}
802
803
804
805
806
807static void wpng_cleanup(void)
808{
809 if (wpng_info.outfile) {
810 fclose(wpng_info.outfile);
811 wpng_info.outfile = NULL;
812 }
813
814 if (wpng_info.infile) {
815 fclose(wpng_info.infile);
816 wpng_info.infile = NULL;
817 }
818
819 if (wpng_info.image_data) {
820 free(wpng_info.image_data);
821 wpng_info.image_data = NULL;
822 }
823
824 if (wpng_info.row_pointers) {
825 free(wpng_info.row_pointers);
826 wpng_info.row_pointers = NULL;
827 }
828}
829
830
831
832
833#ifdef DOS_OS2_W32
834
835static char *dos_kbd_gets(char *buf, int len)
836{
837 int ch, count=0;
838
839 do {
840 buf[count++] = ch = getche();
841 } while (ch != '\r' && count < len-1);
842
843 buf[count--] = '\0'; /* terminate string */
844 if (buf[count] == '\r') /* Enter key makes CR, so change to newline */
845 buf[count] = '\n';
846
847 fprintf(stderr, "\n"); /* Enter key does *not* cause a newline */
848 fflush(stderr);
849
850 return buf;
851}
852
853#endif /* DOS_OS2_W32 */
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/writepng.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/writepng.c
new file mode 100644
index 0000000..8373c16
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/writepng.c
@@ -0,0 +1,400 @@
1/*---------------------------------------------------------------------------
2
3 wpng - simple PNG-writing program writepng.c
4
5 ---------------------------------------------------------------------------
6
7 Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
8
9 This software is provided "as is," without warranty of any kind,
10 express or implied. In no event shall the author or contributors
11 be held liable for any damages arising in any way from the use of
12 this software.
13
14 The contents of this file are DUAL-LICENSED. You may modify and/or
15 redistribute this software according to the terms of one of the
16 following two licenses (at your option):
17
18
19 LICENSE 1 ("BSD-like with advertising clause"):
20
21 Permission is granted to anyone to use this software for any purpose,
22 including commercial applications, and to alter it and redistribute
23 it freely, subject to the following restrictions:
24
25 1. Redistributions of source code must retain the above copyright
26 notice, disclaimer, and this list of conditions.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, disclaimer, and this list of conditions in the documenta-
29 tion and/or other materials provided with the distribution.
30 3. All advertising materials mentioning features or use of this
31 software must display the following acknowledgment:
32
33 This product includes software developed by Greg Roelofs
34 and contributors for the book, "PNG: The Definitive Guide,"
35 published by O'Reilly and Associates.
36
37
38 LICENSE 2 (GNU GPL v2 or later):
39
40 This program is free software; you can redistribute it and/or modify
41 it under the terms of the GNU General Public License as published by
42 the Free Software Foundation; either version 2 of the License, or
43 (at your option) any later version.
44
45 This program is distributed in the hope that it will be useful,
46 but WITHOUT ANY WARRANTY; without even the implied warranty of
47 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 GNU General Public License for more details.
49
50 You should have received a copy of the GNU General Public License
51 along with this program; if not, write to the Free Software Foundation,
52 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53
54 ---------------------------------------------------------------------------*/
55
56
57#include <stdlib.h> /* for exit() prototype */
58
59#include "png.h" /* libpng header; includes zlib.h and setjmp.h */
60#include "writepng.h" /* typedefs, common macros, public prototypes */
61
62
63/* local prototype */
64
65static void writepng_error_handler(png_structp png_ptr, png_const_charp msg);
66
67
68
69void writepng_version_info(void)
70{
71 fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
72 PNG_LIBPNG_VER_STRING, png_libpng_ver);
73 fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
74 ZLIB_VERSION, zlib_version);
75}
76
77
78
79
80/* returns 0 for success, 2 for libpng problem, 4 for out of memory, 11 for
81 * unexpected pnmtype; note that outfile might be stdout */
82
83int writepng_init(mainprog_info *mainprog_ptr)
84{
85 png_structp png_ptr; /* note: temporary variables! */
86 png_infop info_ptr;
87 int color_type, interlace_type;
88
89
90 /* could also replace libpng warning-handler (final NULL), but no need: */
91
92 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
93 writepng_error_handler, NULL);
94 if (!png_ptr)
95 return 4; /* out of memory */
96
97 info_ptr = png_create_info_struct(png_ptr);
98 if (!info_ptr) {
99 png_destroy_write_struct(&png_ptr, NULL);
100 return 4; /* out of memory */
101 }
102
103
104 /* setjmp() must be called in every function that calls a PNG-writing
105 * libpng function, unless an alternate error handler was installed--
106 * but compatible error handlers must either use longjmp() themselves
107 * (as in this program) or some other method to return control to
108 * application code, so here we go: */
109
110 if (setjmp(mainprog_ptr->jmpbuf)) {
111 png_destroy_write_struct(&png_ptr, &info_ptr);
112 return 2;
113 }
114
115
116 /* make sure outfile is (re)opened in BINARY mode */
117
118 png_init_io(png_ptr, mainprog_ptr->outfile);
119
120
121 /* set the compression levels--in general, always want to leave filtering
122 * turned on (except for palette images) and allow all of the filters,
123 * which is the default; want 32K zlib window, unless entire image buffer
124 * is 16K or smaller (unknown here)--also the default; usually want max
125 * compression (NOT the default); and remaining compression flags should
126 * be left alone */
127
128 png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
129/*
130 >> this is default for no filtering; Z_FILTERED is default otherwise:
131 png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
132 >> these are all defaults:
133 png_set_compression_mem_level(png_ptr, 8);
134 png_set_compression_window_bits(png_ptr, 15);
135 png_set_compression_method(png_ptr, 8);
136 */
137
138
139 /* set the image parameters appropriately */
140
141 if (mainprog_ptr->pnmtype == 5)
142 color_type = PNG_COLOR_TYPE_GRAY;
143 else if (mainprog_ptr->pnmtype == 6)
144 color_type = PNG_COLOR_TYPE_RGB;
145 else if (mainprog_ptr->pnmtype == 8)
146 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
147 else {
148 png_destroy_write_struct(&png_ptr, &info_ptr);
149 return 11;
150 }
151
152 interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 :
153 PNG_INTERLACE_NONE;
154
155 png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
156 mainprog_ptr->sample_depth, color_type, interlace_type,
157 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
158
159 if (mainprog_ptr->gamma > 0.0)
160 png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma);
161
162 if (mainprog_ptr->have_bg) { /* we know it's RGBA, not gray+alpha */
163 png_color_16 background;
164
165 background.red = mainprog_ptr->bg_red;
166 background.green = mainprog_ptr->bg_green;
167 background.blue = mainprog_ptr->bg_blue;
168 png_set_bKGD(png_ptr, info_ptr, &background);
169 }
170
171 if (mainprog_ptr->have_time) {
172 png_time modtime;
173
174 png_convert_from_time_t(&modtime, mainprog_ptr->modtime);
175 png_set_tIME(png_ptr, info_ptr, &modtime);
176 }
177
178 if (mainprog_ptr->have_text) {
179 png_text text[6];
180 int num_text = 0;
181
182 if (mainprog_ptr->have_text & TEXT_TITLE) {
183 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
184 text[num_text].key = "Title";
185 text[num_text].text = mainprog_ptr->title;
186 ++num_text;
187 }
188 if (mainprog_ptr->have_text & TEXT_AUTHOR) {
189 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
190 text[num_text].key = "Author";
191 text[num_text].text = mainprog_ptr->author;
192 ++num_text;
193 }
194 if (mainprog_ptr->have_text & TEXT_DESC) {
195 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
196 text[num_text].key = "Description";
197 text[num_text].text = mainprog_ptr->desc;
198 ++num_text;
199 }
200 if (mainprog_ptr->have_text & TEXT_COPY) {
201 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
202 text[num_text].key = "Copyright";
203 text[num_text].text = mainprog_ptr->copyright;
204 ++num_text;
205 }
206 if (mainprog_ptr->have_text & TEXT_EMAIL) {
207 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
208 text[num_text].key = "E-mail";
209 text[num_text].text = mainprog_ptr->email;
210 ++num_text;
211 }
212 if (mainprog_ptr->have_text & TEXT_URL) {
213 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
214 text[num_text].key = "URL";
215 text[num_text].text = mainprog_ptr->url;
216 ++num_text;
217 }
218 png_set_text(png_ptr, info_ptr, text, num_text);
219 }
220
221
222 /* write all chunks up to (but not including) first IDAT */
223
224 png_write_info(png_ptr, info_ptr);
225
226
227 /* if we wanted to write any more text info *after* the image data, we
228 * would set up text struct(s) here and call png_set_text() again, with
229 * just the new data; png_set_tIME() could also go here, but it would
230 * have no effect since we already called it above (only one tIME chunk
231 * allowed) */
232
233
234 /* set up the transformations: for now, just pack low-bit-depth pixels
235 * into bytes (one, two or four pixels per byte) */
236
237 png_set_packing(png_ptr);
238/* png_set_shift(png_ptr, &sig_bit); to scale low-bit-depth values */
239
240
241 /* make sure we save our pointers for use in writepng_encode_image() */
242
243 mainprog_ptr->png_ptr = png_ptr;
244 mainprog_ptr->info_ptr = info_ptr;
245
246
247 /* OK, that's all we need to do for now; return happy */
248
249 return 0;
250}
251
252
253
254
255
256/* returns 0 for success, 2 for libpng (longjmp) problem */
257
258int writepng_encode_image(mainprog_info *mainprog_ptr)
259{
260 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
261 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
262
263
264 /* as always, setjmp() must be called in every function that calls a
265 * PNG-writing libpng function */
266
267 if (setjmp(mainprog_ptr->jmpbuf)) {
268 png_destroy_write_struct(&png_ptr, &info_ptr);
269 mainprog_ptr->png_ptr = NULL;
270 mainprog_ptr->info_ptr = NULL;
271 return 2;
272 }
273
274
275 /* and now we just write the whole image; libpng takes care of interlacing
276 * for us */
277
278 png_write_image(png_ptr, mainprog_ptr->row_pointers);
279
280
281 /* since that's it, we also close out the end of the PNG file now--if we
282 * had any text or time info to write after the IDATs, second argument
283 * would be info_ptr, but we optimize slightly by sending NULL pointer: */
284
285 png_write_end(png_ptr, NULL);
286
287 return 0;
288}
289
290
291
292
293
294/* returns 0 if succeeds, 2 if libpng problem */
295
296int writepng_encode_row(mainprog_info *mainprog_ptr) /* NON-interlaced only! */
297{
298 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
299 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
300
301
302 /* as always, setjmp() must be called in every function that calls a
303 * PNG-writing libpng function */
304
305 if (setjmp(mainprog_ptr->jmpbuf)) {
306 png_destroy_write_struct(&png_ptr, &info_ptr);
307 mainprog_ptr->png_ptr = NULL;
308 mainprog_ptr->info_ptr = NULL;
309 return 2;
310 }
311
312
313 /* image_data points at our one row of image data */
314
315 png_write_row(png_ptr, mainprog_ptr->image_data);
316
317 return 0;
318}
319
320
321
322
323
324/* returns 0 if succeeds, 2 if libpng problem */
325
326int writepng_encode_finish(mainprog_info *mainprog_ptr) /* NON-interlaced! */
327{
328 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
329 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
330
331
332 /* as always, setjmp() must be called in every function that calls a
333 * PNG-writing libpng function */
334
335 if (setjmp(mainprog_ptr->jmpbuf)) {
336 png_destroy_write_struct(&png_ptr, &info_ptr);
337 mainprog_ptr->png_ptr = NULL;
338 mainprog_ptr->info_ptr = NULL;
339 return 2;
340 }
341
342
343 /* close out PNG file; if we had any text or time info to write after
344 * the IDATs, second argument would be info_ptr: */
345
346 png_write_end(png_ptr, NULL);
347
348 return 0;
349}
350
351
352
353
354
355void writepng_cleanup(mainprog_info *mainprog_ptr)
356{
357 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
358 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
359
360 if (png_ptr && info_ptr)
361 png_destroy_write_struct(&png_ptr, &info_ptr);
362}
363
364
365
366
367
368static void writepng_error_handler(png_structp png_ptr, png_const_charp msg)
369{
370 mainprog_info *mainprog_ptr;
371
372 /* This function, aside from the extra step of retrieving the "error
373 * pointer" (below) and the fact that it exists within the application
374 * rather than within libpng, is essentially identical to libpng's
375 * default error handler. The second point is critical: since both
376 * setjmp() and longjmp() are called from the same code, they are
377 * guaranteed to have compatible notions of how big a jmp_buf is,
378 * regardless of whether _BSD_SOURCE or anything else has (or has not)
379 * been defined. */
380
381 fprintf(stderr, "writepng libpng error: %s\n", msg);
382 fflush(stderr);
383
384 mainprog_ptr = png_get_error_ptr(png_ptr);
385 if (mainprog_ptr == NULL) { /* we are completely hosed now */
386 fprintf(stderr,
387 "writepng severe error: jmpbuf not recoverable; terminating.\n");
388 fflush(stderr);
389 exit(99);
390 }
391
392 /* Now we have our data structure we can use the information in it
393 * to return control to our own higher level code (all the points
394 * where 'setjmp' is called in this file.) This will work with other
395 * error handling mechanisms as well - libpng always calls png_error
396 * when it can proceed no further, thus, so long as the error handler
397 * is intercepted, application code can do its own error recovery.
398 */
399 longjmp(mainprog_ptr->jmpbuf, 1);
400}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/writepng.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/writepng.h
new file mode 100644
index 0000000..904e4fb
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/writepng.h
@@ -0,0 +1,133 @@
1/*---------------------------------------------------------------------------
2
3 wpng - simple PNG-writing program writepng.h
4
5 ---------------------------------------------------------------------------
6
7 Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
8
9 This software is provided "as is," without warranty of any kind,
10 express or implied. In no event shall the author or contributors
11 be held liable for any damages arising in any way from the use of
12 this software.
13
14 The contents of this file are DUAL-LICENSED. You may modify and/or
15 redistribute this software according to the terms of one of the
16 following two licenses (at your option):
17
18
19 LICENSE 1 ("BSD-like with advertising clause"):
20
21 Permission is granted to anyone to use this software for any purpose,
22 including commercial applications, and to alter it and redistribute
23 it freely, subject to the following restrictions:
24
25 1. Redistributions of source code must retain the above copyright
26 notice, disclaimer, and this list of conditions.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, disclaimer, and this list of conditions in the documenta-
29 tion and/or other materials provided with the distribution.
30 3. All advertising materials mentioning features or use of this
31 software must display the following acknowledgment:
32
33 This product includes software developed by Greg Roelofs
34 and contributors for the book, "PNG: The Definitive Guide,"
35 published by O'Reilly and Associates.
36
37
38 LICENSE 2 (GNU GPL v2 or later):
39
40 This program is free software; you can redistribute it and/or modify
41 it under the terms of the GNU General Public License as published by
42 the Free Software Foundation; either version 2 of the License, or
43 (at your option) any later version.
44
45 This program is distributed in the hope that it will be useful,
46 but WITHOUT ANY WARRANTY; without even the implied warranty of
47 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 GNU General Public License for more details.
49
50 You should have received a copy of the GNU General Public License
51 along with this program; if not, write to the Free Software Foundation,
52 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53
54 ---------------------------------------------------------------------------*/
55
56#ifndef TRUE
57# define TRUE 1
58# define FALSE 0
59#endif
60
61#ifndef MAX
62# define MAX(a,b) ((a) > (b)? (a) : (b))
63# define MIN(a,b) ((a) < (b)? (a) : (b))
64#endif
65
66#ifdef DEBUG
67# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
68#else
69# define Trace(x) ;
70#endif
71
72#define TEXT_TITLE 0x01
73#define TEXT_AUTHOR 0x02
74#define TEXT_DESC 0x04
75#define TEXT_COPY 0x08
76#define TEXT_EMAIL 0x10
77#define TEXT_URL 0x20
78
79#define TEXT_TITLE_OFFSET 0
80#define TEXT_AUTHOR_OFFSET 72
81#define TEXT_COPY_OFFSET (2*72)
82#define TEXT_EMAIL_OFFSET (3*72)
83#define TEXT_URL_OFFSET (4*72)
84#define TEXT_DESC_OFFSET (5*72)
85
86typedef unsigned char uch;
87typedef unsigned short ush;
88typedef unsigned long ulg;
89
90typedef struct _mainprog_info {
91 double gamma;
92 long width;
93 long height;
94 time_t modtime;
95 FILE *infile;
96 FILE *outfile;
97 void *png_ptr;
98 void *info_ptr;
99 uch *image_data;
100 uch **row_pointers;
101 char *title;
102 char *author;
103 char *desc;
104 char *copyright;
105 char *email;
106 char *url;
107 int filter; /* command-line-filter flag, not PNG row filter! */
108 int pnmtype;
109 int sample_depth;
110 int interlaced;
111 int have_bg;
112 int have_time;
113 int have_text;
114 jmp_buf jmpbuf;
115 uch bg_red;
116 uch bg_green;
117 uch bg_blue;
118} mainprog_info;
119
120
121/* prototypes for public functions in writepng.c */
122
123void writepng_version_info(void);
124
125int writepng_init(mainprog_info *mainprog_ptr);
126
127int writepng_encode_image(mainprog_info *mainprog_ptr);
128
129int writepng_encode_row(mainprog_info *mainprog_ptr);
130
131int writepng_encode_finish(mainprog_info *mainprog_ptr);
132
133void writepng_cleanup(mainprog_info *mainprog_ptr);
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c
new file mode 100644
index 0000000..c7068fa
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c
@@ -0,0 +1,9837 @@
1
2/* pngvalid.c - validate libpng by constructing then reading png files.
3 *
4 * Last changed in libpng 1.5.8 [%RDATE%]
5 * Copyright (c) 2012 Glenn Randers-Pehrson
6 * Written by John Cunningham Bowler
7 *
8 * This code is released under the libpng license.
9 * For conditions of distribution and use, see the disclaimer
10 * and license in png.h
11 *
12 * NOTES:
13 * This is a C program that is intended to be linked against libpng. It
14 * generates bitmaps internally, stores them as PNG files (using the
15 * sequential write code) then reads them back (using the sequential
16 * read code) and validates that the result has the correct data.
17 *
18 * The program can be modified and extended to test the correctness of
19 * transformations performed by libpng.
20 */
21
22#define _POSIX_SOURCE 1
23#define _ISOC99_SOURCE 1 /* For floating point */
24#define _GNU_SOURCE 1 /* For the floating point exception extension */
25
26#include <signal.h>
27
28#ifdef HAVE_FEENABLEEXCEPT
29# include <fenv.h>
30#endif
31
32/* Define the following to use this test against your installed libpng, rather
33 * than the one being built here:
34 */
35#ifdef PNG_FREESTANDING_TESTS
36# include <png.h>
37#else
38# include "../../png.h"
39#endif
40
41#if PNG_LIBPNG_VER < 10500
42/* This deliberately lacks the PNG_CONST. */
43typedef png_byte *png_const_bytep;
44
45/* This is copied from 1.5.1 png.h: */
46#define PNG_INTERLACE_ADAM7_PASSES 7
47#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7)
48#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7)
49#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3)
50#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3)
51#define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\
52 -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass))
53#define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\
54 -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass))
55#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \
56 (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
57#define PNG_COL_FROM_PASS_COL(xIn, pass) \
58 (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
59#define PNG_PASS_MASK(pass,off) ( \
60 ((0x110145AFU>>(((7-(off))-(pass))<<2)) & 0xFU) | \
61 ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U))
62#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \
63 ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1)
64#define PNG_COL_IN_INTERLACE_PASS(x, pass) \
65 ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
66
67/* These are needed too for the default build: */
68#define PNG_WRITE_16BIT_SUPPORTED
69#define PNG_READ_16BIT_SUPPORTED
70
71/* This comes from pnglibconf.h afer 1.5: */
72#define PNG_FP_1 100000
73#define PNG_GAMMA_THRESHOLD_FIXED\
74 ((png_fixed_point)(PNG_GAMMA_THRESHOLD * PNG_FP_1))
75#endif
76
77#include "zlib.h" /* For crc32 */
78
79#include <float.h> /* For floating point constants */
80#include <stdlib.h> /* For malloc */
81#include <string.h> /* For memcpy, memset */
82#include <math.h> /* For floor */
83
84/* Unused formal parameter errors are removed using the following macro which is
85 * expected to have no bad effects on performance.
86 */
87#ifndef UNUSED
88# if defined(__GNUC__) || defined(_MSC_VER)
89# define UNUSED(param) (void)param;
90# else
91# define UNUSED(param)
92# endif
93#endif
94
95/***************************** EXCEPTION HANDLING *****************************/
96#include "../visupng/cexcept.h"
97
98#ifdef __cplusplus
99# define this not_the_cpp_this
100# define new not_the_cpp_new
101# define voidcast(type, value) static_cast<type>(value)
102#else
103# define voidcast(type, value) (value)
104#endif /* __cplusplus */
105
106struct png_store;
107define_exception_type(struct png_store*);
108
109/* The following are macros to reduce typing everywhere where the well known
110 * name 'the_exception_context' must be defined.
111 */
112#define anon_context(ps) struct exception_context *the_exception_context = \
113 &(ps)->exception_context
114#define context(ps,fault) anon_context(ps); png_store *fault
115
116/******************************* UTILITIES ************************************/
117/* Error handling is particularly problematic in production code - error
118 * handlers often themselves have bugs which lead to programs that detect
119 * minor errors crashing. The following functions deal with one very
120 * common class of errors in error handlers - attempting to format error or
121 * warning messages into buffers that are too small.
122 */
123static size_t safecat(char *buffer, size_t bufsize, size_t pos,
124 PNG_CONST char *cat)
125{
126 while (pos < bufsize && cat != NULL && *cat != 0)
127 buffer[pos++] = *cat++;
128
129 if (pos >= bufsize)
130 pos = bufsize-1;
131
132 buffer[pos] = 0;
133 return pos;
134}
135
136static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n)
137{
138 char number[64];
139 sprintf(number, "%d", n);
140 return safecat(buffer, bufsize, pos, number);
141}
142
143#ifdef PNG_READ_TRANSFORMS_SUPPORTED
144static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d,
145 int precision)
146{
147 char number[64];
148 sprintf(number, "%.*f", precision, d);
149 return safecat(buffer, bufsize, pos, number);
150}
151#endif
152
153static PNG_CONST char invalid[] = "invalid";
154static PNG_CONST char sep[] = ": ";
155
156static PNG_CONST char *colour_types[8] =
157{
158 "grayscale", invalid, "truecolour", "indexed-colour",
159 "grayscale with alpha", invalid, "truecolour with alpha", invalid
160};
161
162/* Convert a double precision value to fixed point. */
163static png_fixed_point
164fix(double d)
165{
166 d = floor(d * PNG_FP_1 + .5);
167 return (png_fixed_point)d;
168}
169
170/* Generate random bytes. This uses a boring repeatable algorithm and it
171 * is implemented here so that it gives the same set of numbers on every
172 * architecture. It's a linear congruential generator (Knuth or Sedgewick
173 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
174 * Hill, "The Art of Electronics".
175 */
176static void
177make_random_bytes(png_uint_32* seed, void* pv, size_t size)
178{
179 png_uint_32 u0 = seed[0], u1 = seed[1];
180 png_bytep bytes = voidcast(png_bytep, pv);
181
182 /* There are thirty three bits, the next bit in the sequence is bit-33 XOR
183 * bit-20. The top 1 bit is in u1, the bottom 32 are in u0.
184 */
185 size_t i;
186 for (i=0; i<size; ++i)
187 {
188 /* First generate 8 new bits then shift them in at the end. */
189 png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff;
190 u1 <<= 8;
191 u1 |= u0 >> 24;
192 u0 <<= 8;
193 u0 |= u;
194 *bytes++ = (png_byte)u;
195 }
196
197 seed[0] = u0;
198 seed[1] = u1;
199}
200
201static void
202make_four_random_bytes(png_uint_32* seed, png_bytep bytes)
203{
204 make_random_bytes(seed, bytes, 4);
205}
206
207static void
208randomize(void *pv, size_t size)
209{
210 static png_uint_32 random_seed[2] = {0x56789abc, 0xd};
211 make_random_bytes(random_seed, pv, size);
212}
213
214#define RANDOMIZE(this) randomize(&(this), sizeof (this))
215
216static unsigned int
217random_mod(unsigned int max)
218{
219 unsigned int x;
220
221 RANDOMIZE(x);
222
223 return x % max; /* 0 .. max-1 */
224}
225
226static int
227random_choice(void)
228{
229 unsigned char x;
230
231 RANDOMIZE(x);
232
233 return x & 1;
234}
235
236/* A numeric ID based on PNG file characteristics. The 'do_interlace' field
237 * simply records whether pngvalid did the interlace itself or whether it
238 * was done by libpng. Width and height must be less than 256. 'palette' is an
239 * index of the palette to use for formats with a palette (0 otherwise.)
240 */
241#define FILEID(col, depth, palette, interlace, width, height, do_interlace) \
242 ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \
243 (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24)))
244
245#define COL_FROM_ID(id) ((png_byte)((id)& 0x7U))
246#define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU))
247#define PALETTE_FROM_ID(id) ((int)(((id) >> 8) & 0x1f))
248#define INTERLACE_FROM_ID(id) ((int)(((id) >> 13) & 0x3))
249#define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1))
250#define WIDTH_FROM_ID(id) (((id)>>16) & 0xff)
251#define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff)
252
253/* Utility to construct a standard name for a standard image. */
254static size_t
255standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type,
256 int bit_depth, int npalette, int interlace_type,
257 png_uint_32 w, png_uint_32 h, int do_interlace)
258{
259 pos = safecat(buffer, bufsize, pos, colour_types[colour_type]);
260 if (npalette > 0)
261 {
262 pos = safecat(buffer, bufsize, pos, "[");
263 pos = safecatn(buffer, bufsize, pos, npalette);
264 pos = safecat(buffer, bufsize, pos, "]");
265 }
266 pos = safecat(buffer, bufsize, pos, " ");
267 pos = safecatn(buffer, bufsize, pos, bit_depth);
268 pos = safecat(buffer, bufsize, pos, " bit");
269
270 if (interlace_type != PNG_INTERLACE_NONE)
271 {
272 pos = safecat(buffer, bufsize, pos, " interlaced");
273 if (do_interlace)
274 pos = safecat(buffer, bufsize, pos, "(pngvalid)");
275 else
276 pos = safecat(buffer, bufsize, pos, "(libpng)");
277 }
278
279 if (w > 0 || h > 0)
280 {
281 pos = safecat(buffer, bufsize, pos, " ");
282 pos = safecatn(buffer, bufsize, pos, w);
283 pos = safecat(buffer, bufsize, pos, "x");
284 pos = safecatn(buffer, bufsize, pos, h);
285 }
286
287 return pos;
288}
289
290static size_t
291standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id)
292{
293 return standard_name(buffer, bufsize, pos, COL_FROM_ID(id),
294 DEPTH_FROM_ID(id), PALETTE_FROM_ID(id), INTERLACE_FROM_ID(id),
295 WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id));
296}
297
298/* Convenience API and defines to list valid formats. Note that 16 bit read and
299 * write support is required to do 16 bit read tests (we must be able to make a
300 * 16 bit image to test!)
301 */
302#ifdef PNG_WRITE_16BIT_SUPPORTED
303# define WRITE_BDHI 4
304# ifdef PNG_READ_16BIT_SUPPORTED
305# define READ_BDHI 4
306# define DO_16BIT
307# endif
308#else
309# define WRITE_BDHI 3
310#endif
311#ifndef DO_16BIT
312# define READ_BDHI 3
313#endif
314
315/* The following defines the number of different palettes to generate for
316 * each log bit depth of a colour type 3 standard image.
317 */
318#define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1 : 16)
319
320static int
321next_format(png_bytep colour_type, png_bytep bit_depth, int* palette_number)
322{
323 if (*bit_depth == 0)
324 {
325 *colour_type = 0, *bit_depth = 1, *palette_number = 0;
326 return 1;
327 }
328
329 if (*colour_type == 3)
330 {
331 /* Add multiple palettes for colour type 3. */
332 if (++*palette_number < PALETTE_COUNT(*bit_depth))
333 return 1;
334
335 *palette_number = 0;
336 }
337
338 *bit_depth = (png_byte)(*bit_depth << 1);
339
340 /* Palette images are restricted to 8 bit depth */
341 if (*bit_depth <= 8
342# ifdef DO_16BIT
343 || (*colour_type != 3 && *bit_depth <= 16)
344# endif
345 )
346 return 1;
347
348 /* Move to the next color type, or return 0 at the end. */
349 switch (*colour_type)
350 {
351 case 0:
352 *colour_type = 2;
353 *bit_depth = 8;
354 return 1;
355
356 case 2:
357 *colour_type = 3;
358 *bit_depth = 1;
359 return 1;
360
361 case 3:
362 *colour_type = 4;
363 *bit_depth = 8;
364 return 1;
365
366 case 4:
367 *colour_type = 6;
368 *bit_depth = 8;
369 return 1;
370
371 default:
372 return 0;
373 }
374}
375
376#ifdef PNG_READ_TRANSFORMS_SUPPORTED
377static unsigned int
378sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth,
379 png_uint_32 x, unsigned int sample_index)
380{
381 png_uint_32 bit_index, result;
382
383 /* Find a sample index for the desired sample: */
384 x *= bit_depth;
385 bit_index = x;
386
387 if ((colour_type & 1) == 0) /* !palette */
388 {
389 if (colour_type & 2)
390 bit_index *= 3;
391
392 if (colour_type & 4)
393 bit_index += x; /* Alpha channel */
394
395 /* Multiple channels; select one: */
396 if (colour_type & (2+4))
397 bit_index += sample_index * bit_depth;
398 }
399
400 /* Return the sample from the row as an integer. */
401 row += bit_index >> 3;
402 result = *row;
403
404 if (bit_depth == 8)
405 return result;
406
407 else if (bit_depth > 8)
408 return (result << 8) + *++row;
409
410 /* Less than 8 bits per sample. */
411 bit_index &= 7;
412 return (result >> (8-bit_index-bit_depth)) & ((1U<<bit_depth)-1);
413}
414#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
415
416/* Copy a single pixel, of a given size, from one buffer to another -
417 * while this is basically bit addressed there is an implicit assumption
418 * that pixels 8 or more bits in size are byte aligned and that pixels
419 * do not otherwise cross byte boundaries. (This is, so far as I know,
420 * universally true in bitmap computer graphics. [JCB 20101212])
421 *
422 * NOTE: The to and from buffers may be the same.
423 */
424static void
425pixel_copy(png_bytep toBuffer, png_uint_32 toIndex,
426 png_const_bytep fromBuffer, png_uint_32 fromIndex, unsigned int pixelSize)
427{
428 /* Assume we can multiply by 'size' without overflow because we are
429 * just working in a single buffer.
430 */
431 toIndex *= pixelSize;
432 fromIndex *= pixelSize;
433 if (pixelSize < 8) /* Sub-byte */
434 {
435 /* Mask to select the location of the copied pixel: */
436 unsigned int destMask = ((1U<<pixelSize)-1) << (8-pixelSize-(toIndex&7));
437 /* The following read the entire pixels and clears the extra: */
438 unsigned int destByte = toBuffer[toIndex >> 3] & ~destMask;
439 unsigned int sourceByte = fromBuffer[fromIndex >> 3];
440
441 /* Don't rely on << or >> supporting '0' here, just in case: */
442 fromIndex &= 7;
443 if (fromIndex > 0) sourceByte <<= fromIndex;
444 if ((toIndex & 7) > 0) sourceByte >>= toIndex & 7;
445
446 toBuffer[toIndex >> 3] = (png_byte)(destByte | (sourceByte & destMask));
447 }
448 else /* One or more bytes */
449 memmove(toBuffer+(toIndex>>3), fromBuffer+(fromIndex>>3), pixelSize>>3);
450}
451
452/* Copy a complete row of pixels, taking into account potential partial
453 * bytes at the end.
454 */
455static void
456row_copy(png_bytep toBuffer, png_const_bytep fromBuffer, unsigned int bitWidth)
457{
458 memcpy(toBuffer, fromBuffer, bitWidth >> 3);
459
460 if ((bitWidth & 7) != 0)
461 {
462 unsigned int mask;
463
464 toBuffer += bitWidth >> 3;
465 fromBuffer += bitWidth >> 3;
466 /* The remaining bits are in the top of the byte, the mask is the bits to
467 * retain.
468 */
469 mask = 0xff >> (bitWidth & 7);
470 *toBuffer = (png_byte)((*toBuffer & mask) | (*fromBuffer & ~mask));
471 }
472}
473
474/* Compare pixels - they are assumed to start at the first byte in the
475 * given buffers.
476 */
477static int
478pixel_cmp(png_const_bytep pa, png_const_bytep pb, png_uint_32 bit_width)
479{
480#if PNG_LIBPNG_VER < 10506
481 if (memcmp(pa, pb, bit_width>>3) == 0)
482 {
483 png_uint_32 p;
484
485 if ((bit_width & 7) == 0) return 0;
486
487 /* Ok, any differences? */
488 p = pa[bit_width >> 3];
489 p ^= pb[bit_width >> 3];
490
491 if (p == 0) return 0;
492
493 /* There are, but they may not be significant, remove the bits
494 * after the end (the low order bits in PNG.)
495 */
496 bit_width &= 7;
497 p >>= 8-bit_width;
498
499 if (p == 0) return 0;
500 }
501#else
502 /* From libpng-1.5.6 the overwrite should be fixed, so compare the trailing
503 * bits too:
504 */
505 if (memcmp(pa, pb, (bit_width+7)>>3) == 0)
506 return 0;
507#endif
508
509 /* Return the index of the changed byte. */
510 {
511 png_uint_32 where = 0;
512
513 while (pa[where] == pb[where]) ++where;
514 return 1+where;
515 }
516}
517
518/*************************** BASIC PNG FILE WRITING ***************************/
519/* A png_store takes data from the sequential writer or provides data
520 * to the sequential reader. It can also store the result of a PNG
521 * write for later retrieval.
522 */
523#define STORE_BUFFER_SIZE 500 /* arbitrary */
524typedef struct png_store_buffer
525{
526 struct png_store_buffer* prev; /* NOTE: stored in reverse order */
527 png_byte buffer[STORE_BUFFER_SIZE];
528} png_store_buffer;
529
530#define FILE_NAME_SIZE 64
531
532typedef struct store_palette_entry /* record of a single palette entry */
533{
534 png_byte red;
535 png_byte green;
536 png_byte blue;
537 png_byte alpha;
538} store_palette_entry, store_palette[256];
539
540typedef struct png_store_file
541{
542 struct png_store_file* next; /* as many as you like... */
543 char name[FILE_NAME_SIZE];
544 png_uint_32 id; /* must be correct (see FILEID) */
545 png_size_t datacount; /* In this (the last) buffer */
546 png_store_buffer data; /* Last buffer in file */
547 int npalette; /* Number of entries in palette */
548 store_palette_entry* palette; /* May be NULL */
549} png_store_file;
550
551/* The following is a pool of memory allocated by a single libpng read or write
552 * operation.
553 */
554typedef struct store_pool
555{
556 struct png_store *store; /* Back pointer */
557 struct store_memory *list; /* List of allocated memory */
558 png_byte mark[4]; /* Before and after data */
559
560 /* Statistics for this run. */
561 png_alloc_size_t max; /* Maximum single allocation */
562 png_alloc_size_t current; /* Current allocation */
563 png_alloc_size_t limit; /* Highest current allocation */
564 png_alloc_size_t total; /* Total allocation */
565
566 /* Overall statistics (retained across successive runs). */
567 png_alloc_size_t max_max;
568 png_alloc_size_t max_limit;
569 png_alloc_size_t max_total;
570} store_pool;
571
572typedef struct png_store
573{
574 /* For cexcept.h exception handling - simply store one of these;
575 * the context is a self pointer but it may point to a different
576 * png_store (in fact it never does in this program.)
577 */
578 struct exception_context
579 exception_context;
580
581 unsigned int verbose :1;
582 unsigned int treat_warnings_as_errors :1;
583 unsigned int expect_error :1;
584 unsigned int expect_warning :1;
585 unsigned int saw_warning :1;
586 unsigned int speed :1;
587 unsigned int progressive :1; /* use progressive read */
588 unsigned int validated :1; /* used as a temporary flag */
589 int nerrors;
590 int nwarnings;
591 char test[128]; /* Name of test */
592 char error[256];
593
594 /* Read fields */
595 png_structp pread; /* Used to read a saved file */
596 png_infop piread;
597 png_store_file* current; /* Set when reading */
598 png_store_buffer* next; /* Set when reading */
599 png_size_t readpos; /* Position in *next */
600 png_byte* image; /* Buffer for reading interlaced images */
601 png_size_t cb_image; /* Size of this buffer */
602 png_size_t cb_row; /* Row size of the image(s) */
603 png_uint_32 image_h; /* Number of rows in a single image */
604 store_pool read_memory_pool;
605
606 /* Write fields */
607 png_store_file* saved;
608 png_structp pwrite; /* Used when writing a new file */
609 png_infop piwrite;
610 png_size_t writepos; /* Position in .new */
611 char wname[FILE_NAME_SIZE];
612 png_store_buffer new; /* The end of the new PNG file being written. */
613 store_pool write_memory_pool;
614 store_palette_entry* palette;
615 int npalette;
616} png_store;
617
618/* Initialization and cleanup */
619static void
620store_pool_mark(png_bytep mark)
621{
622 static png_uint_32 store_seed[2] = { 0x12345678, 1};
623
624 make_four_random_bytes(store_seed, mark);
625}
626
627/* Use this for random 32 bit values; this function makes sure the result is
628 * non-zero.
629 */
630static png_uint_32
631random_32(void)
632{
633
634 for(;;)
635 {
636 png_byte mark[4];
637 png_uint_32 result;
638
639 store_pool_mark(mark);
640 result = png_get_uint_32(mark);
641
642 if (result != 0)
643 return result;
644 }
645}
646
647static void
648store_pool_init(png_store *ps, store_pool *pool)
649{
650 memset(pool, 0, sizeof *pool);
651
652 pool->store = ps;
653 pool->list = NULL;
654 pool->max = pool->current = pool->limit = pool->total = 0;
655 pool->max_max = pool->max_limit = pool->max_total = 0;
656 store_pool_mark(pool->mark);
657}
658
659static void
660store_init(png_store* ps)
661{
662 memset(ps, 0, sizeof *ps);
663 init_exception_context(&ps->exception_context);
664 store_pool_init(ps, &ps->read_memory_pool);
665 store_pool_init(ps, &ps->write_memory_pool);
666 ps->verbose = 0;
667 ps->treat_warnings_as_errors = 0;
668 ps->expect_error = 0;
669 ps->expect_warning = 0;
670 ps->saw_warning = 0;
671 ps->speed = 0;
672 ps->progressive = 0;
673 ps->validated = 0;
674 ps->nerrors = ps->nwarnings = 0;
675 ps->pread = NULL;
676 ps->piread = NULL;
677 ps->saved = ps->current = NULL;
678 ps->next = NULL;
679 ps->readpos = 0;
680 ps->image = NULL;
681 ps->cb_image = 0;
682 ps->cb_row = 0;
683 ps->image_h = 0;
684 ps->pwrite = NULL;
685 ps->piwrite = NULL;
686 ps->writepos = 0;
687 ps->new.prev = NULL;
688 ps->palette = NULL;
689 ps->npalette = 0;
690}
691
692static void
693store_freebuffer(png_store_buffer* psb)
694{
695 if (psb->prev)
696 {
697 store_freebuffer(psb->prev);
698 free(psb->prev);
699 psb->prev = NULL;
700 }
701}
702
703static void
704store_freenew(png_store *ps)
705{
706 store_freebuffer(&ps->new);
707 ps->writepos = 0;
708 if (ps->palette != NULL)
709 {
710 free(ps->palette);
711 ps->palette = NULL;
712 ps->npalette = 0;
713 }
714}
715
716static void
717store_storenew(png_store *ps)
718{
719 png_store_buffer *pb;
720
721 if (ps->writepos != STORE_BUFFER_SIZE)
722 png_error(ps->pwrite, "invalid store call");
723
724 pb = voidcast(png_store_buffer*, malloc(sizeof *pb));
725
726 if (pb == NULL)
727 png_error(ps->pwrite, "store new: OOM");
728
729 *pb = ps->new;
730 ps->new.prev = pb;
731 ps->writepos = 0;
732}
733
734static void
735store_freefile(png_store_file **ppf)
736{
737 if (*ppf != NULL)
738 {
739 store_freefile(&(*ppf)->next);
740
741 store_freebuffer(&(*ppf)->data);
742 (*ppf)->datacount = 0;
743 if ((*ppf)->palette != NULL)
744 {
745 free((*ppf)->palette);
746 (*ppf)->palette = NULL;
747 (*ppf)->npalette = 0;
748 }
749 free(*ppf);
750 *ppf = NULL;
751 }
752}
753
754/* Main interface to file storeage, after writing a new PNG file (see the API
755 * below) call store_storefile to store the result with the given name and id.
756 */
757static void
758store_storefile(png_store *ps, png_uint_32 id)
759{
760 png_store_file *pf = voidcast(png_store_file*, malloc(sizeof *pf));
761 if (pf == NULL)
762 png_error(ps->pwrite, "storefile: OOM");
763 safecat(pf->name, sizeof pf->name, 0, ps->wname);
764 pf->id = id;
765 pf->data = ps->new;
766 pf->datacount = ps->writepos;
767 ps->new.prev = NULL;
768 ps->writepos = 0;
769 pf->palette = ps->palette;
770 pf->npalette = ps->npalette;
771 ps->palette = 0;
772 ps->npalette = 0;
773
774 /* And save it. */
775 pf->next = ps->saved;
776 ps->saved = pf;
777}
778
779/* Generate an error message (in the given buffer) */
780static size_t
781store_message(png_store *ps, png_structp pp, char *buffer, size_t bufsize,
782 size_t pos, PNG_CONST char *msg)
783{
784 if (pp != NULL && pp == ps->pread)
785 {
786 /* Reading a file */
787 pos = safecat(buffer, bufsize, pos, "read: ");
788
789 if (ps->current != NULL)
790 {
791 pos = safecat(buffer, bufsize, pos, ps->current->name);
792 pos = safecat(buffer, bufsize, pos, sep);
793 }
794 }
795
796 else if (pp != NULL && pp == ps->pwrite)
797 {
798 /* Writing a file */
799 pos = safecat(buffer, bufsize, pos, "write: ");
800 pos = safecat(buffer, bufsize, pos, ps->wname);
801 pos = safecat(buffer, bufsize, pos, sep);
802 }
803
804 else
805 {
806 /* Neither reading nor writing (or a memory error in struct delete) */
807 pos = safecat(buffer, bufsize, pos, "pngvalid: ");
808 }
809
810 if (ps->test[0] != 0)
811 {
812 pos = safecat(buffer, bufsize, pos, ps->test);
813 pos = safecat(buffer, bufsize, pos, sep);
814 }
815 pos = safecat(buffer, bufsize, pos, msg);
816 return pos;
817}
818
819/* Verbose output to the error stream: */
820static void
821store_verbose(png_store *ps, png_structp pp, png_const_charp prefix,
822 png_const_charp message)
823{
824 char buffer[512];
825
826 if (prefix)
827 fputs(prefix, stderr);
828
829 (void)store_message(ps, pp, buffer, sizeof buffer, 0, message);
830 fputs(buffer, stderr);
831 fputc('\n', stderr);
832}
833
834/* Log an error or warning - the relevant count is always incremented. */
835static void
836store_log(png_store* ps, png_structp pp, png_const_charp message, int is_error)
837{
838 /* The warning is copied to the error buffer if there are no errors and it is
839 * the first warning. The error is copied to the error buffer if it is the
840 * first error (overwriting any prior warnings).
841 */
842 if (is_error ? (ps->nerrors)++ == 0 :
843 (ps->nwarnings)++ == 0 && ps->nerrors == 0)
844 store_message(ps, pp, ps->error, sizeof ps->error, 0, message);
845
846 if (ps->verbose)
847 store_verbose(ps, pp, is_error ? "error: " : "warning: ", message);
848}
849
850/* Internal error function, called with a png_store but no libpng stuff. */
851static void
852internal_error(png_store *ps, png_const_charp message)
853{
854 store_log(ps, NULL, message, 1 /* error */);
855
856 /* And finally throw an exception. */
857 {
858 struct exception_context *the_exception_context = &ps->exception_context;
859 Throw ps;
860 }
861}
862
863/* Functions to use as PNG callbacks. */
864static void
865store_error(png_structp pp, png_const_charp message) /* PNG_NORETURN */
866{
867 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp));
868
869 if (!ps->expect_error)
870 store_log(ps, pp, message, 1 /* error */);
871
872 /* And finally throw an exception. */
873 {
874 struct exception_context *the_exception_context = &ps->exception_context;
875 Throw ps;
876 }
877}
878
879static void
880store_warning(png_structp pp, png_const_charp message)
881{
882 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp));
883
884 if (!ps->expect_warning)
885 store_log(ps, pp, message, 0 /* warning */);
886 else
887 ps->saw_warning = 1;
888}
889
890/* These somewhat odd functions are used when reading an image to ensure that
891 * the buffer is big enough, the png_structp is for errors.
892 */
893/* Return a single row from the correct image. */
894static png_bytep
895store_image_row(PNG_CONST png_store* ps, png_structp pp, int nImage,
896 png_uint_32 y)
897{
898 png_size_t coffset = (nImage * ps->image_h + y) * (ps->cb_row + 5) + 2;
899
900 if (ps->image == NULL)
901 png_error(pp, "no allocated image");
902
903 if (coffset + ps->cb_row + 3 > ps->cb_image)
904 png_error(pp, "image too small");
905
906 return ps->image + coffset;
907}
908
909static void
910store_image_free(png_store *ps, png_structp pp)
911{
912 if (ps->image != NULL)
913 {
914 png_bytep image = ps->image;
915
916 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe)
917 {
918 if (pp != NULL)
919 png_error(pp, "png_store image overwrite (1)");
920 else
921 store_log(ps, NULL, "png_store image overwrite (2)", 1);
922 }
923
924 ps->image = NULL;
925 ps->cb_image = 0;
926 --image;
927 free(image);
928 }
929}
930
931static void
932store_ensure_image(png_store *ps, png_structp pp, int nImages, png_size_t cbRow,
933 png_uint_32 cRows)
934{
935 png_size_t cb = nImages * cRows * (cbRow + 5);
936
937 if (ps->cb_image < cb)
938 {
939 png_bytep image;
940
941 store_image_free(ps, pp);
942
943 /* The buffer is deliberately mis-aligned. */
944 image = voidcast(png_bytep, malloc(cb+2));
945 if (image == NULL)
946 {
947 /* Called from the startup - ignore the error for the moment. */
948 if (pp == NULL)
949 return;
950
951 png_error(pp, "OOM allocating image buffer");
952 }
953
954 /* These magic tags are used to detect overwrites above. */
955 ++image;
956 image[-1] = 0xed;
957 image[cb] = 0xfe;
958
959 ps->image = image;
960 ps->cb_image = cb;
961 }
962
963 /* We have an adequate sized image; lay out the rows. There are 2 bytes at
964 * the start and three at the end of each (this ensures that the row
965 * alignment starts out odd - 2+1 and changes for larger images on each row.)
966 */
967 ps->cb_row = cbRow;
968 ps->image_h = cRows;
969
970 /* For error checking, the whole buffer is set to 10110010 (0xb2 - 178).
971 * This deliberately doesn't match the bits in the size test image which are
972 * outside the image; these are set to 0xff (all 1). To make the row
973 * comparison work in the 'size' test case the size rows are pre-initialized
974 * to the same value prior to calling 'standard_row'.
975 */
976 memset(ps->image, 178, cb);
977
978 /* Then put in the marks. */
979 while (--nImages >= 0)
980 {
981 png_uint_32 y;
982
983 for (y=0; y<cRows; ++y)
984 {
985 png_bytep row = store_image_row(ps, pp, nImages, y);
986
987 /* The markers: */
988 row[-2] = 190;
989 row[-1] = 239;
990 row[cbRow] = 222;
991 row[cbRow+1] = 173;
992 row[cbRow+2] = 17;
993 }
994 }
995}
996
997static void
998store_image_check(PNG_CONST png_store* ps, png_structp pp, int iImage)
999{
1000 png_const_bytep image = ps->image;
1001
1002 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe)
1003 png_error(pp, "image overwrite");
1004 else
1005 {
1006 png_size_t cbRow = ps->cb_row;
1007 png_uint_32 rows = ps->image_h;
1008
1009 image += iImage * (cbRow+5) * ps->image_h;
1010
1011 image += 2; /* skip image first row markers */
1012
1013 while (rows-- > 0)
1014 {
1015 if (image[-2] != 190 || image[-1] != 239)
1016 png_error(pp, "row start overwritten");
1017
1018 if (image[cbRow] != 222 || image[cbRow+1] != 173 ||
1019 image[cbRow+2] != 17)
1020 png_error(pp, "row end overwritten");
1021
1022 image += cbRow+5;
1023 }
1024 }
1025}
1026
1027static void
1028store_write(png_structp pp, png_bytep pb, png_size_t st)
1029{
1030 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp));
1031
1032 if (ps->pwrite != pp)
1033 png_error(pp, "store state damaged");
1034
1035 while (st > 0)
1036 {
1037 size_t cb;
1038
1039 if (ps->writepos >= STORE_BUFFER_SIZE)
1040 store_storenew(ps);
1041
1042 cb = st;
1043
1044 if (cb > STORE_BUFFER_SIZE - ps->writepos)
1045 cb = STORE_BUFFER_SIZE - ps->writepos;
1046
1047 memcpy(ps->new.buffer + ps->writepos, pb, cb);
1048 pb += cb;
1049 st -= cb;
1050 ps->writepos += cb;
1051 }
1052}
1053
1054static void
1055store_flush(png_structp pp)
1056{
1057 UNUSED(pp) /*DOES NOTHING*/
1058}
1059
1060static size_t
1061store_read_buffer_size(png_store *ps)
1062{
1063 /* Return the bytes available for read in the current buffer. */
1064 if (ps->next != &ps->current->data)
1065 return STORE_BUFFER_SIZE;
1066
1067 return ps->current->datacount;
1068}
1069
1070#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1071/* Return total bytes available for read. */
1072static size_t
1073store_read_buffer_avail(png_store *ps)
1074{
1075 if (ps->current != NULL && ps->next != NULL)
1076 {
1077 png_store_buffer *next = &ps->current->data;
1078 size_t cbAvail = ps->current->datacount;
1079
1080 while (next != ps->next && next != NULL)
1081 {
1082 next = next->prev;
1083 cbAvail += STORE_BUFFER_SIZE;
1084 }
1085
1086 if (next != ps->next)
1087 png_error(ps->pread, "buffer read error");
1088
1089 if (cbAvail > ps->readpos)
1090 return cbAvail - ps->readpos;
1091 }
1092
1093 return 0;
1094}
1095#endif
1096
1097static int
1098store_read_buffer_next(png_store *ps)
1099{
1100 png_store_buffer *pbOld = ps->next;
1101 png_store_buffer *pbNew = &ps->current->data;
1102 if (pbOld != pbNew)
1103 {
1104 while (pbNew != NULL && pbNew->prev != pbOld)
1105 pbNew = pbNew->prev;
1106
1107 if (pbNew != NULL)
1108 {
1109 ps->next = pbNew;
1110 ps->readpos = 0;
1111 return 1;
1112 }
1113
1114 png_error(ps->pread, "buffer lost");
1115 }
1116
1117 return 0; /* EOF or error */
1118}
1119
1120/* Need separate implementation and callback to allow use of the same code
1121 * during progressive read, where the io_ptr is set internally by libpng.
1122 */
1123static void
1124store_read_imp(png_store *ps, png_bytep pb, png_size_t st)
1125{
1126 if (ps->current == NULL || ps->next == NULL)
1127 png_error(ps->pread, "store state damaged");
1128
1129 while (st > 0)
1130 {
1131 size_t cbAvail = store_read_buffer_size(ps) - ps->readpos;
1132
1133 if (cbAvail > 0)
1134 {
1135 if (cbAvail > st) cbAvail = st;
1136 memcpy(pb, ps->next->buffer + ps->readpos, cbAvail);
1137 st -= cbAvail;
1138 pb += cbAvail;
1139 ps->readpos += cbAvail;
1140 }
1141
1142 else if (!store_read_buffer_next(ps))
1143 png_error(ps->pread, "read beyond end of file");
1144 }
1145}
1146
1147static void
1148store_read(png_structp pp, png_bytep pb, png_size_t st)
1149{
1150 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp));
1151
1152 if (ps == NULL || ps->pread != pp)
1153 png_error(pp, "bad store read call");
1154
1155 store_read_imp(ps, pb, st);
1156}
1157
1158static void
1159store_progressive_read(png_store *ps, png_structp pp, png_infop pi)
1160{
1161 /* Notice that a call to store_read will cause this function to fail because
1162 * readpos will be set.
1163 */
1164 if (ps->pread != pp || ps->current == NULL || ps->next == NULL)
1165 png_error(pp, "store state damaged (progressive)");
1166
1167 do
1168 {
1169 if (ps->readpos != 0)
1170 png_error(pp, "store_read called during progressive read");
1171
1172 png_process_data(pp, pi, ps->next->buffer, store_read_buffer_size(ps));
1173 }
1174 while (store_read_buffer_next(ps));
1175}
1176
1177/* The caller must fill this in: */
1178static store_palette_entry *
1179store_write_palette(png_store *ps, int npalette)
1180{
1181 if (ps->pwrite == NULL)
1182 store_log(ps, NULL, "attempt to write palette without write stream", 1);
1183
1184 if (ps->palette != NULL)
1185 png_error(ps->pwrite, "multiple store_write_palette calls");
1186
1187 /* This function can only return NULL if called with '0'! */
1188 if (npalette > 0)
1189 {
1190 ps->palette = voidcast(store_palette_entry*, malloc(npalette *
1191 sizeof *ps->palette));
1192
1193 if (ps->palette == NULL)
1194 png_error(ps->pwrite, "store new palette: OOM");
1195
1196 ps->npalette = npalette;
1197 }
1198
1199 return ps->palette;
1200}
1201
1202static store_palette_entry *
1203store_current_palette(png_store *ps, int *npalette)
1204{
1205 /* This is an internal error (the call has been made outside a read
1206 * operation.)
1207 */
1208 if (ps->current == NULL)
1209 store_log(ps, ps->pread, "no current stream for palette", 1);
1210
1211 /* The result may be null if there is no palette. */
1212 *npalette = ps->current->npalette;
1213 return ps->current->palette;
1214}
1215
1216/***************************** MEMORY MANAGEMENT*** ***************************/
1217/* A store_memory is simply the header for an allocated block of memory. The
1218 * pointer returned to libpng is just after the end of the header block, the
1219 * allocated memory is followed by a second copy of the 'mark'.
1220 */
1221typedef struct store_memory
1222{
1223 store_pool *pool; /* Originating pool */
1224 struct store_memory *next; /* Singly linked list */
1225 png_alloc_size_t size; /* Size of memory allocated */
1226 png_byte mark[4]; /* ID marker */
1227} store_memory;
1228
1229/* Handle a fatal error in memory allocation. This calls png_error if the
1230 * libpng struct is non-NULL, else it outputs a message and returns. This means
1231 * that a memory problem while libpng is running will abort (png_error) the
1232 * handling of particular file while one in cleanup (after the destroy of the
1233 * struct has returned) will simply keep going and free (or attempt to free)
1234 * all the memory.
1235 */
1236static void
1237store_pool_error(png_store *ps, png_structp pp, PNG_CONST char *msg)
1238{
1239 if (pp != NULL)
1240 png_error(pp, msg);
1241
1242 /* Else we have to do it ourselves. png_error eventually calls store_log,
1243 * above. store_log accepts a NULL png_structp - it just changes what gets
1244 * output by store_message.
1245 */
1246 store_log(ps, pp, msg, 1 /* error */);
1247}
1248
1249static void
1250store_memory_free(png_structp pp, store_pool *pool, store_memory *memory)
1251{
1252 /* Note that pp may be NULL (see store_pool_delete below), the caller has
1253 * found 'memory' in pool->list *and* unlinked this entry, so this is a valid
1254 * pointer (for sure), but the contents may have been trashed.
1255 */
1256 if (memory->pool != pool)
1257 store_pool_error(pool->store, pp, "memory corrupted (pool)");
1258
1259 else if (memcmp(memory->mark, pool->mark, sizeof memory->mark) != 0)
1260 store_pool_error(pool->store, pp, "memory corrupted (start)");
1261
1262 /* It should be safe to read the size field now. */
1263 else
1264 {
1265 png_alloc_size_t cb = memory->size;
1266
1267 if (cb > pool->max)
1268 store_pool_error(pool->store, pp, "memory corrupted (size)");
1269
1270 else if (memcmp((png_bytep)(memory+1)+cb, pool->mark, sizeof pool->mark)
1271 != 0)
1272 store_pool_error(pool->store, pp, "memory corrupted (end)");
1273
1274 /* Finally give the library a chance to find problems too: */
1275 else
1276 {
1277 pool->current -= cb;
1278 free(memory);
1279 }
1280 }
1281}
1282
1283static void
1284store_pool_delete(png_store *ps, store_pool *pool)
1285{
1286 if (pool->list != NULL)
1287 {
1288 fprintf(stderr, "%s: %s %s: memory lost (list follows):\n", ps->test,
1289 pool == &ps->read_memory_pool ? "read" : "write",
1290 pool == &ps->read_memory_pool ? (ps->current != NULL ?
1291 ps->current->name : "unknown file") : ps->wname);
1292 ++ps->nerrors;
1293
1294 do
1295 {
1296 store_memory *next = pool->list;
1297 pool->list = next->next;
1298 next->next = NULL;
1299
1300 fprintf(stderr, "\t%lu bytes @ %p\n",
1301 (unsigned long)next->size, (PNG_CONST void*)(next+1));
1302 /* The NULL means this will always return, even if the memory is
1303 * corrupted.
1304 */
1305 store_memory_free(NULL, pool, next);
1306 }
1307 while (pool->list != NULL);
1308 }
1309
1310 /* And reset the other fields too for the next time. */
1311 if (pool->max > pool->max_max) pool->max_max = pool->max;
1312 pool->max = 0;
1313 if (pool->current != 0) /* unexpected internal error */
1314 fprintf(stderr, "%s: %s %s: memory counter mismatch (internal error)\n",
1315 ps->test, pool == &ps->read_memory_pool ? "read" : "write",
1316 pool == &ps->read_memory_pool ? (ps->current != NULL ?
1317 ps->current->name : "unknown file") : ps->wname);
1318 pool->current = 0;
1319
1320 if (pool->limit > pool->max_limit)
1321 pool->max_limit = pool->limit;
1322
1323 pool->limit = 0;
1324
1325 if (pool->total > pool->max_total)
1326 pool->max_total = pool->total;
1327
1328 pool->total = 0;
1329
1330 /* Get a new mark too. */
1331 store_pool_mark(pool->mark);
1332}
1333
1334/* The memory callbacks: */
1335static png_voidp
1336store_malloc(png_structp pp, png_alloc_size_t cb)
1337{
1338 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp));
1339 store_memory *new = voidcast(store_memory*, malloc(cb + (sizeof *new) +
1340 (sizeof pool->mark)));
1341
1342 if (new != NULL)
1343 {
1344 if (cb > pool->max)
1345 pool->max = cb;
1346
1347 pool->current += cb;
1348
1349 if (pool->current > pool->limit)
1350 pool->limit = pool->current;
1351
1352 pool->total += cb;
1353
1354 new->size = cb;
1355 memcpy(new->mark, pool->mark, sizeof new->mark);
1356 memcpy((png_byte*)(new+1) + cb, pool->mark, sizeof pool->mark);
1357 new->pool = pool;
1358 new->next = pool->list;
1359 pool->list = new;
1360 ++new;
1361 }
1362
1363 else
1364 {
1365 /* NOTE: the PNG user malloc function cannot use the png_ptr it is passed
1366 * other than to retrieve the allocation pointer! libpng calls the
1367 * store_malloc callback in two basic cases:
1368 *
1369 * 1) From png_malloc; png_malloc will do a png_error itself if NULL is
1370 * returned.
1371 * 2) From png_struct or png_info structure creation; png_malloc is
1372 * to return so cleanup can be performed.
1373 *
1374 * To handle this store_malloc can log a message, but can't do anything
1375 * else.
1376 */
1377 store_log(pool->store, pp, "out of memory", 1 /* is_error */);
1378 }
1379
1380 return new;
1381}
1382
1383static void
1384store_free(png_structp pp, png_voidp memory)
1385{
1386 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp));
1387 store_memory *this = voidcast(store_memory*, memory), **test;
1388
1389 /* Because libpng calls store_free with a dummy png_struct when deleting
1390 * png_struct or png_info via png_destroy_struct_2 it is necessary to check
1391 * the passed in png_structp to ensure it is valid, and not pass it to
1392 * png_error if it is not.
1393 */
1394 if (pp != pool->store->pread && pp != pool->store->pwrite)
1395 pp = NULL;
1396
1397 /* First check that this 'memory' really is valid memory - it must be in the
1398 * pool list. If it is, use the shared memory_free function to free it.
1399 */
1400 --this;
1401 for (test = &pool->list; *test != this; test = &(*test)->next)
1402 {
1403 if (*test == NULL)
1404 {
1405 store_pool_error(pool->store, pp, "bad pointer to free");
1406 return;
1407 }
1408 }
1409
1410 /* Unlink this entry, *test == this. */
1411 *test = this->next;
1412 this->next = NULL;
1413 store_memory_free(pp, pool, this);
1414}
1415
1416/* Setup functions. */
1417/* Cleanup when aborting a write or after storing the new file. */
1418static void
1419store_write_reset(png_store *ps)
1420{
1421 if (ps->pwrite != NULL)
1422 {
1423 anon_context(ps);
1424
1425 Try
1426 png_destroy_write_struct(&ps->pwrite, &ps->piwrite);
1427
1428 Catch_anonymous
1429 {
1430 /* memory corruption: continue. */
1431 }
1432
1433 ps->pwrite = NULL;
1434 ps->piwrite = NULL;
1435 }
1436
1437 /* And make sure that all the memory has been freed - this will output
1438 * spurious errors in the case of memory corruption above, but this is safe.
1439 */
1440 store_pool_delete(ps, &ps->write_memory_pool);
1441
1442 store_freenew(ps);
1443}
1444
1445/* The following is the main write function, it returns a png_struct and,
1446 * optionally, a png_info suitable for writiing a new PNG file. Use
1447 * store_storefile above to record this file after it has been written. The
1448 * returned libpng structures as destroyed by store_write_reset above.
1449 */
1450static png_structp
1451set_store_for_write(png_store *ps, png_infopp ppi,
1452 PNG_CONST char * volatile name)
1453{
1454 anon_context(ps);
1455
1456 Try
1457 {
1458 if (ps->pwrite != NULL)
1459 png_error(ps->pwrite, "write store already in use");
1460
1461 store_write_reset(ps);
1462 safecat(ps->wname, sizeof ps->wname, 0, name);
1463
1464 /* Don't do the slow memory checks if doing a speed test. */
1465 if (ps->speed)
1466 ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1467 ps, store_error, store_warning);
1468
1469 else
1470 ps->pwrite = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
1471 ps, store_error, store_warning, &ps->write_memory_pool,
1472 store_malloc, store_free);
1473
1474 png_set_write_fn(ps->pwrite, ps, store_write, store_flush);
1475
1476 if (ppi != NULL)
1477 *ppi = ps->piwrite = png_create_info_struct(ps->pwrite);
1478 }
1479
1480 Catch_anonymous
1481 return NULL;
1482
1483 return ps->pwrite;
1484}
1485
1486/* Cleanup when finished reading (either due to error or in the success case).
1487 */
1488static void
1489store_read_reset(png_store *ps)
1490{
1491 if (ps->pread != NULL)
1492 {
1493 anon_context(ps);
1494
1495 Try
1496 png_destroy_read_struct(&ps->pread, &ps->piread, NULL);
1497
1498 Catch_anonymous
1499 {
1500 /* error already output: continue */
1501 }
1502
1503 ps->pread = NULL;
1504 ps->piread = NULL;
1505 }
1506
1507 /* Always do this to be safe. */
1508 store_pool_delete(ps, &ps->read_memory_pool);
1509
1510 ps->current = NULL;
1511 ps->next = NULL;
1512 ps->readpos = 0;
1513 ps->validated = 0;
1514}
1515
1516static void
1517store_read_set(png_store *ps, png_uint_32 id)
1518{
1519 png_store_file *pf = ps->saved;
1520
1521 while (pf != NULL)
1522 {
1523 if (pf->id == id)
1524 {
1525 ps->current = pf;
1526 ps->next = NULL;
1527 store_read_buffer_next(ps);
1528 return;
1529 }
1530
1531 pf = pf->next;
1532 }
1533
1534 {
1535 size_t pos;
1536 char msg[FILE_NAME_SIZE+64];
1537
1538 pos = standard_name_from_id(msg, sizeof msg, 0, id);
1539 pos = safecat(msg, sizeof msg, pos, ": file not found");
1540 png_error(ps->pread, msg);
1541 }
1542}
1543
1544/* The main interface for reading a saved file - pass the id number of the file
1545 * to retrieve. Ids must be unique or the earlier file will be hidden. The API
1546 * returns a png_struct and, optionally, a png_info. Both of these will be
1547 * destroyed by store_read_reset above.
1548 */
1549static png_structp
1550set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id,
1551 PNG_CONST char *name)
1552{
1553 /* Set the name for png_error */
1554 safecat(ps->test, sizeof ps->test, 0, name);
1555
1556 if (ps->pread != NULL)
1557 png_error(ps->pread, "read store already in use");
1558
1559 store_read_reset(ps);
1560
1561 /* Both the create APIs can return NULL if used in their default mode
1562 * (because there is no other way of handling an error because the jmp_buf
1563 * by default is stored in png_struct and that has not been allocated!)
1564 * However, given that store_error works correctly in these circumstances
1565 * we don't ever expect NULL in this program.
1566 */
1567 if (ps->speed)
1568 ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps,
1569 store_error, store_warning);
1570
1571 else
1572 ps->pread = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, ps,
1573 store_error, store_warning, &ps->read_memory_pool, store_malloc,
1574 store_free);
1575
1576 if (ps->pread == NULL)
1577 {
1578 struct exception_context *the_exception_context = &ps->exception_context;
1579
1580 store_log(ps, NULL, "png_create_read_struct returned NULL (unexpected)",
1581 1 /*error*/);
1582
1583 Throw ps;
1584 }
1585
1586 store_read_set(ps, id);
1587
1588 if (ppi != NULL)
1589 *ppi = ps->piread = png_create_info_struct(ps->pread);
1590
1591 return ps->pread;
1592}
1593
1594/* The overall cleanup of a store simply calls the above then removes all the
1595 * saved files. This does not delete the store itself.
1596 */
1597static void
1598store_delete(png_store *ps)
1599{
1600 store_write_reset(ps);
1601 store_read_reset(ps);
1602 store_freefile(&ps->saved);
1603 store_image_free(ps, NULL);
1604}
1605
1606/*********************** PNG FILE MODIFICATION ON READ ************************/
1607/* Files may be modified on read. The following structure contains a complete
1608 * png_store together with extra members to handle modification and a special
1609 * read callback for libpng. To use this the 'modifications' field must be set
1610 * to a list of png_modification structures that actually perform the
1611 * modification, otherwise a png_modifier is functionally equivalent to a
1612 * png_store. There is a special read function, set_modifier_for_read, which
1613 * replaces set_store_for_read.
1614 */
1615typedef enum modifier_state
1616{
1617 modifier_start, /* Initial value */
1618 modifier_signature, /* Have a signature */
1619 modifier_IHDR /* Have an IHDR */
1620} modifier_state;
1621
1622typedef struct CIE_color
1623{
1624 /* A single CIE tristimulus value, representing the unique response of a
1625 * standard observer to a variety of light spectra. The observer recognizes
1626 * all spectra that produce this response as the same color, therefore this
1627 * is effectively a description of a color.
1628 */
1629 double X, Y, Z;
1630} CIE_color;
1631
1632static double
1633chromaticity_x(CIE_color c)
1634{
1635 return c.X / (c.X + c.Y + c.Z);
1636}
1637
1638static double
1639chromaticity_y(CIE_color c)
1640{
1641 return c.Y / (c.X + c.Y + c.Z);
1642}
1643
1644typedef struct color_encoding
1645{
1646 /* A description of an (R,G,B) encoding of color (as defined above); this
1647 * includes the actual colors of the (R,G,B) triples (1,0,0), (0,1,0) and
1648 * (0,0,1) plus an encoding value that is used to encode the linear
1649 * components R, G and B to give the actual values R^gamma, G^gamma and
1650 * B^gamma that are stored.
1651 */
1652 double gamma; /* Encoding (file) gamma of space */
1653 CIE_color red, green, blue; /* End points */
1654} color_encoding;
1655
1656static CIE_color
1657white_point(PNG_CONST color_encoding *encoding)
1658{
1659 CIE_color white;
1660
1661 white.X = encoding->red.X + encoding->green.X + encoding->blue.X;
1662 white.Y = encoding->red.Y + encoding->green.Y + encoding->blue.Y;
1663 white.Z = encoding->red.Z + encoding->green.Z + encoding->blue.Z;
1664
1665 return white;
1666}
1667
1668static void
1669normalize_color_encoding(color_encoding *encoding)
1670{
1671 PNG_CONST double whiteY = encoding->red.Y + encoding->green.Y +
1672 encoding->blue.Y;
1673
1674 if (whiteY != 1)
1675 {
1676 encoding->red.X /= whiteY;
1677 encoding->red.Y /= whiteY;
1678 encoding->red.Z /= whiteY;
1679 encoding->green.X /= whiteY;
1680 encoding->green.Y /= whiteY;
1681 encoding->green.Z /= whiteY;
1682 encoding->blue.X /= whiteY;
1683 encoding->blue.Y /= whiteY;
1684 encoding->blue.Z /= whiteY;
1685 }
1686}
1687
1688static size_t
1689safecat_color_encoding(char *buffer, size_t bufsize, size_t pos,
1690 PNG_CONST color_encoding *e, double encoding_gamma)
1691{
1692 if (e != 0)
1693 {
1694 if (encoding_gamma != 0)
1695 pos = safecat(buffer, bufsize, pos, "(");
1696 pos = safecat(buffer, bufsize, pos, "R(");
1697 pos = safecatd(buffer, bufsize, pos, e->red.X, 4);
1698 pos = safecat(buffer, bufsize, pos, ",");
1699 pos = safecatd(buffer, bufsize, pos, e->red.Y, 4);
1700 pos = safecat(buffer, bufsize, pos, ",");
1701 pos = safecatd(buffer, bufsize, pos, e->red.Z, 4);
1702 pos = safecat(buffer, bufsize, pos, "),G(");
1703 pos = safecatd(buffer, bufsize, pos, e->green.X, 4);
1704 pos = safecat(buffer, bufsize, pos, ",");
1705 pos = safecatd(buffer, bufsize, pos, e->green.Y, 4);
1706 pos = safecat(buffer, bufsize, pos, ",");
1707 pos = safecatd(buffer, bufsize, pos, e->green.Z, 4);
1708 pos = safecat(buffer, bufsize, pos, "),B(");
1709 pos = safecatd(buffer, bufsize, pos, e->blue.X, 4);
1710 pos = safecat(buffer, bufsize, pos, ",");
1711 pos = safecatd(buffer, bufsize, pos, e->blue.Y, 4);
1712 pos = safecat(buffer, bufsize, pos, ",");
1713 pos = safecatd(buffer, bufsize, pos, e->blue.Z, 4);
1714 pos = safecat(buffer, bufsize, pos, ")");
1715 if (encoding_gamma != 0)
1716 pos = safecat(buffer, bufsize, pos, ")");
1717 }
1718
1719 if (encoding_gamma != 0)
1720 {
1721 pos = safecat(buffer, bufsize, pos, "^");
1722 pos = safecatd(buffer, bufsize, pos, encoding_gamma, 5);
1723 }
1724
1725 return pos;
1726}
1727
1728typedef struct png_modifier
1729{
1730 png_store this; /* I am a png_store */
1731 struct png_modification *modifications; /* Changes to make */
1732
1733 modifier_state state; /* My state */
1734
1735 /* Information from IHDR: */
1736 png_byte bit_depth; /* From IHDR */
1737 png_byte colour_type; /* From IHDR */
1738
1739 /* While handling PLTE, IDAT and IEND these chunks may be pended to allow
1740 * other chunks to be inserted.
1741 */
1742 png_uint_32 pending_len;
1743 png_uint_32 pending_chunk;
1744
1745 /* Test values */
1746 double *gammas;
1747 unsigned int ngammas;
1748 unsigned int ngamma_tests; /* Number of gamma tests to run*/
1749 double current_gamma; /* 0 if not set */
1750 PNG_CONST color_encoding *encodings;
1751 unsigned int nencodings;
1752 PNG_CONST color_encoding *current_encoding; /* If an encoding has been set */
1753 unsigned int encoding_counter; /* For iteration */
1754 int encoding_ignored; /* Something overwrote it */
1755
1756 /* Control variables used to iterate through possible encodings, the
1757 * following must be set to 0 and tested by the function that uses the
1758 * png_modifier because the modifier only sets it to 1 (true.)
1759 */
1760 unsigned int repeat :1; /* Repeat this transform test. */
1761 unsigned int test_uses_encoding :1;
1762
1763 /* Lowest sbit to test (libpng fails for sbit < 8) */
1764 png_byte sbitlow;
1765
1766 /* Error control - these are the limits on errors accepted by the gamma tests
1767 * below.
1768 */
1769 double maxout8; /* Maximum output value error */
1770 double maxabs8; /* Absolute sample error 0..1 */
1771 double maxcalc8; /* Absolute sample error 0..1 */
1772 double maxpc8; /* Percentage sample error 0..100% */
1773 double maxout16; /* Maximum output value error */
1774 double maxabs16; /* Absolute sample error 0..1 */
1775 double maxcalc16;/* Absolute sample error 0..1 */
1776 double maxpc16; /* Percentage sample error 0..100% */
1777
1778 /* This is set by transforms that need to allow a higher limit, it is an
1779 * internal check on pngvalid to ensure that the calculated error limits are
1780 * not ridiculous; without this it is too easy to make a mistake in pngvalid
1781 * that allows any value through.
1782 */
1783 double limit; /* limit on error values, normally 4E-3 */
1784
1785 /* Log limits - values above this are logged, but not necessarily
1786 * warned.
1787 */
1788 double log8; /* Absolute error in 8 bits to log */
1789 double log16; /* Absolute error in 16 bits to log */
1790
1791 /* Logged 8 and 16 bit errors ('output' values): */
1792 double error_gray_2;
1793 double error_gray_4;
1794 double error_gray_8;
1795 double error_gray_16;
1796 double error_color_8;
1797 double error_color_16;
1798 double error_indexed;
1799
1800 /* Flags: */
1801 /* Whether to call png_read_update_info, not png_read_start_image, and how
1802 * many times to call it.
1803 */
1804 int use_update_info;
1805
1806 /* Whether or not to interlace. */
1807 int interlace_type :9; /* int, but must store '1' */
1808
1809 /* Run the standard tests? */
1810 unsigned int test_standard :1;
1811
1812 /* Run the odd-sized image and interlace read/write tests? */
1813 unsigned int test_size :1;
1814
1815 /* Run tests on reading with a combiniation of transforms, */
1816 unsigned int test_transform :1;
1817
1818 /* When to use the use_input_precision option: */
1819 unsigned int use_input_precision :1;
1820 unsigned int use_input_precision_sbit :1;
1821 unsigned int use_input_precision_16to8 :1;
1822
1823 /* If set assume that the calculation bit depth is set by the input
1824 * precision, not the output precision.
1825 */
1826 unsigned int calculations_use_input_precision :1;
1827
1828 /* If set assume that the calculations are done in 16 bits even if both input
1829 * and output are 8 bit or less.
1830 */
1831 unsigned int assume_16_bit_calculations :1;
1832
1833 /* Which gamma tests to run: */
1834 unsigned int test_gamma_threshold :1;
1835 unsigned int test_gamma_transform :1; /* main tests */
1836 unsigned int test_gamma_sbit :1;
1837 unsigned int test_gamma_scale16 :1;
1838 unsigned int test_gamma_background :1;
1839 unsigned int test_gamma_alpha_mode :1;
1840 unsigned int test_gamma_expand16 :1;
1841 unsigned int test_exhaustive :1;
1842
1843 unsigned int log :1; /* Log max error */
1844
1845 /* Buffer information, the buffer size limits the size of the chunks that can
1846 * be modified - they must fit (including header and CRC) into the buffer!
1847 */
1848 size_t flush; /* Count of bytes to flush */
1849 size_t buffer_count; /* Bytes in buffer */
1850 size_t buffer_position; /* Position in buffer */
1851 png_byte buffer[1024];
1852} png_modifier;
1853
1854/* This returns true if the test should be stopped now because it has already
1855 * failed and it is running silently.
1856 */
1857static int fail(png_modifier *pm)
1858{
1859 return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 ||
1860 (pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0));
1861}
1862
1863static void
1864modifier_init(png_modifier *pm)
1865{
1866 memset(pm, 0, sizeof *pm);
1867 store_init(&pm->this);
1868 pm->modifications = NULL;
1869 pm->state = modifier_start;
1870 pm->sbitlow = 1U;
1871 pm->ngammas = 0;
1872 pm->ngamma_tests = 0;
1873 pm->gammas = 0;
1874 pm->current_gamma = 0;
1875 pm->encodings = 0;
1876 pm->nencodings = 0;
1877 pm->current_encoding = 0;
1878 pm->encoding_counter = 0;
1879 pm->encoding_ignored = 0;
1880 pm->repeat = 0;
1881 pm->test_uses_encoding = 0;
1882 pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0;
1883 pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0;
1884 pm->limit = 4E-3;
1885 pm->log8 = pm->log16 = 0; /* Means 'off' */
1886 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0;
1887 pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0;
1888 pm->error_indexed = 0;
1889 pm->use_update_info = 0;
1890 pm->interlace_type = PNG_INTERLACE_NONE;
1891 pm->test_standard = 0;
1892 pm->test_size = 0;
1893 pm->test_transform = 0;
1894 pm->use_input_precision = 0;
1895 pm->use_input_precision_sbit = 0;
1896 pm->use_input_precision_16to8 = 0;
1897 pm->calculations_use_input_precision = 0;
1898 pm->test_gamma_threshold = 0;
1899 pm->test_gamma_transform = 0;
1900 pm->test_gamma_sbit = 0;
1901 pm->test_gamma_scale16 = 0;
1902 pm->test_gamma_background = 0;
1903 pm->test_gamma_alpha_mode = 0;
1904 pm->test_gamma_expand16 = 0;
1905 pm->test_exhaustive = 0;
1906 pm->log = 0;
1907
1908 /* Rely on the memset for all the other fields - there are no pointers */
1909}
1910
1911#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1912/* If pm->calculations_use_input_precision is set then operations will happen
1913 * with only 8 bit precision unless both the input and output bit depth are 16.
1914 *
1915 * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16
1916 * bit precision. This only affects those of the following limits that pertain
1917 * to a calculation - not a digitization operation - unless the following API is
1918 * called directly.
1919 */
1920static double digitize(PNG_CONST png_modifier *pm, double value,
1921 int sample_depth, int do_round)
1922{
1923 /* 'value' is in the range 0 to 1, the result is the same value rounded to a
1924 * multiple of the digitization factor - 8 or 16 bits depending on both the
1925 * sample depth and the 'assume' setting. Digitization is normally by
1926 * rounding and 'do_round' should be 1, if it is 0 the digitized value will
1927 * be truncated.
1928 */
1929 PNG_CONST unsigned int digitization_factor =
1930 (pm->assume_16_bit_calculations || sample_depth == 16) ? 65535 : 255;
1931
1932 /* Limiting the range is done as a convenience to the caller - it's easier to
1933 * do it once here than every time at the call site.
1934 */
1935 if (value <= 0)
1936 value = 0;
1937 else if (value >= 1)
1938 value = 1;
1939
1940 value *= digitization_factor;
1941 if (do_round) value += .5;
1942 return floor(value)/digitization_factor;
1943}
1944
1945static double abserr(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
1946{
1947 /* Absolute error permitted in linear values - affected by the bit depth of
1948 * the calculations.
1949 */
1950 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 ||
1951 !pm->calculations_use_input_precision)))
1952 return pm->maxabs16;
1953 else
1954 return pm->maxabs8;
1955}
1956
1957static double calcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
1958{
1959 /* Error in the linear composition arithmetic - only relevant when
1960 * composition actually happens (0 < alpha < 1).
1961 */
1962 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 ||
1963 !pm->calculations_use_input_precision)))
1964 return pm->maxcalc16;
1965 else
1966 return pm->maxcalc8;
1967}
1968
1969static double pcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
1970{
1971 /* Percentage error permitted in the linear values. Note that the specified
1972 * value is a percentage but this routine returns a simple number.
1973 */
1974 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 ||
1975 !pm->calculations_use_input_precision)))
1976 return pm->maxpc16 * .01;
1977 else
1978 return pm->maxpc8 * .01;
1979}
1980
1981/* Output error - the error in the encoded value. This is determined by the
1982 * digitization of the output so can be +/-0.5 in the actual output value. In
1983 * the expand_16 case with the current code in libpng the expand happens after
1984 * all the calculations are done in 8 bit arithmetic, so even though the output
1985 * depth is 16 the output error is determined by the 8 bit calculation.
1986 *
1987 * This limit is not determined by the bit depth of internal calculations.
1988 *
1989 * The specified parameter does *not* include the base .5 digitization error but
1990 * it is added here.
1991 */
1992static double outerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
1993{
1994 /* There is a serious error in the 2 and 4 bit grayscale transform because
1995 * the gamma table value (8 bits) is simply shifted, not rounded, so the
1996 * error in 4 bit grayscale gamma is up to the value below. This is a hack
1997 * to allow pngvalid to succeed:
1998 *
1999 * TODO: fix this in libpng
2000 */
2001 if (out_depth == 2)
2002 return .73182-.5;
2003
2004 if (out_depth == 4)
2005 return .90644-.5;
2006
2007 if (out_depth == 16 && (in_depth == 16 ||
2008 !pm->calculations_use_input_precision))
2009 return pm->maxout16;
2010
2011 /* This is the case where the value was calculated at 8-bit precision then
2012 * scaled to 16 bits.
2013 */
2014 else if (out_depth == 16)
2015 return pm->maxout8 * 257;
2016
2017 else
2018 return pm->maxout8;
2019}
2020
2021/* This does the same thing as the above however it returns the value to log,
2022 * rather than raising a warning. This is useful for debugging to track down
2023 * exactly what set of parameters cause high error values.
2024 */
2025static double outlog(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
2026{
2027 /* The command line parameters are either 8 bit (0..255) or 16 bit (0..65535)
2028 * and so must be adjusted for low bit depth grayscale:
2029 */
2030 if (out_depth <= 8)
2031 {
2032 if (pm->log8 == 0) /* switched off */
2033 return 256;
2034
2035 if (out_depth < 8)
2036 return pm->log8 / 255 * ((1<<out_depth)-1);
2037
2038 return pm->log8;
2039 }
2040
2041 if (out_depth == 16 && (in_depth == 16 ||
2042 !pm->calculations_use_input_precision))
2043 {
2044 if (pm->log16 == 0)
2045 return 65536;
2046
2047 return pm->log16;
2048 }
2049
2050 /* This is the case where the value was calculated at 8-bit precision then
2051 * scaled to 16 bits.
2052 */
2053 if (pm->log8 == 0)
2054 return 65536;
2055
2056 return pm->log8 * 257;
2057}
2058
2059/* This complements the above by providing the appropriate quantization for the
2060 * final value. Normally this would just be quantization to an integral value,
2061 * but in the 8 bit calculation case it's actually quantization to a multiple of
2062 * 257!
2063 */
2064static int output_quantization_factor(PNG_CONST png_modifier *pm, int in_depth,
2065 int out_depth)
2066{
2067 if (out_depth == 16 && in_depth != 16
2068 && pm->calculations_use_input_precision)
2069 return 257;
2070 else
2071 return 1;
2072}
2073
2074/* One modification structure must be provided for each chunk to be modified (in
2075 * fact more than one can be provided if multiple separate changes are desired
2076 * for a single chunk.) Modifications include adding a new chunk when a
2077 * suitable chunk does not exist.
2078 *
2079 * The caller of modify_fn will reset the CRC of the chunk and record 'modified'
2080 * or 'added' as appropriate if the modify_fn returns 1 (true). If the
2081 * modify_fn is NULL the chunk is simply removed.
2082 */
2083typedef struct png_modification
2084{
2085 struct png_modification *next;
2086 png_uint_32 chunk;
2087
2088 /* If the following is NULL all matching chunks will be removed: */
2089 int (*modify_fn)(struct png_modifier *pm,
2090 struct png_modification *me, int add);
2091
2092 /* If the following is set to PLTE, IDAT or IEND and the chunk has not been
2093 * found and modified (and there is a modify_fn) the modify_fn will be called
2094 * to add the chunk before the relevant chunk.
2095 */
2096 png_uint_32 add;
2097 unsigned int modified :1; /* Chunk was modified */
2098 unsigned int added :1; /* Chunk was added */
2099 unsigned int removed :1; /* Chunk was removed */
2100} png_modification;
2101
2102static void
2103modification_reset(png_modification *pmm)
2104{
2105 if (pmm != NULL)
2106 {
2107 pmm->modified = 0;
2108 pmm->added = 0;
2109 pmm->removed = 0;
2110 modification_reset(pmm->next);
2111 }
2112}
2113
2114static void
2115modification_init(png_modification *pmm)
2116{
2117 memset(pmm, 0, sizeof *pmm);
2118 pmm->next = NULL;
2119 pmm->chunk = 0;
2120 pmm->modify_fn = NULL;
2121 pmm->add = 0;
2122 modification_reset(pmm);
2123}
2124
2125static void
2126modifier_current_encoding(PNG_CONST png_modifier *pm, color_encoding *ce)
2127{
2128 if (pm->current_encoding != 0)
2129 *ce = *pm->current_encoding;
2130
2131 else
2132 memset(ce, 0, sizeof *ce);
2133
2134 ce->gamma = pm->current_gamma;
2135}
2136
2137static size_t
2138safecat_current_encoding(char *buffer, size_t bufsize, size_t pos,
2139 PNG_CONST png_modifier *pm)
2140{
2141 pos = safecat_color_encoding(buffer, bufsize, pos, pm->current_encoding,
2142 pm->current_gamma);
2143
2144 if (pm->encoding_ignored)
2145 pos = safecat(buffer, bufsize, pos, "[overridden]");
2146
2147 return pos;
2148}
2149
2150/* Iterate through the usefully testable color encodings. An encoding is one
2151 * of:
2152 *
2153 * 1) Nothing (no color space, no gamma).
2154 * 2) Just a gamma value from the gamma array (including 1.0)
2155 * 3) A color space from the encodings array with the corresponding gamma.
2156 * 4) The same, but with gamma 1.0 (only really useful with 16 bit calculations)
2157 *
2158 * The iterator selects these in turn, the randomizer selects one at random,
2159 * which is used depends on the setting of the 'test_exhaustive' flag. Notice
2160 * that this function changes the colour space encoding so it must only be
2161 * called on completion of the previous test. This is what 'modifier_reset'
2162 * does, below.
2163 *
2164 * After the function has been called the 'repeat' flag will still be set; the
2165 * caller of modifier_reset must reset it at the start of each run of the test!
2166 */
2167static unsigned int
2168modifier_total_encodings(PNG_CONST png_modifier *pm)
2169{
2170 return 1 + /* (1) nothing */
2171 pm->ngammas + /* (2) gamma values to test */
2172 pm->nencodings + /* (3) total number of encodings */
2173 /* The following test only works after the first time through the
2174 * png_modifier code because 'bit_depth' is set when the IHDR is read.
2175 * modifier_reset, below, preserves the setting until after it has called
2176 * the iterate function (also below.)
2177 *
2178 * For this reason do not rely on this function outside a call to
2179 * modifier_reset.
2180 */
2181 ((pm->bit_depth == 16 || pm->assume_16_bit_calculations) ?
2182 pm->nencodings : 0); /* (4) encodings with gamma == 1.0 */
2183}
2184
2185static void
2186modifier_encoding_iterate(png_modifier *pm)
2187{
2188 if (!pm->repeat && /* Else something needs the current encoding again. */
2189 pm->test_uses_encoding) /* Some transform is encoding dependent */
2190 {
2191 if (pm->test_exhaustive)
2192 {
2193 if (++pm->encoding_counter >= modifier_total_encodings(pm))
2194 pm->encoding_counter = 0; /* This will stop the repeat */
2195 }
2196
2197 else
2198 {
2199 /* Not exhaustive - choose an encoding at random; generate a number in
2200 * the range 1..(max-1), so the result is always non-zero:
2201 */
2202 if (pm->encoding_counter == 0)
2203 pm->encoding_counter = random_mod(modifier_total_encodings(pm)-1)+1;
2204 else
2205 pm->encoding_counter = 0;
2206 }
2207
2208 if (pm->encoding_counter > 0)
2209 pm->repeat = 1;
2210 }
2211
2212 else if (!pm->repeat)
2213 pm->encoding_counter = 0;
2214}
2215
2216static void
2217modifier_reset(png_modifier *pm)
2218{
2219 store_read_reset(&pm->this);
2220 pm->limit = 4E-3;
2221 pm->pending_len = pm->pending_chunk = 0;
2222 pm->flush = pm->buffer_count = pm->buffer_position = 0;
2223 pm->modifications = NULL;
2224 pm->state = modifier_start;
2225 modifier_encoding_iterate(pm);
2226 /* The following must be set in the next run. In particular
2227 * test_uses_encodings must be set in the _ini function of each transform
2228 * that looks at the encodings. (Not the 'add' function!)
2229 */
2230 pm->test_uses_encoding = 0;
2231 pm->current_gamma = 0;
2232 pm->current_encoding = 0;
2233 pm->encoding_ignored = 0;
2234 /* These only become value after IHDR is read: */
2235 pm->bit_depth = pm->colour_type = 0;
2236}
2237
2238/* The following must be called before anything else to get the encoding set up
2239 * on the modifier. In particular it must be called before the transform init
2240 * functions are called.
2241 */
2242static void
2243modifier_set_encoding(png_modifier *pm)
2244{
2245 /* Set the encoding to the one specified by the current encoding counter,
2246 * first clear out all the settings - this corresponds to an encoding_counter
2247 * of 0.
2248 */
2249 pm->current_gamma = 0;
2250 pm->current_encoding = 0;
2251 pm->encoding_ignored = 0; /* not ignored yet - happens in _ini functions. */
2252
2253 /* Now, if required, set the gamma and encoding fields. */
2254 if (pm->encoding_counter > 0)
2255 {
2256 /* The gammas[] array is an array of screen gammas, not encoding gammas,
2257 * so we need the inverse:
2258 */
2259 if (pm->encoding_counter <= pm->ngammas)
2260 pm->current_gamma = 1/pm->gammas[pm->encoding_counter-1];
2261
2262 else
2263 {
2264 unsigned int i = pm->encoding_counter - pm->ngammas;
2265
2266 if (i >= pm->nencodings)
2267 {
2268 i %= pm->nencodings;
2269 pm->current_gamma = 1; /* Linear, only in the 16 bit case */
2270 }
2271
2272 else
2273 pm->current_gamma = pm->encodings[i].gamma;
2274
2275 pm->current_encoding = pm->encodings + i;
2276 }
2277 }
2278}
2279
2280/* Enquiry functions to find out what is set. Notice that there is an implicit
2281 * assumption below that the first encoding in the list is the one for sRGB.
2282 */
2283static int
2284modifier_color_encoding_is_sRGB(PNG_CONST png_modifier *pm)
2285{
2286 return pm->current_encoding != 0 && pm->current_encoding == pm->encodings &&
2287 pm->current_encoding->gamma == pm->current_gamma;
2288}
2289
2290static int
2291modifier_color_encoding_is_set(PNG_CONST png_modifier *pm)
2292{
2293 return pm->current_gamma != 0;
2294}
2295
2296/* Convenience macros. */
2297#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
2298#define CHUNK_IHDR CHUNK(73,72,68,82)
2299#define CHUNK_PLTE CHUNK(80,76,84,69)
2300#define CHUNK_IDAT CHUNK(73,68,65,84)
2301#define CHUNK_IEND CHUNK(73,69,78,68)
2302#define CHUNK_cHRM CHUNK(99,72,82,77)
2303#define CHUNK_gAMA CHUNK(103,65,77,65)
2304#define CHUNK_sBIT CHUNK(115,66,73,84)
2305#define CHUNK_sRGB CHUNK(115,82,71,66)
2306
2307/* The guts of modification are performed during a read. */
2308static void
2309modifier_crc(png_bytep buffer)
2310{
2311 /* Recalculate the chunk CRC - a complete chunk must be in
2312 * the buffer, at the start.
2313 */
2314 uInt datalen = png_get_uint_32(buffer);
2315 uLong crc = crc32(0, buffer+4, datalen+4);
2316 /* The cast to png_uint_32 is safe because a crc32 is always a 32 bit value.
2317 */
2318 png_save_uint_32(buffer+datalen+8, (png_uint_32)crc);
2319}
2320
2321static void
2322modifier_setbuffer(png_modifier *pm)
2323{
2324 modifier_crc(pm->buffer);
2325 pm->buffer_count = png_get_uint_32(pm->buffer)+12;
2326 pm->buffer_position = 0;
2327}
2328
2329/* Separate the callback into the actual implementation (which is passed the
2330 * png_modifier explicitly) and the callback, which gets the modifier from the
2331 * png_struct.
2332 */
2333static void
2334modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st)
2335{
2336 while (st > 0)
2337 {
2338 size_t cb;
2339 png_uint_32 len, chunk;
2340 png_modification *mod;
2341
2342 if (pm->buffer_position >= pm->buffer_count) switch (pm->state)
2343 {
2344 static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
2345 case modifier_start:
2346 store_read_imp(&pm->this, pm->buffer, 8); /* size of signature. */
2347 pm->buffer_count = 8;
2348 pm->buffer_position = 0;
2349
2350 if (memcmp(pm->buffer, sign, 8) != 0)
2351 png_error(pm->this.pread, "invalid PNG file signature");
2352 pm->state = modifier_signature;
2353 break;
2354
2355 case modifier_signature:
2356 store_read_imp(&pm->this, pm->buffer, 13+12); /* size of IHDR */
2357 pm->buffer_count = 13+12;
2358 pm->buffer_position = 0;
2359
2360 if (png_get_uint_32(pm->buffer) != 13 ||
2361 png_get_uint_32(pm->buffer+4) != CHUNK_IHDR)
2362 png_error(pm->this.pread, "invalid IHDR");
2363
2364 /* Check the list of modifiers for modifications to the IHDR. */
2365 mod = pm->modifications;
2366 while (mod != NULL)
2367 {
2368 if (mod->chunk == CHUNK_IHDR && mod->modify_fn &&
2369 (*mod->modify_fn)(pm, mod, 0))
2370 {
2371 mod->modified = 1;
2372 modifier_setbuffer(pm);
2373 }
2374
2375 /* Ignore removal or add if IHDR! */
2376 mod = mod->next;
2377 }
2378
2379 /* Cache information from the IHDR (the modified one.) */
2380 pm->bit_depth = pm->buffer[8+8];
2381 pm->colour_type = pm->buffer[8+8+1];
2382
2383 pm->state = modifier_IHDR;
2384 pm->flush = 0;
2385 break;
2386
2387 case modifier_IHDR:
2388 default:
2389 /* Read a new chunk and process it until we see PLTE, IDAT or
2390 * IEND. 'flush' indicates that there is still some data to
2391 * output from the preceding chunk.
2392 */
2393 if ((cb = pm->flush) > 0)
2394 {
2395 if (cb > st) cb = st;
2396 pm->flush -= cb;
2397 store_read_imp(&pm->this, pb, cb);
2398 pb += cb;
2399 st -= cb;
2400 if (st == 0) return;
2401 }
2402
2403 /* No more bytes to flush, read a header, or handle a pending
2404 * chunk.
2405 */
2406 if (pm->pending_chunk != 0)
2407 {
2408 png_save_uint_32(pm->buffer, pm->pending_len);
2409 png_save_uint_32(pm->buffer+4, pm->pending_chunk);
2410 pm->pending_len = 0;
2411 pm->pending_chunk = 0;
2412 }
2413 else
2414 store_read_imp(&pm->this, pm->buffer, 8);
2415
2416 pm->buffer_count = 8;
2417 pm->buffer_position = 0;
2418
2419 /* Check for something to modify or a terminator chunk. */
2420 len = png_get_uint_32(pm->buffer);
2421 chunk = png_get_uint_32(pm->buffer+4);
2422
2423 /* Terminators first, they may have to be delayed for added
2424 * chunks
2425 */
2426 if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT ||
2427 chunk == CHUNK_IEND)
2428 {
2429 mod = pm->modifications;
2430
2431 while (mod != NULL)
2432 {
2433 if ((mod->add == chunk ||
2434 (mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT)) &&
2435 mod->modify_fn != NULL && !mod->modified && !mod->added)
2436 {
2437 /* Regardless of what the modify function does do not run
2438 * this again.
2439 */
2440 mod->added = 1;
2441
2442 if ((*mod->modify_fn)(pm, mod, 1 /*add*/))
2443 {
2444 /* Reset the CRC on a new chunk */
2445 if (pm->buffer_count > 0)
2446 modifier_setbuffer(pm);
2447
2448 else
2449 {
2450 pm->buffer_position = 0;
2451 mod->removed = 1;
2452 }
2453
2454 /* The buffer has been filled with something (we assume)
2455 * so output this. Pend the current chunk.
2456 */
2457 pm->pending_len = len;
2458 pm->pending_chunk = chunk;
2459 break; /* out of while */
2460 }
2461 }
2462
2463 mod = mod->next;
2464 }
2465
2466 /* Don't do any further processing if the buffer was modified -
2467 * otherwise the code will end up modifying a chunk that was
2468 * just added.
2469 */
2470 if (mod != NULL)
2471 break; /* out of switch */
2472 }
2473
2474 /* If we get to here then this chunk may need to be modified. To
2475 * do this it must be less than 1024 bytes in total size, otherwise
2476 * it just gets flushed.
2477 */
2478 if (len+12 <= sizeof pm->buffer)
2479 {
2480 store_read_imp(&pm->this, pm->buffer+pm->buffer_count,
2481 len+12-pm->buffer_count);
2482 pm->buffer_count = len+12;
2483
2484 /* Check for a modification, else leave it be. */
2485 mod = pm->modifications;
2486 while (mod != NULL)
2487 {
2488 if (mod->chunk == chunk)
2489 {
2490 if (mod->modify_fn == NULL)
2491 {
2492 /* Remove this chunk */
2493 pm->buffer_count = pm->buffer_position = 0;
2494 mod->removed = 1;
2495 break; /* Terminate the while loop */
2496 }
2497
2498 else if ((*mod->modify_fn)(pm, mod, 0))
2499 {
2500 mod->modified = 1;
2501 /* The chunk may have been removed: */
2502 if (pm->buffer_count == 0)
2503 {
2504 pm->buffer_position = 0;
2505 break;
2506 }
2507 modifier_setbuffer(pm);
2508 }
2509 }
2510
2511 mod = mod->next;
2512 }
2513 }
2514
2515 else
2516 pm->flush = len+12 - pm->buffer_count; /* data + crc */
2517
2518 /* Take the data from the buffer (if there is any). */
2519 break;
2520 }
2521
2522 /* Here to read from the modifier buffer (not directly from
2523 * the store, as in the flush case above.)
2524 */
2525 cb = pm->buffer_count - pm->buffer_position;
2526
2527 if (cb > st)
2528 cb = st;
2529
2530 memcpy(pb, pm->buffer + pm->buffer_position, cb);
2531 st -= cb;
2532 pb += cb;
2533 pm->buffer_position += cb;
2534 }
2535}
2536
2537/* The callback: */
2538static void
2539modifier_read(png_structp pp, png_bytep pb, png_size_t st)
2540{
2541 png_modifier *pm = voidcast(png_modifier*, png_get_io_ptr(pp));
2542
2543 if (pm == NULL || pm->this.pread != pp)
2544 png_error(pp, "bad modifier_read call");
2545
2546 modifier_read_imp(pm, pb, st);
2547}
2548
2549/* Like store_progressive_read but the data is getting changed as we go so we
2550 * need a local buffer.
2551 */
2552static void
2553modifier_progressive_read(png_modifier *pm, png_structp pp, png_infop pi)
2554{
2555 if (pm->this.pread != pp || pm->this.current == NULL ||
2556 pm->this.next == NULL)
2557 png_error(pp, "store state damaged (progressive)");
2558
2559 /* This is another Horowitz and Hill random noise generator. In this case
2560 * the aim is to stress the progressive reader with truly horrible variable
2561 * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers
2562 * is generated. We could probably just count from 1 to 32767 and get as
2563 * good a result.
2564 */
2565 for (;;)
2566 {
2567 static png_uint_32 noise = 1;
2568 png_size_t cb, cbAvail;
2569 png_byte buffer[512];
2570
2571 /* Generate 15 more bits of stuff: */
2572 noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff);
2573 cb = noise & 0x1ff;
2574
2575 /* Check that this number of bytes are available (in the current buffer.)
2576 * (This doesn't quite work - the modifier might delete a chunk; unlikely
2577 * but possible, it doesn't happen at present because the modifier only
2578 * adds chunks to standard images.)
2579 */
2580 cbAvail = store_read_buffer_avail(&pm->this);
2581 if (pm->buffer_count > pm->buffer_position)
2582 cbAvail += pm->buffer_count - pm->buffer_position;
2583
2584 if (cb > cbAvail)
2585 {
2586 /* Check for EOF: */
2587 if (cbAvail == 0)
2588 break;
2589
2590 cb = cbAvail;
2591 }
2592
2593 modifier_read_imp(pm, buffer, cb);
2594 png_process_data(pp, pi, buffer, cb);
2595 }
2596
2597 /* Check the invariants at the end (if this fails it's a problem in this
2598 * file!)
2599 */
2600 if (pm->buffer_count > pm->buffer_position ||
2601 pm->this.next != &pm->this.current->data ||
2602 pm->this.readpos < pm->this.current->datacount)
2603 png_error(pp, "progressive read implementation error");
2604}
2605
2606/* Set up a modifier. */
2607static png_structp
2608set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id,
2609 PNG_CONST char *name)
2610{
2611 /* Do this first so that the modifier fields are cleared even if an error
2612 * happens allocating the png_struct. No allocation is done here so no
2613 * cleanup is required.
2614 */
2615 pm->state = modifier_start;
2616 pm->bit_depth = 0;
2617 pm->colour_type = 255;
2618
2619 pm->pending_len = 0;
2620 pm->pending_chunk = 0;
2621 pm->flush = 0;
2622 pm->buffer_count = 0;
2623 pm->buffer_position = 0;
2624
2625 return set_store_for_read(&pm->this, ppi, id, name);
2626}
2627
2628
2629/******************************** MODIFICATIONS *******************************/
2630/* Standard modifications to add chunks. These do not require the _SUPPORTED
2631 * macros because the chunks can be there regardless of whether this specific
2632 * libpng supports them.
2633 */
2634typedef struct gama_modification
2635{
2636 png_modification this;
2637 png_fixed_point gamma;
2638} gama_modification;
2639
2640static int
2641gama_modify(png_modifier *pm, png_modification *me, int add)
2642{
2643 UNUSED(add)
2644 /* This simply dumps the given gamma value into the buffer. */
2645 png_save_uint_32(pm->buffer, 4);
2646 png_save_uint_32(pm->buffer+4, CHUNK_gAMA);
2647 png_save_uint_32(pm->buffer+8, ((gama_modification*)me)->gamma);
2648 return 1;
2649}
2650
2651static void
2652gama_modification_init(gama_modification *me, png_modifier *pm, double gammad)
2653{
2654 double g;
2655
2656 modification_init(&me->this);
2657 me->this.chunk = CHUNK_gAMA;
2658 me->this.modify_fn = gama_modify;
2659 me->this.add = CHUNK_PLTE;
2660 g = fix(gammad);
2661 me->gamma = (png_fixed_point)g;
2662 me->this.next = pm->modifications;
2663 pm->modifications = &me->this;
2664}
2665
2666typedef struct chrm_modification
2667{
2668 png_modification this;
2669 PNG_CONST color_encoding *encoding;
2670 png_fixed_point wx, wy, rx, ry, gx, gy, bx, by;
2671} chrm_modification;
2672
2673static int
2674chrm_modify(png_modifier *pm, png_modification *me, int add)
2675{
2676 UNUSED(add)
2677 /* As with gAMA this just adds the required cHRM chunk to the buffer. */
2678 png_save_uint_32(pm->buffer , 32);
2679 png_save_uint_32(pm->buffer+ 4, CHUNK_cHRM);
2680 png_save_uint_32(pm->buffer+ 8, ((chrm_modification*)me)->wx);
2681 png_save_uint_32(pm->buffer+12, ((chrm_modification*)me)->wy);
2682 png_save_uint_32(pm->buffer+16, ((chrm_modification*)me)->rx);
2683 png_save_uint_32(pm->buffer+20, ((chrm_modification*)me)->ry);
2684 png_save_uint_32(pm->buffer+24, ((chrm_modification*)me)->gx);
2685 png_save_uint_32(pm->buffer+28, ((chrm_modification*)me)->gy);
2686 png_save_uint_32(pm->buffer+32, ((chrm_modification*)me)->bx);
2687 png_save_uint_32(pm->buffer+36, ((chrm_modification*)me)->by);
2688 return 1;
2689}
2690
2691static void
2692chrm_modification_init(chrm_modification *me, png_modifier *pm,
2693 PNG_CONST color_encoding *encoding)
2694{
2695 CIE_color white = white_point(encoding);
2696
2697 /* Original end points: */
2698 me->encoding = encoding;
2699
2700 /* Chromaticities (in fixed point): */
2701 me->wx = fix(chromaticity_x(white));
2702 me->wy = fix(chromaticity_y(white));
2703
2704 me->rx = fix(chromaticity_x(encoding->red));
2705 me->ry = fix(chromaticity_y(encoding->red));
2706 me->gx = fix(chromaticity_x(encoding->green));
2707 me->gy = fix(chromaticity_y(encoding->green));
2708 me->bx = fix(chromaticity_x(encoding->blue));
2709 me->by = fix(chromaticity_y(encoding->blue));
2710
2711 modification_init(&me->this);
2712 me->this.chunk = CHUNK_cHRM;
2713 me->this.modify_fn = chrm_modify;
2714 me->this.add = CHUNK_PLTE;
2715 me->this.next = pm->modifications;
2716 pm->modifications = &me->this;
2717}
2718
2719typedef struct srgb_modification
2720{
2721 png_modification this;
2722 png_byte intent;
2723} srgb_modification;
2724
2725static int
2726srgb_modify(png_modifier *pm, png_modification *me, int add)
2727{
2728 UNUSED(add)
2729 /* As above, ignore add and just make a new chunk */
2730 png_save_uint_32(pm->buffer, 1);
2731 png_save_uint_32(pm->buffer+4, CHUNK_sRGB);
2732 pm->buffer[8] = ((srgb_modification*)me)->intent;
2733 return 1;
2734}
2735
2736static void
2737srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent)
2738{
2739 modification_init(&me->this);
2740 me->this.chunk = CHUNK_sBIT;
2741
2742 if (intent <= 3) /* if valid, else *delete* sRGB chunks */
2743 {
2744 me->this.modify_fn = srgb_modify;
2745 me->this.add = CHUNK_PLTE;
2746 me->intent = intent;
2747 }
2748
2749 else
2750 {
2751 me->this.modify_fn = 0;
2752 me->this.add = 0;
2753 me->intent = 0;
2754 }
2755
2756 me->this.next = pm->modifications;
2757 pm->modifications = &me->this;
2758}
2759
2760typedef struct sbit_modification
2761{
2762 png_modification this;
2763 png_byte sbit;
2764} sbit_modification;
2765
2766static int
2767sbit_modify(png_modifier *pm, png_modification *me, int add)
2768{
2769 png_byte sbit = ((sbit_modification*)me)->sbit;
2770 if (pm->bit_depth > sbit)
2771 {
2772 int cb = 0;
2773 switch (pm->colour_type)
2774 {
2775 case 0:
2776 cb = 1;
2777 break;
2778
2779 case 2:
2780 case 3:
2781 cb = 3;
2782 break;
2783
2784 case 4:
2785 cb = 2;
2786 break;
2787
2788 case 6:
2789 cb = 4;
2790 break;
2791
2792 default:
2793 png_error(pm->this.pread,
2794 "unexpected colour type in sBIT modification");
2795 }
2796
2797 png_save_uint_32(pm->buffer, cb);
2798 png_save_uint_32(pm->buffer+4, CHUNK_sBIT);
2799
2800 while (cb > 0)
2801 (pm->buffer+8)[--cb] = sbit;
2802
2803 return 1;
2804 }
2805 else if (!add)
2806 {
2807 /* Remove the sBIT chunk */
2808 pm->buffer_count = pm->buffer_position = 0;
2809 return 1;
2810 }
2811 else
2812 return 0; /* do nothing */
2813}
2814
2815static void
2816sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit)
2817{
2818 modification_init(&me->this);
2819 me->this.chunk = CHUNK_sBIT;
2820 me->this.modify_fn = sbit_modify;
2821 me->this.add = CHUNK_PLTE;
2822 me->sbit = sbit;
2823 me->this.next = pm->modifications;
2824 pm->modifications = &me->this;
2825}
2826#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
2827
2828/***************************** STANDARD PNG FILES *****************************/
2829/* Standard files - write and save standard files. */
2830/* There are two basic forms of standard images. Those which attempt to have
2831 * all the possible pixel values (not possible for 16bpp images, but a range of
2832 * values are produced) and those which have a range of image sizes. The former
2833 * are used for testing transforms, in particular gamma correction and bit
2834 * reduction and increase. The latter are reserved for testing the behavior of
2835 * libpng with respect to 'odd' image sizes - particularly small images where
2836 * rows become 1 byte and interlace passes disappear.
2837 *
2838 * The first, most useful, set are the 'transform' images, the second set of
2839 * small images are the 'size' images.
2840 *
2841 * The transform files are constructed with rows which fit into a 1024 byte row
2842 * buffer. This makes allocation easier below. Further regardless of the file
2843 * format every row has 128 pixels (giving 1024 bytes for 64bpp formats).
2844 *
2845 * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed
2846 * and with an ID derived from the colour type, bit depth and interlace type
2847 * as above (FILEID). The width (128) and height (variable) are not stored in
2848 * the FILEID - instead the fields are set to 0, indicating a transform file.
2849 *
2850 * The size files ar constructed with rows a maximum of 128 bytes wide, allowing
2851 * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum
2852 * height of 16 rows. The width and height are stored in the FILEID and, being
2853 * non-zero, indicate a size file.
2854 *
2855 * For palette image (colour type 3) multiple transform images are stored with
2856 * the same bit depth to allow testing of more colour combinations -
2857 * particularly important for testing the gamma code because libpng uses a
2858 * different code path for palette images. For size images a single palette is
2859 * used.
2860 */
2861
2862/* Make a 'standard' palette. Because there are only 256 entries in a palette
2863 * (maximum) this actually makes a random palette in the hope that enough tests
2864 * will catch enough errors. (Note that the same palette isn't produced every
2865 * time for the same test - it depends on what previous tests have been run -
2866 * but a given set of arguments to pngvalid will always produce the same palette
2867 * at the same test! This is why pseudo-random number generators are useful for
2868 * testing.)
2869 *
2870 * The store must be open for write when this is called, otherwise an internal
2871 * error will occur. This routine contains its own magic number seed, so the
2872 * palettes generated don't change if there are intervening errors (changing the
2873 * calls to the store_mark seed.)
2874 */
2875static store_palette_entry *
2876make_standard_palette(png_store* ps, int npalette, int do_tRNS)
2877{
2878 static png_uint_32 palette_seed[2] = { 0x87654321, 9 };
2879
2880 int i = 0;
2881 png_byte values[256][4];
2882
2883 /* Always put in black and white plus the six primary and secondary colors.
2884 */
2885 for (; i<8; ++i)
2886 {
2887 values[i][1] = (i&1) ? 255 : 0;
2888 values[i][2] = (i&2) ? 255 : 0;
2889 values[i][3] = (i&4) ? 255 : 0;
2890 }
2891
2892 /* Then add 62 grays (one quarter of the remaining 256 slots). */
2893 {
2894 int j = 0;
2895 png_byte random_bytes[4];
2896 png_byte need[256];
2897
2898 need[0] = 0; /*got black*/
2899 memset(need+1, 1, (sizeof need)-2); /*need these*/
2900 need[255] = 0; /*but not white*/
2901
2902 while (i<70)
2903 {
2904 png_byte b;
2905
2906 if (j==0)
2907 {
2908 make_four_random_bytes(palette_seed, random_bytes);
2909 j = 4;
2910 }
2911
2912 b = random_bytes[--j];
2913 if (need[b])
2914 {
2915 values[i][1] = b;
2916 values[i][2] = b;
2917 values[i++][3] = b;
2918 }
2919 }
2920 }
2921
2922 /* Finally add 192 colors at random - don't worry about matches to things we
2923 * already have, chance is less than 1/65536. Don't worry about grays,
2924 * chance is the same, so we get a duplicate or extra gray less than 1 time
2925 * in 170.
2926 */
2927 for (; i<256; ++i)
2928 make_four_random_bytes(palette_seed, values[i]);
2929
2930 /* Fill in the alpha values in the first byte. Just use all possible values
2931 * (0..255) in an apparently random order:
2932 */
2933 {
2934 store_palette_entry *palette;
2935 png_byte selector[4];
2936
2937 make_four_random_bytes(palette_seed, selector);
2938
2939 if (do_tRNS)
2940 for (i=0; i<256; ++i)
2941 values[i][0] = (png_byte)(i ^ selector[0]);
2942
2943 else
2944 for (i=0; i<256; ++i)
2945 values[i][0] = 255; /* no transparency/tRNS chunk */
2946
2947 /* 'values' contains 256 ARGB values, but we only need 'npalette'.
2948 * 'npalette' will always be a power of 2: 2, 4, 16 or 256. In the low
2949 * bit depth cases select colors at random, else it is difficult to have
2950 * a set of low bit depth palette test with any chance of a reasonable
2951 * range of colors. Do this by randomly permuting values into the low
2952 * 'npalette' entries using an XOR mask generated here. This also
2953 * permutes the npalette == 256 case in a potentially useful way (there is
2954 * no relationship between palette index and the color value therein!)
2955 */
2956 palette = store_write_palette(ps, npalette);
2957
2958 for (i=0; i<npalette; ++i)
2959 {
2960 palette[i].alpha = values[i ^ selector[1]][0];
2961 palette[i].red = values[i ^ selector[1]][1];
2962 palette[i].green = values[i ^ selector[1]][2];
2963 palette[i].blue = values[i ^ selector[1]][3];
2964 }
2965
2966 return palette;
2967 }
2968}
2969
2970/* Initialize a standard palette on a write stream. The 'do_tRNS' argument
2971 * indicates whether or not to also set the tRNS chunk.
2972 */
2973static void
2974init_standard_palette(png_store *ps, png_structp pp, png_infop pi, int npalette,
2975 int do_tRNS)
2976{
2977 store_palette_entry *ppal = make_standard_palette(ps, npalette, do_tRNS);
2978
2979 {
2980 int i;
2981 png_color palette[256];
2982
2983 /* Set all entries to detect overread errors. */
2984 for (i=0; i<npalette; ++i)
2985 {
2986 palette[i].red = ppal[i].red;
2987 palette[i].green = ppal[i].green;
2988 palette[i].blue = ppal[i].blue;
2989 }
2990
2991 /* Just in case fill in the rest with detectable values: */
2992 for (; i<256; ++i)
2993 palette[i].red = palette[i].green = palette[i].blue = 42;
2994
2995 png_set_PLTE(pp, pi, palette, npalette);
2996 }
2997
2998 if (do_tRNS)
2999 {
3000 int i, j;
3001 png_byte tRNS[256];
3002
3003 /* Set all the entries, but skip trailing opaque entries */
3004 for (i=j=0; i<npalette; ++i)
3005 if ((tRNS[i] = ppal[i].alpha) < 255)
3006 j = i+1;
3007
3008 /* Fill in the remainder with a detectable value: */
3009 for (; i<256; ++i)
3010 tRNS[i] = 24;
3011
3012 if (j > 0)
3013 png_set_tRNS(pp, pi, tRNS, j, 0/*color*/);
3014 }
3015}
3016
3017/* The number of passes is related to the interlace type. There was no libpng
3018 * API to determine this prior to 1.5, so we need an inquiry function:
3019 */
3020static int
3021npasses_from_interlace_type(png_structp pp, int interlace_type)
3022{
3023 switch (interlace_type)
3024 {
3025 default:
3026 png_error(pp, "invalid interlace type");
3027
3028 case PNG_INTERLACE_NONE:
3029 return 1;
3030
3031 case PNG_INTERLACE_ADAM7:
3032 return PNG_INTERLACE_ADAM7_PASSES;
3033 }
3034}
3035
3036static unsigned int
3037bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth)
3038{
3039 switch (colour_type)
3040 {
3041 default: png_error(pp, "invalid color type");
3042
3043 case 0: return bit_depth;
3044
3045 case 2: return 3*bit_depth;
3046
3047 case 3: return bit_depth;
3048
3049 case 4: return 2*bit_depth;
3050
3051 case 6: return 4*bit_depth;
3052 }
3053}
3054
3055#define TRANSFORM_WIDTH 128U
3056#define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U)
3057#define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */
3058#define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */
3059#define SIZE_HEIGHTMAX 16 /* Maximum range of size images */
3060
3061static size_t
3062transform_rowsize(png_structp pp, png_byte colour_type, png_byte bit_depth)
3063{
3064 return (TRANSFORM_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8;
3065}
3066
3067/* transform_width(pp, colour_type, bit_depth) current returns the same number
3068 * every time, so just use a macro:
3069 */
3070#define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH
3071
3072static png_uint_32
3073transform_height(png_structp pp, png_byte colour_type, png_byte bit_depth)
3074{
3075 switch (bit_size(pp, colour_type, bit_depth))
3076 {
3077 case 1:
3078 case 2:
3079 case 4:
3080 return 1; /* Total of 128 pixels */
3081
3082 case 8:
3083 return 2; /* Total of 256 pixels/bytes */
3084
3085 case 16:
3086 return 512; /* Total of 65536 pixels */
3087
3088 case 24:
3089 case 32:
3090 return 512; /* 65536 pixels */
3091
3092 case 48:
3093 case 64:
3094 return 2048;/* 4 x 65536 pixels. */
3095# define TRANSFORM_HEIGHTMAX 2048
3096
3097 default:
3098 return 0; /* Error, will be caught later */
3099 }
3100}
3101
3102/* The following can only be defined here, now we have the definitions
3103 * of the transform image sizes.
3104 */
3105static png_uint_32
3106standard_width(png_structp pp, png_uint_32 id)
3107{
3108 png_uint_32 width = WIDTH_FROM_ID(id);
3109 UNUSED(pp)
3110
3111 if (width == 0)
3112 width = transform_width(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3113
3114 return width;
3115}
3116
3117static png_uint_32
3118standard_height(png_structp pp, png_uint_32 id)
3119{
3120 png_uint_32 height = HEIGHT_FROM_ID(id);
3121
3122 if (height == 0)
3123 height = transform_height(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3124
3125 return height;
3126}
3127
3128static png_uint_32
3129standard_rowsize(png_structp pp, png_uint_32 id)
3130{
3131 png_uint_32 width = standard_width(pp, id);
3132
3133 /* This won't overflow: */
3134 width *= bit_size(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3135 return (width + 7) / 8;
3136}
3137
3138static void
3139transform_row(png_structp pp, png_byte buffer[TRANSFORM_ROWMAX],
3140 png_byte colour_type, png_byte bit_depth, png_uint_32 y)
3141{
3142 png_uint_32 v = y << 7;
3143 png_uint_32 i = 0;
3144
3145 switch (bit_size(pp, colour_type, bit_depth))
3146 {
3147 case 1:
3148 while (i<128/8) buffer[i] = v & 0xff, v += 17, ++i;
3149 return;
3150
3151 case 2:
3152 while (i<128/4) buffer[i] = v & 0xff, v += 33, ++i;
3153 return;
3154
3155 case 4:
3156 while (i<128/2) buffer[i] = v & 0xff, v += 65, ++i;
3157 return;
3158
3159 case 8:
3160 /* 256 bytes total, 128 bytes in each row set as follows: */
3161 while (i<128) buffer[i] = v & 0xff, ++v, ++i;
3162 return;
3163
3164 case 16:
3165 /* Generate all 65536 pixel values in order, which includes the 8 bit
3166 * GA case as well as the 16 bit G case.
3167 */
3168 while (i<128)
3169 buffer[2*i] = (v>>8) & 0xff, buffer[2*i+1] = v & 0xff, ++v, ++i;
3170
3171 return;
3172
3173 case 24:
3174 /* 65535 pixels, but rotate the values. */
3175 while (i<128)
3176 {
3177 /* Three bytes per pixel, r, g, b, make b by r^g */
3178 buffer[3*i+0] = (v >> 8) & 0xff;
3179 buffer[3*i+1] = v & 0xff;
3180 buffer[3*i+2] = ((v >> 8) ^ v) & 0xff;
3181 ++v;
3182 ++i;
3183 }
3184
3185 return;
3186
3187 case 32:
3188 /* 65535 pixels, r, g, b, a; just replicate */
3189 while (i<128)
3190 {
3191 buffer[4*i+0] = (v >> 8) & 0xff;
3192 buffer[4*i+1] = v & 0xff;
3193 buffer[4*i+2] = (v >> 8) & 0xff;
3194 buffer[4*i+3] = v & 0xff;
3195 ++v;
3196 ++i;
3197 }
3198
3199 return;
3200
3201 case 48:
3202 /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at
3203 * each pixel, g increase by 257 (0x101) and 'b' by 0x1111:
3204 */
3205 while (i<128)
3206 {
3207 png_uint_32 t = v++;
3208 buffer[6*i+0] = (t >> 8) & 0xff;
3209 buffer[6*i+1] = t & 0xff;
3210 t *= 257;
3211 buffer[6*i+2] = (t >> 8) & 0xff;
3212 buffer[6*i+3] = t & 0xff;
3213 t *= 17;
3214 buffer[6*i+4] = (t >> 8) & 0xff;
3215 buffer[6*i+5] = t & 0xff;
3216 ++i;
3217 }
3218
3219 return;
3220
3221 case 64:
3222 /* As above in the 32 bit case. */
3223 while (i<128)
3224 {
3225 png_uint_32 t = v++;
3226 buffer[8*i+0] = (t >> 8) & 0xff;
3227 buffer[8*i+1] = t & 0xff;
3228 buffer[8*i+4] = (t >> 8) & 0xff;
3229 buffer[8*i+5] = t & 0xff;
3230 t *= 257;
3231 buffer[8*i+2] = (t >> 8) & 0xff;
3232 buffer[8*i+3] = t & 0xff;
3233 buffer[8*i+6] = (t >> 8) & 0xff;
3234 buffer[8*i+7] = t & 0xff;
3235 ++i;
3236 }
3237 return;
3238
3239 default:
3240 break;
3241 }
3242
3243 png_error(pp, "internal error");
3244}
3245
3246/* This is just to do the right cast - could be changed to a function to check
3247 * 'bd' but there isn't much point.
3248 */
3249#define DEPTH(bd) ((png_byte)(1U << (bd)))
3250
3251/* Make a standardized image given a an image colour type, bit depth and
3252 * interlace type. The standard images have a very restricted range of
3253 * rows and heights and are used for testing transforms rather than image
3254 * layout details. See make_size_images below for a way to make images
3255 * that test odd sizes along with the libpng interlace handling.
3256 */
3257static void
3258make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type,
3259 png_byte PNG_CONST bit_depth, int palette_number, int interlace_type,
3260 png_const_charp name)
3261{
3262 context(ps, fault);
3263
3264 Try
3265 {
3266 png_infop pi;
3267 png_structp pp = set_store_for_write(ps, &pi, name);
3268 png_uint_32 h;
3269
3270 /* In the event of a problem return control to the Catch statement below
3271 * to do the clean up - it is not possible to 'return' directly from a Try
3272 * block.
3273 */
3274 if (pp == NULL)
3275 Throw ps;
3276
3277 h = transform_height(pp, colour_type, bit_depth);
3278
3279 png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), h,
3280 bit_depth, colour_type, interlace_type,
3281 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
3282
3283#ifdef PNG_TEXT_SUPPORTED
3284 {
3285 static char key[] = "image name"; /* must be writeable */
3286 size_t pos;
3287 png_text text;
3288 char copy[FILE_NAME_SIZE];
3289
3290 /* Use a compressed text string to test the correct interaction of text
3291 * compression and IDAT compression.
3292 */
3293 text.compression = PNG_TEXT_COMPRESSION_zTXt;
3294 text.key = key;
3295 /* Yuck: the text must be writable! */
3296 pos = safecat(copy, sizeof copy, 0, ps->wname);
3297 text.text = copy;
3298 text.text_length = pos;
3299 text.itxt_length = 0;
3300 text.lang = 0;
3301 text.lang_key = 0;
3302
3303 png_set_text(pp, pi, &text, 1);
3304 }
3305#endif
3306
3307 if (colour_type == 3) /* palette */
3308 init_standard_palette(ps, pp, pi, 1U << bit_depth, 1/*do tRNS*/);
3309
3310 png_write_info(pp, pi);
3311
3312 if (png_get_rowbytes(pp, pi) !=
3313 transform_rowsize(pp, colour_type, bit_depth))
3314 png_error(pp, "row size incorrect");
3315
3316 else
3317 {
3318 /* Somewhat confusingly this must be called *after* png_write_info
3319 * because if it is called before, the information in *pp has not been
3320 * updated to reflect the interlaced image.
3321 */
3322 int npasses = png_set_interlace_handling(pp);
3323 int pass;
3324
3325 if (npasses != npasses_from_interlace_type(pp, interlace_type))
3326 png_error(pp, "write: png_set_interlace_handling failed");
3327
3328 for (pass=0; pass<npasses; ++pass)
3329 {
3330 png_uint_32 y;
3331
3332 for (y=0; y<h; ++y)
3333 {
3334 png_byte buffer[TRANSFORM_ROWMAX];
3335
3336 transform_row(pp, buffer, colour_type, bit_depth, y);
3337 png_write_row(pp, buffer);
3338 }
3339 }
3340 }
3341
3342#ifdef PNG_TEXT_SUPPORTED
3343 {
3344 static char key[] = "end marker";
3345 static char comment[] = "end";
3346 png_text text;
3347
3348 /* Use a compressed text string to test the correct interaction of text
3349 * compression and IDAT compression.
3350 */
3351 text.compression = PNG_TEXT_COMPRESSION_zTXt;
3352 text.key = key;
3353 text.text = comment;
3354 text.text_length = (sizeof comment)-1;
3355 text.itxt_length = 0;
3356 text.lang = 0;
3357 text.lang_key = 0;
3358
3359 png_set_text(pp, pi, &text, 1);
3360 }
3361#endif
3362
3363 png_write_end(pp, pi);
3364
3365 /* And store this under the appropriate id, then clean up. */
3366 store_storefile(ps, FILEID(colour_type, bit_depth, palette_number,
3367 interlace_type, 0, 0, 0));
3368
3369 store_write_reset(ps);
3370 }
3371
3372 Catch(fault)
3373 {
3374 /* Use the png_store returned by the exception. This may help the compiler
3375 * because 'ps' is not used in this branch of the setjmp. Note that fault
3376 * and ps will always be the same value.
3377 */
3378 store_write_reset(fault);
3379 }
3380}
3381
3382static void
3383make_transform_images(png_store *ps)
3384{
3385 png_byte colour_type = 0;
3386 png_byte bit_depth = 0;
3387 int palette_number = 0;
3388
3389 /* This is in case of errors. */
3390 safecat(ps->test, sizeof ps->test, 0, "make standard images");
3391
3392 /* Use next_format to enumerate all the combinations we test, including
3393 * generating multiple low bit depth palette images.
3394 */
3395 while (next_format(&colour_type, &bit_depth, &palette_number))
3396 {
3397 int interlace_type;
3398
3399 for (interlace_type = PNG_INTERLACE_NONE;
3400 interlace_type < PNG_INTERLACE_LAST; ++interlace_type)
3401 {
3402 char name[FILE_NAME_SIZE];
3403
3404 standard_name(name, sizeof name, 0, colour_type, bit_depth,
3405 palette_number, interlace_type, 0, 0, 0);
3406 make_transform_image(ps, colour_type, bit_depth, palette_number,
3407 interlace_type, name);
3408 }
3409 }
3410}
3411
3412/* The following two routines use the PNG interlace support macros from
3413 * png.h to interlace or deinterlace rows.
3414 */
3415static void
3416interlace_row(png_bytep buffer, png_const_bytep imageRow,
3417 unsigned int pixel_size, png_uint_32 w, int pass)
3418{
3419 png_uint_32 xin, xout, xstep;
3420
3421 /* Note that this can, trivially, be optimized to a memcpy on pass 7, the
3422 * code is presented this way to make it easier to understand. In practice
3423 * consult the code in the libpng source to see other ways of doing this.
3424 */
3425 xin = PNG_PASS_START_COL(pass);
3426 xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
3427
3428 for (xout=0; xin<w; xin+=xstep)
3429 {
3430 pixel_copy(buffer, xout, imageRow, xin, pixel_size);
3431 ++xout;
3432 }
3433}
3434
3435static void
3436deinterlace_row(png_bytep buffer, png_const_bytep row,
3437 unsigned int pixel_size, png_uint_32 w, int pass)
3438{
3439 /* The inverse of the above, 'row' is part of row 'y' of the output image,
3440 * in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute
3441 * the pixels of row into buffer and return the number written (to allow
3442 * this to be checked).
3443 */
3444 png_uint_32 xin, xout, xstep;
3445
3446 xout = PNG_PASS_START_COL(pass);
3447 xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
3448
3449 for (xin=0; xout<w; xout+=xstep)
3450 {
3451 pixel_copy(buffer, xout, row, xin, pixel_size);
3452 ++xin;
3453 }
3454}
3455
3456/* Build a single row for the 'size' test images; this fills in only the
3457 * first bit_width bits of the sample row.
3458 */
3459static void
3460size_row(png_byte buffer[SIZE_ROWMAX], png_uint_32 bit_width, png_uint_32 y)
3461{
3462 /* height is in the range 1 to 16, so: */
3463 y = ((y & 1) << 7) + ((y & 2) << 6) + ((y & 4) << 5) + ((y & 8) << 4);
3464 /* the following ensures bits are set in small images: */
3465 y ^= 0xA5;
3466
3467 while (bit_width >= 8)
3468 *buffer++ = (png_byte)y++, bit_width -= 8;
3469
3470 /* There may be up to 7 remaining bits, these go in the most significant
3471 * bits of the byte.
3472 */
3473 if (bit_width > 0)
3474 {
3475 png_uint_32 mask = (1U<<(8-bit_width))-1;
3476 *buffer = (png_byte)((*buffer & mask) | (y & ~mask));
3477 }
3478}
3479
3480static void
3481make_size_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type,
3482 png_byte PNG_CONST bit_depth, int PNG_CONST interlace_type,
3483 png_uint_32 PNG_CONST w, png_uint_32 PNG_CONST h,
3484 int PNG_CONST do_interlace)
3485{
3486 context(ps, fault);
3487
3488 Try
3489 {
3490 png_infop pi;
3491 png_structp pp;
3492 unsigned int pixel_size;
3493
3494 /* Make a name and get an appropriate id for the store: */
3495 char name[FILE_NAME_SIZE];
3496 PNG_CONST png_uint_32 id = FILEID(colour_type, bit_depth, 0/*palette*/,
3497 interlace_type, w, h, do_interlace);
3498
3499 standard_name_from_id(name, sizeof name, 0, id);
3500 pp = set_store_for_write(ps, &pi, name);
3501
3502 /* In the event of a problem return control to the Catch statement below
3503 * to do the clean up - it is not possible to 'return' directly from a Try
3504 * block.
3505 */
3506 if (pp == NULL)
3507 Throw ps;
3508
3509 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type,
3510 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
3511
3512 if (colour_type == 3) /* palette */
3513 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/);
3514
3515 png_write_info(pp, pi);
3516
3517 /* Calculate the bit size, divide by 8 to get the byte size - this won't
3518 * overflow because we know the w values are all small enough even for
3519 * a system where 'unsigned int' is only 16 bits.
3520 */
3521 pixel_size = bit_size(pp, colour_type, bit_depth);
3522 if (png_get_rowbytes(pp, pi) != ((w * pixel_size) + 7) / 8)
3523 png_error(pp, "row size incorrect");
3524
3525 else
3526 {
3527 int npasses = npasses_from_interlace_type(pp, interlace_type);
3528 png_uint_32 y;
3529 int pass;
3530 png_byte image[16][SIZE_ROWMAX];
3531
3532 /* To help consistent error detection make the parts of this buffer
3533 * that aren't set below all '1':
3534 */
3535 memset(image, 0xff, sizeof image);
3536
3537 if (!do_interlace && npasses != png_set_interlace_handling(pp))
3538 png_error(pp, "write: png_set_interlace_handling failed");
3539
3540 /* Prepare the whole image first to avoid making it 7 times: */
3541 for (y=0; y<h; ++y)
3542 size_row(image[y], w * pixel_size, y);
3543
3544 for (pass=0; pass<npasses; ++pass)
3545 {
3546 /* The following two are for checking the macros: */
3547 PNG_CONST png_uint_32 wPass = PNG_PASS_COLS(w, pass);
3548
3549 /* If do_interlace is set we don't call png_write_row for every
3550 * row because some of them are empty. In fact, for a 1x1 image,
3551 * most of them are empty!
3552 */
3553 for (y=0; y<h; ++y)
3554 {
3555 png_const_bytep row = image[y];
3556 png_byte tempRow[SIZE_ROWMAX];
3557
3558 /* If do_interlace *and* the image is interlaced we
3559 * need a reduced interlace row; this may be reduced
3560 * to empty.
3561 */
3562 if (do_interlace && interlace_type == PNG_INTERLACE_ADAM7)
3563 {
3564 /* The row must not be written if it doesn't exist, notice
3565 * that there are two conditions here, either the row isn't
3566 * ever in the pass or the row would be but isn't wide
3567 * enough to contribute any pixels. In fact the wPass test
3568 * can be used to skip the whole y loop in this case.
3569 */
3570 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) && wPass > 0)
3571 {
3572 /* Set to all 1's for error detection (libpng tends to
3573 * set unset things to 0).
3574 */
3575 memset(tempRow, 0xff, sizeof tempRow);
3576 interlace_row(tempRow, row, pixel_size, w, pass);
3577 row = tempRow;
3578 }
3579 else
3580 continue;
3581 }
3582
3583 /* Only get to here if the row has some pixels in it. */
3584 png_write_row(pp, row);
3585 }
3586 }
3587 }
3588
3589 png_write_end(pp, pi);
3590
3591 /* And store this under the appropriate id, then clean up. */
3592 store_storefile(ps, id);
3593
3594 store_write_reset(ps);
3595 }
3596
3597 Catch(fault)
3598 {
3599 /* Use the png_store returned by the exception. This may help the compiler
3600 * because 'ps' is not used in this branch of the setjmp. Note that fault
3601 * and ps will always be the same value.
3602 */
3603 store_write_reset(fault);
3604 }
3605}
3606
3607static void
3608make_size(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, int bdlo,
3609 int PNG_CONST bdhi)
3610{
3611 for (; bdlo <= bdhi; ++bdlo)
3612 {
3613 png_uint_32 width;
3614
3615 for (width = 1; width <= 16; ++width)
3616 {
3617 png_uint_32 height;
3618
3619 for (height = 1; height <= 16; ++height)
3620 {
3621 /* The four combinations of DIY interlace and interlace or not -
3622 * no interlace + DIY should be identical to no interlace with
3623 * libpng doing it.
3624 */
3625 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE,
3626 width, height, 0);
3627 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE,
3628 width, height, 1);
3629 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7,
3630 width, height, 0);
3631 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7,
3632 width, height, 1);
3633 }
3634 }
3635 }
3636}
3637
3638static void
3639make_size_images(png_store *ps)
3640{
3641 /* This is in case of errors. */
3642 safecat(ps->test, sizeof ps->test, 0, "make size images");
3643
3644 /* Arguments are colour_type, low bit depth, high bit depth
3645 */
3646 make_size(ps, 0, 0, WRITE_BDHI);
3647 make_size(ps, 2, 3, WRITE_BDHI);
3648 make_size(ps, 3, 0, 3 /*palette: max 8 bits*/);
3649 make_size(ps, 4, 3, WRITE_BDHI);
3650 make_size(ps, 6, 3, WRITE_BDHI);
3651}
3652
3653/* Return a row based on image id and 'y' for checking: */
3654static void
3655standard_row(png_structp pp, png_byte std[STANDARD_ROWMAX], png_uint_32 id,
3656 png_uint_32 y)
3657{
3658 if (WIDTH_FROM_ID(id) == 0)
3659 transform_row(pp, std, COL_FROM_ID(id), DEPTH_FROM_ID(id), y);
3660 else
3661 size_row(std, WIDTH_FROM_ID(id) * bit_size(pp, COL_FROM_ID(id),
3662 DEPTH_FROM_ID(id)), y);
3663}
3664
3665/* Tests - individual test cases */
3666/* Like 'make_standard' but errors are deliberately introduced into the calls
3667 * to ensure that they get detected - it should not be possible to write an
3668 * invalid image with libpng!
3669 */
3670#ifdef PNG_WARNINGS_SUPPORTED
3671static void
3672sBIT0_error_fn(png_structp pp, png_infop pi)
3673{
3674 /* 0 is invalid... */
3675 png_color_8 bad;
3676 bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 0;
3677 png_set_sBIT(pp, pi, &bad);
3678}
3679
3680static void
3681sBIT_error_fn(png_structp pp, png_infop pi)
3682{
3683 png_byte bit_depth;
3684 png_color_8 bad;
3685
3686 if (png_get_color_type(pp, pi) == PNG_COLOR_TYPE_PALETTE)
3687 bit_depth = 8;
3688
3689 else
3690 bit_depth = png_get_bit_depth(pp, pi);
3691
3692 /* Now we know the bit depth we can easily generate an invalid sBIT entry */
3693 bad.red = bad.green = bad.blue = bad.gray = bad.alpha =
3694 (png_byte)(bit_depth+1);
3695 png_set_sBIT(pp, pi, &bad);
3696}
3697
3698static PNG_CONST struct
3699{
3700 void (*fn)(png_structp, png_infop);
3701 PNG_CONST char *msg;
3702 unsigned int warning :1; /* the error is a warning... */
3703} error_test[] =
3704 {
3705 /* no warnings makes these errors undetectable. */
3706 { sBIT0_error_fn, "sBIT(0): failed to detect error", 1 },
3707 { sBIT_error_fn, "sBIT(too big): failed to detect error", 1 },
3708 };
3709
3710static void
3711make_error(png_store* volatile psIn, png_byte PNG_CONST colour_type,
3712 png_byte bit_depth, int interlace_type, int test, png_const_charp name)
3713{
3714 png_store * volatile ps = psIn;
3715
3716 context(ps, fault);
3717
3718 Try
3719 {
3720 png_structp pp;
3721 png_infop pi;
3722
3723 pp = set_store_for_write(ps, &pi, name);
3724
3725 if (pp == NULL)
3726 Throw ps;
3727
3728 png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth),
3729 transform_height(pp, colour_type, bit_depth), bit_depth, colour_type,
3730 interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
3731
3732 if (colour_type == 3) /* palette */
3733 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/);
3734
3735 /* Time for a few errors; these are in various optional chunks, the
3736 * standard tests test the standard chunks pretty well.
3737 */
3738# define exception__prev exception_prev_1
3739# define exception__env exception_env_1
3740 Try
3741 {
3742 /* Expect this to throw: */
3743 ps->expect_error = !error_test[test].warning;
3744 ps->expect_warning = error_test[test].warning;
3745 ps->saw_warning = 0;
3746 error_test[test].fn(pp, pi);
3747
3748 /* Normally the error is only detected here: */
3749 png_write_info(pp, pi);
3750
3751 /* And handle the case where it was only a warning: */
3752 if (ps->expect_warning && ps->saw_warning)
3753 Throw ps;
3754
3755 /* If we get here there is a problem, we have success - no error or
3756 * no warning - when we shouldn't have success. Log an error.
3757 */
3758 store_log(ps, pp, error_test[test].msg, 1 /*error*/);
3759 }
3760
3761 Catch (fault)
3762 ps = fault; /* expected exit, make sure ps is not clobbered */
3763#undef exception__prev
3764#undef exception__env
3765
3766 /* And clear these flags */
3767 ps->expect_error = 0;
3768 ps->expect_warning = 0;
3769
3770 /* Now write the whole image, just to make sure that the detected, or
3771 * undetected, errro has not created problems inside libpng.
3772 */
3773 if (png_get_rowbytes(pp, pi) !=
3774 transform_rowsize(pp, colour_type, bit_depth))
3775 png_error(pp, "row size incorrect");
3776
3777 else
3778 {
3779 png_uint_32 h = transform_height(pp, colour_type, bit_depth);
3780 int npasses = png_set_interlace_handling(pp);
3781 int pass;
3782
3783 if (npasses != npasses_from_interlace_type(pp, interlace_type))
3784 png_error(pp, "write: png_set_interlace_handling failed");
3785
3786 for (pass=0; pass<npasses; ++pass)
3787 {
3788 png_uint_32 y;
3789
3790 for (y=0; y<h; ++y)
3791 {
3792 png_byte buffer[TRANSFORM_ROWMAX];
3793
3794 transform_row(pp, buffer, colour_type, bit_depth, y);
3795 png_write_row(pp, buffer);
3796 }
3797 }
3798 }
3799
3800 png_write_end(pp, pi);
3801
3802 /* The following deletes the file that was just written. */
3803 store_write_reset(ps);
3804 }
3805
3806 Catch(fault)
3807 {
3808 store_write_reset(fault);
3809 }
3810}
3811
3812static int
3813make_errors(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type,
3814 int bdlo, int PNG_CONST bdhi)
3815{
3816 for (; bdlo <= bdhi; ++bdlo)
3817 {
3818 int interlace_type;
3819
3820 for (interlace_type = PNG_INTERLACE_NONE;
3821 interlace_type < PNG_INTERLACE_LAST; ++interlace_type)
3822 {
3823 unsigned int test;
3824 char name[FILE_NAME_SIZE];
3825
3826 standard_name(name, sizeof name, 0, colour_type, 1<<bdlo, 0,
3827 interlace_type, 0, 0, 0);
3828
3829 for (test=0; test<(sizeof error_test)/(sizeof error_test[0]); ++test)
3830 {
3831 make_error(&pm->this, colour_type, DEPTH(bdlo), interlace_type,
3832 test, name);
3833
3834 if (fail(pm))
3835 return 0;
3836 }
3837 }
3838 }
3839
3840 return 1; /* keep going */
3841}
3842#endif
3843
3844static void
3845perform_error_test(png_modifier *pm)
3846{
3847#ifdef PNG_WARNINGS_SUPPORTED /* else there are no cases that work! */
3848 /* Need to do this here because we just write in this test. */
3849 safecat(pm->this.test, sizeof pm->this.test, 0, "error test");
3850
3851 if (!make_errors(pm, 0, 0, WRITE_BDHI))
3852 return;
3853
3854 if (!make_errors(pm, 2, 3, WRITE_BDHI))
3855 return;
3856
3857 if (!make_errors(pm, 3, 0, 3))
3858 return;
3859
3860 if (!make_errors(pm, 4, 3, WRITE_BDHI))
3861 return;
3862
3863 if (!make_errors(pm, 6, 3, WRITE_BDHI))
3864 return;
3865#else
3866 UNUSED(pm)
3867#endif
3868}
3869
3870/* This is just to validate the internal PNG formatting code - if this fails
3871 * then the warning messages the library outputs will probably be garbage.
3872 */
3873static void
3874perform_formatting_test(png_store *volatile ps)
3875{
3876#ifdef PNG_TIME_RFC1123_SUPPORTED
3877 /* The handle into the formatting code is the RFC1123 support; this test does
3878 * nothing if that is compiled out.
3879 */
3880 context(ps, fault);
3881
3882 Try
3883 {
3884 png_const_charp correct = "29 Aug 2079 13:53:60 +0000";
3885 png_const_charp result;
3886 png_structp pp;
3887 png_time pt;
3888
3889 pp = set_store_for_write(ps, NULL, "libpng formatting test");
3890
3891 if (pp == NULL)
3892 Throw ps;
3893
3894
3895 /* Arbitrary settings: */
3896 pt.year = 2079;
3897 pt.month = 8;
3898 pt.day = 29;
3899 pt.hour = 13;
3900 pt.minute = 53;
3901 pt.second = 60; /* a leap second */
3902
3903 result = png_convert_to_rfc1123(pp, &pt);
3904
3905 if (result == NULL)
3906 png_error(pp, "png_convert_to_rfc1123 failed");
3907
3908 if (strcmp(result, correct) != 0)
3909 {
3910 size_t pos = 0;
3911 char msg[128];
3912
3913 pos = safecat(msg, sizeof msg, pos, "png_convert_to_rfc1123(");
3914 pos = safecat(msg, sizeof msg, pos, correct);
3915 pos = safecat(msg, sizeof msg, pos, ") returned: '");
3916 pos = safecat(msg, sizeof msg, pos, result);
3917 pos = safecat(msg, sizeof msg, pos, "'");
3918
3919 png_error(pp, msg);
3920 }
3921
3922 store_write_reset(ps);
3923 }
3924
3925 Catch(fault)
3926 {
3927 store_write_reset(fault);
3928 }
3929#else
3930 UNUSED(ps)
3931#endif
3932}
3933
3934/* Because we want to use the same code in both the progressive reader and the
3935 * sequential reader it is necessary to deal with the fact that the progressive
3936 * reader callbacks only have one parameter (png_get_progressive_ptr()), so this
3937 * must contain all the test parameters and all the local variables directly
3938 * accessible to the sequential reader implementation.
3939 *
3940 * The technique adopted is to reinvent part of what Dijkstra termed a
3941 * 'display'; an array of pointers to the stack frames of enclosing functions so
3942 * that a nested function definition can access the local (C auto) variables of
3943 * the functions that contain its definition. In fact C provides the first
3944 * pointer (the local variables - the stack frame pointer) and the last (the
3945 * global variables - the BCPL global vector typically implemented as global
3946 * addresses), this code requires one more pointer to make the display - the
3947 * local variables (and function call parameters) of the function that actually
3948 * invokes either the progressive or sequential reader.
3949 *
3950 * Perhaps confusingly this technique is confounded with classes - the
3951 * 'standard_display' defined here is sub-classed as the 'gamma_display' below.
3952 * A gamma_display is a standard_display, taking advantage of the ANSI-C
3953 * requirement that the pointer to the first member of a structure must be the
3954 * same as the pointer to the structure. This allows us to reuse standard_
3955 * functions in the gamma test code; something that could not be done with
3956 * nested functions!
3957 */
3958typedef struct standard_display
3959{
3960 png_store* ps; /* Test parameters (passed to the function) */
3961 png_byte colour_type;
3962 png_byte bit_depth;
3963 png_byte red_sBIT; /* Input data sBIT values. */
3964 png_byte green_sBIT;
3965 png_byte blue_sBIT;
3966 png_byte alpha_sBIT;
3967 int interlace_type;
3968 png_uint_32 id; /* Calculated file ID */
3969 png_uint_32 w; /* Width of image */
3970 png_uint_32 h; /* Height of image */
3971 int npasses; /* Number of interlaced passes */
3972 png_uint_32 pixel_size; /* Width of one pixel in bits */
3973 png_uint_32 bit_width; /* Width of output row in bits */
3974 size_t cbRow; /* Bytes in a row of the output image */
3975 int do_interlace; /* Do interlacing internally */
3976 int is_transparent; /* Transparency information was present. */
3977 int speed; /* Doing a speed test */
3978 int use_update_info;/* Call update_info, not start_image */
3979 struct
3980 {
3981 png_uint_16 red;
3982 png_uint_16 green;
3983 png_uint_16 blue;
3984 } transparent; /* The transparent color, if set. */
3985 int npalette; /* Number of entries in the palette. */
3986 store_palette
3987 palette;
3988} standard_display;
3989
3990static void
3991standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id,
3992 int do_interlace, int use_update_info)
3993{
3994 memset(dp, 0, sizeof *dp);
3995
3996 dp->ps = ps;
3997 dp->colour_type = COL_FROM_ID(id);
3998 dp->bit_depth = DEPTH_FROM_ID(id);
3999 if (dp->bit_depth < 1 || dp->bit_depth > 16)
4000 internal_error(ps, "internal: bad bit depth");
4001 if (dp->colour_type == 3)
4002 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8;
4003 else
4004 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT =
4005 dp->bit_depth;
4006 dp->interlace_type = INTERLACE_FROM_ID(id);
4007 dp->id = id;
4008 /* All the rest are filled in after the read_info: */
4009 dp->w = 0;
4010 dp->h = 0;
4011 dp->npasses = 0;
4012 dp->pixel_size = 0;
4013 dp->bit_width = 0;
4014 dp->cbRow = 0;
4015 dp->do_interlace = do_interlace;
4016 dp->is_transparent = 0;
4017 dp->speed = ps->speed;
4018 dp->use_update_info = use_update_info;
4019 dp->npalette = 0;
4020 /* Preset the transparent color to black: */
4021 memset(&dp->transparent, 0, sizeof dp->transparent);
4022 /* Preset the palette to full intensity/opaque througout: */
4023 memset(dp->palette, 0xff, sizeof dp->palette);
4024}
4025
4026/* Initialize the palette fields - this must be done later because the palette
4027 * comes from the particular png_store_file that is selected.
4028 */
4029static void
4030standard_palette_init(standard_display *dp)
4031{
4032 store_palette_entry *palette = store_current_palette(dp->ps, &dp->npalette);
4033
4034 /* The remaining entries remain white/opaque. */
4035 if (dp->npalette > 0)
4036 {
4037 int i = dp->npalette;
4038 memcpy(dp->palette, palette, i * sizeof *palette);
4039
4040 /* Check for a non-opaque palette entry: */
4041 while (--i >= 0)
4042 if (palette[i].alpha < 255)
4043 break;
4044
4045# ifdef __GNUC__
4046 /* GCC can't handle the more obviously optimizable version. */
4047 if (i >= 0)
4048 dp->is_transparent = 1;
4049 else
4050 dp->is_transparent = 0;
4051# else
4052 dp->is_transparent = (i >= 0);
4053# endif
4054 }
4055}
4056
4057/* Utility to read the palette from the PNG file and convert it into
4058 * store_palette format. This returns 1 if there is any transparency in the
4059 * palette (it does not check for a transparent colour in the non-palette case.)
4060 */
4061static int
4062read_palette(store_palette palette, int *npalette, png_structp pp, png_infop pi)
4063{
4064 png_colorp pal;
4065 png_bytep trans_alpha;
4066 int num;
4067
4068 pal = 0;
4069 *npalette = -1;
4070
4071 if (png_get_PLTE(pp, pi, &pal, npalette) & PNG_INFO_PLTE)
4072 {
4073 int i = *npalette;
4074
4075 if (i <= 0 || i > 256)
4076 png_error(pp, "validate: invalid PLTE count");
4077
4078 while (--i >= 0)
4079 {
4080 palette[i].red = pal[i].red;
4081 palette[i].green = pal[i].green;
4082 palette[i].blue = pal[i].blue;
4083 }
4084
4085 /* Mark the remainder of the entries with a flag value (other than
4086 * white/opaque which is the flag value stored above.)
4087 */
4088 memset(palette + *npalette, 126, (256-*npalette) * sizeof *palette);
4089 }
4090
4091 else /* !png_get_PLTE */
4092 {
4093 if (*npalette != (-1))
4094 png_error(pp, "validate: invalid PLTE result");
4095 /* But there is no palette, so record this: */
4096 *npalette = 0;
4097 memset(palette, 113, sizeof (store_palette));
4098 }
4099
4100 trans_alpha = 0;
4101 num = 2; /* force error below */
4102 if ((png_get_tRNS(pp, pi, &trans_alpha, &num, 0) & PNG_INFO_tRNS) != 0 &&
4103 (trans_alpha != NULL || num != 1/*returns 1 for a transparent color*/) &&
4104 /* Oops, if a palette tRNS gets expanded png_read_update_info (at least so
4105 * far as 1.5.4) does not remove the trans_alpha pointer, only num_trans,
4106 * so in the above call we get a success, we get a pointer (who knows what
4107 * to) and we get num_trans == 0:
4108 */
4109 !(trans_alpha != NULL && num == 0)) /* TODO: fix this in libpng. */
4110 {
4111 int i;
4112
4113 /* Any of these are crash-worthy - given the implementation of
4114 * png_get_tRNS up to 1.5 an app won't crash if it just checks the
4115 * result above and fails to check that the variables it passed have
4116 * actually been filled in! Note that if the app were to pass the
4117 * last, png_color_16p, variable too it couldn't rely on this.
4118 */
4119 if (trans_alpha == NULL || num <= 0 || num > 256 || num > *npalette)
4120 png_error(pp, "validate: unexpected png_get_tRNS (palette) result");
4121
4122 for (i=0; i<num; ++i)
4123 palette[i].alpha = trans_alpha[i];
4124
4125 for (num=*npalette; i<num; ++i)
4126 palette[i].alpha = 255;
4127
4128 for (; i<256; ++i)
4129 palette[i].alpha = 33; /* flag value */
4130
4131 return 1; /* transparency */
4132 }
4133
4134 else
4135 {
4136 /* No palette transparency - just set the alpha channel to opaque. */
4137 int i;
4138
4139 for (i=0, num=*npalette; i<num; ++i)
4140 palette[i].alpha = 255;
4141
4142 for (; i<256; ++i)
4143 palette[i].alpha = 55; /* flag value */
4144
4145 return 0; /* no transparency */
4146 }
4147}
4148
4149/* Utility to validate the palette if it should not have changed (the
4150 * non-transform case).
4151 */
4152static void
4153standard_palette_validate(standard_display *dp, png_structp pp, png_infop pi)
4154{
4155 int npalette;
4156 store_palette palette;
4157
4158 if (read_palette(palette, &npalette, pp, pi) != dp->is_transparent)
4159 png_error(pp, "validate: palette transparency changed");
4160
4161 if (npalette != dp->npalette)
4162 {
4163 size_t pos = 0;
4164 char msg[64];
4165
4166 pos = safecat(msg, sizeof msg, pos, "validate: palette size changed: ");
4167 pos = safecatn(msg, sizeof msg, pos, dp->npalette);
4168 pos = safecat(msg, sizeof msg, pos, " -> ");
4169 pos = safecatn(msg, sizeof msg, pos, npalette);
4170 png_error(pp, msg);
4171 }
4172
4173 {
4174 int i = npalette; /* npalette is aliased */
4175
4176 while (--i >= 0)
4177 if (palette[i].red != dp->palette[i].red ||
4178 palette[i].green != dp->palette[i].green ||
4179 palette[i].blue != dp->palette[i].blue ||
4180 palette[i].alpha != dp->palette[i].alpha)
4181 png_error(pp, "validate: PLTE or tRNS chunk changed");
4182 }
4183}
4184
4185/* By passing a 'standard_display' the progressive callbacks can be used
4186 * directly by the sequential code, the functions suffixed "_imp" are the
4187 * implementations, the functions without the suffix are the callbacks.
4188 *
4189 * The code for the info callback is split into two because this callback calls
4190 * png_read_update_info or png_start_read_image and what gets called depends on
4191 * whether the info needs updating (we want to test both calls in pngvalid.)
4192 */
4193static void
4194standard_info_part1(standard_display *dp, png_structp pp, png_infop pi)
4195{
4196 if (png_get_bit_depth(pp, pi) != dp->bit_depth)
4197 png_error(pp, "validate: bit depth changed");
4198
4199 if (png_get_color_type(pp, pi) != dp->colour_type)
4200 png_error(pp, "validate: color type changed");
4201
4202 if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE)
4203 png_error(pp, "validate: filter type changed");
4204
4205 if (png_get_interlace_type(pp, pi) != dp->interlace_type)
4206 png_error(pp, "validate: interlacing changed");
4207
4208 if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE)
4209 png_error(pp, "validate: compression type changed");
4210
4211 dp->w = png_get_image_width(pp, pi);
4212
4213 if (dp->w != standard_width(pp, dp->id))
4214 png_error(pp, "validate: image width changed");
4215
4216 dp->h = png_get_image_height(pp, pi);
4217
4218 if (dp->h != standard_height(pp, dp->id))
4219 png_error(pp, "validate: image height changed");
4220
4221 /* Record (but don't check at present) the input sBIT according to the colour
4222 * type information.
4223 */
4224 {
4225 png_color_8p sBIT = 0;
4226
4227 if (png_get_sBIT(pp, pi, &sBIT) & PNG_INFO_sBIT)
4228 {
4229 int sBIT_invalid = 0;
4230
4231 if (sBIT == 0)
4232 png_error(pp, "validate: unexpected png_get_sBIT result");
4233
4234 if (dp->colour_type & PNG_COLOR_MASK_COLOR)
4235 {
4236 if (sBIT->red == 0 || sBIT->red > dp->bit_depth)
4237 sBIT_invalid = 1;
4238 else
4239 dp->red_sBIT = sBIT->red;
4240
4241 if (sBIT->green == 0 || sBIT->green > dp->bit_depth)
4242 sBIT_invalid = 1;
4243 else
4244 dp->green_sBIT = sBIT->green;
4245
4246 if (sBIT->blue == 0 || sBIT->blue > dp->bit_depth)
4247 sBIT_invalid = 1;
4248 else
4249 dp->blue_sBIT = sBIT->blue;
4250 }
4251
4252 else /* !COLOR */
4253 {
4254 if (sBIT->gray == 0 || sBIT->gray > dp->bit_depth)
4255 sBIT_invalid = 1;
4256 else
4257 dp->blue_sBIT = dp->green_sBIT = dp->red_sBIT = sBIT->gray;
4258 }
4259
4260 /* All 8 bits in tRNS for a palette image are significant - see the
4261 * spec.
4262 */
4263 if (dp->colour_type & PNG_COLOR_MASK_ALPHA)
4264 {
4265 if (sBIT->alpha == 0 || sBIT->alpha > dp->bit_depth)
4266 sBIT_invalid = 1;
4267 else
4268 dp->alpha_sBIT = sBIT->alpha;
4269 }
4270
4271 if (sBIT_invalid)
4272 png_error(pp, "validate: sBIT value out of range");
4273 }
4274 }
4275
4276 /* Important: this is validating the value *before* any transforms have been
4277 * put in place. It doesn't matter for the standard tests, where there are
4278 * no transforms, but it does for other tests where rowbytes may change after
4279 * png_read_update_info.
4280 */
4281 if (png_get_rowbytes(pp, pi) != standard_rowsize(pp, dp->id))
4282 png_error(pp, "validate: row size changed");
4283
4284 /* Validate the colour type 3 palette (this can be present on other color
4285 * types.)
4286 */
4287 standard_palette_validate(dp, pp, pi);
4288
4289 /* In any case always check for a tranparent color (notice that the
4290 * colour type 3 case must not give a successful return on the get_tRNS call
4291 * with these arguments!)
4292 */
4293 {
4294 png_color_16p trans_color = 0;
4295
4296 if (png_get_tRNS(pp, pi, 0, 0, &trans_color) & PNG_INFO_tRNS)
4297 {
4298 if (trans_color == 0)
4299 png_error(pp, "validate: unexpected png_get_tRNS (color) result");
4300
4301 switch (dp->colour_type)
4302 {
4303 case 0:
4304 dp->transparent.red = dp->transparent.green = dp->transparent.blue =
4305 trans_color->gray;
4306 dp->is_transparent = 1;
4307 break;
4308
4309 case 2:
4310 dp->transparent.red = trans_color->red;
4311 dp->transparent.green = trans_color->green;
4312 dp->transparent.blue = trans_color->blue;
4313 dp->is_transparent = 1;
4314 break;
4315
4316 case 3:
4317 /* Not expected because it should result in the array case
4318 * above.
4319 */
4320 png_error(pp, "validate: unexpected png_get_tRNS result");
4321 break;
4322
4323 default:
4324 png_error(pp, "validate: invalid tRNS chunk with alpha image");
4325 }
4326 }
4327 }
4328
4329 /* Read the number of passes - expected to match the value used when
4330 * creating the image (interlaced or not). This has the side effect of
4331 * turning on interlace handling (if do_interlace is not set.)
4332 */
4333 dp->npasses = npasses_from_interlace_type(pp, dp->interlace_type);
4334 if (!dp->do_interlace && dp->npasses != png_set_interlace_handling(pp))
4335 png_error(pp, "validate: file changed interlace type");
4336
4337 /* Caller calls png_read_update_info or png_start_read_image now, then calls
4338 * part2.
4339 */
4340}
4341
4342/* This must be called *after* the png_read_update_info call to get the correct
4343 * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed
4344 * image.
4345 */
4346static void
4347standard_info_part2(standard_display *dp, png_structp pp, png_infop pi,
4348 int nImages)
4349{
4350 /* Record cbRow now that it can be found. */
4351 dp->pixel_size = bit_size(pp, png_get_color_type(pp, pi),
4352 png_get_bit_depth(pp, pi));
4353 dp->bit_width = png_get_image_width(pp, pi) * dp->pixel_size;
4354 dp->cbRow = png_get_rowbytes(pp, pi);
4355
4356 /* Validate the rowbytes here again. */
4357 if (dp->cbRow != (dp->bit_width+7)/8)
4358 png_error(pp, "bad png_get_rowbytes calculation");
4359
4360 /* Then ensure there is enough space for the output image(s). */
4361 store_ensure_image(dp->ps, pp, nImages, dp->cbRow, dp->h);
4362}
4363
4364static void
4365standard_info_imp(standard_display *dp, png_structp pp, png_infop pi,
4366 int nImages)
4367{
4368 /* Note that the validation routine has the side effect of turning on
4369 * interlace handling in the subsequent code.
4370 */
4371 standard_info_part1(dp, pp, pi);
4372
4373 /* And the info callback has to call this (or png_read_update_info - see
4374 * below in the png_modifier code for that variant.
4375 */
4376 if (dp->use_update_info)
4377 {
4378 /* For debugging the effect of multiple calls: */
4379 int i = dp->use_update_info;
4380 while (i-- > 0)
4381 png_read_update_info(pp, pi);
4382 }
4383
4384 else
4385 png_start_read_image(pp);
4386
4387 /* Validate the height, width and rowbytes plus ensure that sufficient buffer
4388 * exists for decoding the image.
4389 */
4390 standard_info_part2(dp, pp, pi, nImages);
4391}
4392
4393static void
4394standard_info(png_structp pp, png_infop pi)
4395{
4396 standard_display *dp = voidcast(standard_display*,
4397 png_get_progressive_ptr(pp));
4398
4399 /* Call with nImages==1 because the progressive reader can only produce one
4400 * image.
4401 */
4402 standard_info_imp(dp, pp, pi, 1 /*only one image*/);
4403}
4404
4405static void
4406progressive_row(png_structp pp, png_bytep new_row, png_uint_32 y, int pass)
4407{
4408 PNG_CONST standard_display *dp = voidcast(standard_display*,
4409 png_get_progressive_ptr(pp));
4410
4411 /* When handling interlacing some rows will be absent in each pass, the
4412 * callback still gets called, but with a NULL pointer. This is checked
4413 * in the 'else' clause below. We need our own 'cbRow', but we can't call
4414 * png_get_rowbytes because we got no info structure.
4415 */
4416 if (new_row != NULL)
4417 {
4418 png_bytep row;
4419
4420 /* In the case where the reader doesn't do the interlace it gives
4421 * us the y in the sub-image:
4422 */
4423 if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7)
4424 {
4425#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
4426 /* Use this opportunity to validate the png 'current' APIs: */
4427 if (y != png_get_current_row_number(pp))
4428 png_error(pp, "png_get_current_row_number is broken");
4429
4430 if (pass != png_get_current_pass_number(pp))
4431 png_error(pp, "png_get_current_pass_number is broken");
4432#endif
4433
4434 y = PNG_ROW_FROM_PASS_ROW(y, pass);
4435 }
4436
4437 /* Validate this just in case. */
4438 if (y >= dp->h)
4439 png_error(pp, "invalid y to progressive row callback");
4440
4441 row = store_image_row(dp->ps, pp, 0, y);
4442
4443#ifdef PNG_READ_INTERLACING_SUPPORTED
4444 /* Combine the new row into the old: */
4445 if (dp->do_interlace)
4446 {
4447 if (dp->interlace_type == PNG_INTERLACE_ADAM7)
4448 deinterlace_row(row, new_row, dp->pixel_size, dp->w, pass);
4449 else
4450 row_copy(row, new_row, dp->pixel_size * dp->w);
4451 }
4452 else
4453 png_progressive_combine_row(pp, row, new_row);
4454 } else if (dp->interlace_type == PNG_INTERLACE_ADAM7 &&
4455 PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
4456 PNG_PASS_COLS(dp->w, pass) > 0)
4457 png_error(pp, "missing row in progressive de-interlacing");
4458#endif /* PNG_READ_INTERLACING_SUPPORTED */
4459}
4460
4461static void
4462sequential_row(standard_display *dp, png_structp pp, png_infop pi,
4463 PNG_CONST int iImage, PNG_CONST int iDisplay)
4464{
4465 PNG_CONST int npasses = dp->npasses;
4466 PNG_CONST int do_interlace = dp->do_interlace &&
4467 dp->interlace_type == PNG_INTERLACE_ADAM7;
4468 PNG_CONST png_uint_32 height = standard_height(pp, dp->id);
4469 PNG_CONST png_uint_32 width = standard_width(pp, dp->id);
4470 PNG_CONST png_store* ps = dp->ps;
4471 int pass;
4472
4473 for (pass=0; pass<npasses; ++pass)
4474 {
4475 png_uint_32 y;
4476 png_uint_32 wPass = PNG_PASS_COLS(width, pass);
4477
4478 for (y=0; y<height; ++y)
4479 {
4480 if (do_interlace)
4481 {
4482 /* wPass may be zero or this row may not be in this pass.
4483 * png_read_row must not be called in either case.
4484 */
4485 if (wPass > 0 && PNG_ROW_IN_INTERLACE_PASS(y, pass))
4486 {
4487 /* Read the row into a pair of temporary buffers, then do the
4488 * merge here into the output rows.
4489 */
4490 png_byte row[STANDARD_ROWMAX], display[STANDARD_ROWMAX];
4491
4492 /* The following aids (to some extent) error detection - we can
4493 * see where png_read_row wrote. Use opposite values in row and
4494 * display to make this easier. Don't use 0xff (which is used in
4495 * the image write code to fill unused bits) or 0 (which is a
4496 * likely value to overwrite unused bits with).
4497 */
4498 memset(row, 0xc5, sizeof row);
4499 memset(display, 0x5c, sizeof display);
4500
4501 png_read_row(pp, row, display);
4502
4503 if (iImage >= 0)
4504 deinterlace_row(store_image_row(ps, pp, iImage, y), row,
4505 dp->pixel_size, dp->w, pass);
4506
4507 if (iDisplay >= 0)
4508 deinterlace_row(store_image_row(ps, pp, iDisplay, y), display,
4509 dp->pixel_size, dp->w, pass);
4510 }
4511 }
4512 else
4513 png_read_row(pp,
4514 iImage >= 0 ? store_image_row(ps, pp, iImage, y) : NULL,
4515 iDisplay >= 0 ? store_image_row(ps, pp, iDisplay, y) : NULL);
4516 }
4517 }
4518
4519 /* And finish the read operation (only really necessary if the caller wants
4520 * to find additional data in png_info from chunks after the last IDAT.)
4521 */
4522 png_read_end(pp, pi);
4523}
4524
4525static void
4526standard_row_validate(standard_display *dp, png_structp pp,
4527 int iImage, int iDisplay, png_uint_32 y)
4528{
4529 int where;
4530 png_byte std[STANDARD_ROWMAX];
4531
4532 /* The row must be pre-initialized to the magic number here for the size
4533 * tests to pass:
4534 */
4535 memset(std, 178, sizeof std);
4536 standard_row(pp, std, dp->id, y);
4537
4538 /* At the end both the 'row' and 'display' arrays should end up identical.
4539 * In earlier passes 'row' will be partially filled in, with only the pixels
4540 * that have been read so far, but 'display' will have those pixels
4541 * replicated to fill the unread pixels while reading an interlaced image.
4542#if PNG_LIBPNG_VER < 10506
4543 * The side effect inside the libpng sequential reader is that the 'row'
4544 * array retains the correct values for unwritten pixels within the row
4545 * bytes, while the 'display' array gets bits off the end of the image (in
4546 * the last byte) trashed. Unfortunately in the progressive reader the
4547 * row bytes are always trashed, so we always do a pixel_cmp here even though
4548 * a memcmp of all cbRow bytes will succeed for the sequential reader.
4549#endif
4550 */
4551 if (iImage >= 0 &&
4552 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iImage, y),
4553 dp->bit_width)) != 0)
4554 {
4555 char msg[64];
4556 sprintf(msg, "PNG image row[%d][%d] changed from %.2x to %.2x", y,
4557 where-1, std[where-1],
4558 store_image_row(dp->ps, pp, iImage, y)[where-1]);
4559 png_error(pp, msg);
4560 }
4561
4562#if PNG_LIBPNG_VER < 10506
4563 /* In this case use pixel_cmp because we need to compare a partial
4564 * byte at the end of the row if the row is not an exact multiple
4565 * of 8 bits wide. (This is fixed in libpng-1.5.6 and pixel_cmp is
4566 * changed to match!)
4567 */
4568#endif
4569 if (iDisplay >= 0 &&
4570 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iDisplay, y),
4571 dp->bit_width)) != 0)
4572 {
4573 char msg[64];
4574 sprintf(msg, "display row[%d][%d] changed from %.2x to %.2x", y,
4575 where-1, std[where-1],
4576 store_image_row(dp->ps, pp, iDisplay, y)[where-1]);
4577 png_error(pp, msg);
4578 }
4579}
4580
4581static void
4582standard_image_validate(standard_display *dp, png_structp pp, int iImage,
4583 int iDisplay)
4584{
4585 png_uint_32 y;
4586
4587 if (iImage >= 0)
4588 store_image_check(dp->ps, pp, iImage);
4589
4590 if (iDisplay >= 0)
4591 store_image_check(dp->ps, pp, iDisplay);
4592
4593 for (y=0; y<dp->h; ++y)
4594 standard_row_validate(dp, pp, iImage, iDisplay, y);
4595
4596 /* This avoids false positives if the validation code is never called! */
4597 dp->ps->validated = 1;
4598}
4599
4600static void
4601standard_end(png_structp pp, png_infop pi)
4602{
4603 standard_display *dp = voidcast(standard_display*,
4604 png_get_progressive_ptr(pp));
4605
4606 UNUSED(pi)
4607
4608 /* Validate the image - progressive reading only produces one variant for
4609 * interlaced images.
4610 */
4611 standard_image_validate(dp, pp, 0, -1);
4612}
4613
4614/* A single test run checking the standard image to ensure it is not damaged. */
4615static void
4616standard_test(png_store* PNG_CONST psIn, png_uint_32 PNG_CONST id,
4617 int do_interlace, int use_update_info)
4618{
4619 standard_display d;
4620 context(psIn, fault);
4621
4622 /* Set up the display (stack frame) variables from the arguments to the
4623 * function and initialize the locals that are filled in later.
4624 */
4625 standard_display_init(&d, psIn, id, do_interlace, use_update_info);
4626
4627 /* Everything is protected by a Try/Catch. The functions called also
4628 * typically have local Try/Catch blocks.
4629 */
4630 Try
4631 {
4632 png_structp pp;
4633 png_infop pi;
4634
4635 /* Get a png_struct for reading the image. This will throw an error if it
4636 * fails, so we don't need to check the result.
4637 */
4638 pp = set_store_for_read(d.ps, &pi, d.id,
4639 d.do_interlace ? (d.ps->progressive ?
4640 "pngvalid progressive deinterlacer" :
4641 "pngvalid sequential deinterlacer") : (d.ps->progressive ?
4642 "progressive reader" : "sequential reader"));
4643
4644 /* Initialize the palette correctly from the png_store_file. */
4645 standard_palette_init(&d);
4646
4647 /* Introduce the correct read function. */
4648 if (d.ps->progressive)
4649 {
4650 png_set_progressive_read_fn(pp, &d, standard_info, progressive_row,
4651 standard_end);
4652
4653 /* Now feed data into the reader until we reach the end: */
4654 store_progressive_read(d.ps, pp, pi);
4655 }
4656 else
4657 {
4658 /* Note that this takes the store, not the display. */
4659 png_set_read_fn(pp, d.ps, store_read);
4660
4661 /* Check the header values: */
4662 png_read_info(pp, pi);
4663
4664 /* The code tests both versions of the images that the sequential
4665 * reader can produce.
4666 */
4667 standard_info_imp(&d, pp, pi, 2 /*images*/);
4668
4669 /* Need the total bytes in the image below; we can't get to this point
4670 * unless the PNG file values have been checked against the expected
4671 * values.
4672 */
4673 {
4674 sequential_row(&d, pp, pi, 0, 1);
4675
4676 /* After the last pass loop over the rows again to check that the
4677 * image is correct.
4678 */
4679 if (!d.speed)
4680 standard_image_validate(&d, pp, 0, 1);
4681 else
4682 d.ps->validated = 1;
4683 }
4684 }
4685
4686 /* Check for validation. */
4687 if (!d.ps->validated)
4688 png_error(pp, "image read failed silently");
4689
4690 /* Successful completion. */
4691 }
4692
4693 Catch(fault)
4694 d.ps = fault; /* make sure this hasn't been clobbered. */
4695
4696 /* In either case clean up the store. */
4697 store_read_reset(d.ps);
4698}
4699
4700static int
4701test_standard(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type,
4702 int bdlo, int PNG_CONST bdhi)
4703{
4704 for (; bdlo <= bdhi; ++bdlo)
4705 {
4706 int interlace_type;
4707
4708 for (interlace_type = PNG_INTERLACE_NONE;
4709 interlace_type < PNG_INTERLACE_LAST; ++interlace_type)
4710 {
4711 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4712 interlace_type, 0, 0, 0), 0/*do_interlace*/, pm->use_update_info);
4713
4714 if (fail(pm))
4715 return 0;
4716 }
4717 }
4718
4719 return 1; /* keep going */
4720}
4721
4722static void
4723perform_standard_test(png_modifier *pm)
4724{
4725 /* Test each colour type over the valid range of bit depths (expressed as
4726 * log2(bit_depth) in turn, stop as soon as any error is detected.
4727 */
4728 if (!test_standard(pm, 0, 0, READ_BDHI))
4729 return;
4730
4731 if (!test_standard(pm, 2, 3, READ_BDHI))
4732 return;
4733
4734 if (!test_standard(pm, 3, 0, 3))
4735 return;
4736
4737 if (!test_standard(pm, 4, 3, READ_BDHI))
4738 return;
4739
4740 if (!test_standard(pm, 6, 3, READ_BDHI))
4741 return;
4742}
4743
4744
4745/********************************** SIZE TESTS ********************************/
4746static int
4747test_size(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type,
4748 int bdlo, int PNG_CONST bdhi)
4749{
4750 /* Run the tests on each combination.
4751 *
4752 * NOTE: on my 32 bit x86 each of the following blocks takes
4753 * a total of 3.5 seconds if done across every combo of bit depth
4754 * width and height. This is a waste of time in practice, hence the
4755 * hinc and winc stuff:
4756 */
4757 static PNG_CONST png_byte hinc[] = {1, 3, 11, 1, 5};
4758 static PNG_CONST png_byte winc[] = {1, 9, 5, 7, 1};
4759 for (; bdlo <= bdhi; ++bdlo)
4760 {
4761 png_uint_32 h, w;
4762
4763 for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo])
4764 {
4765 /* First test all the 'size' images against the sequential
4766 * reader using libpng to deinterlace (where required.) This
4767 * validates the write side of libpng. There are four possibilities
4768 * to validate.
4769 */
4770 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4771 PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/,
4772 pm->use_update_info);
4773
4774 if (fail(pm))
4775 return 0;
4776
4777 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4778 PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/,
4779 pm->use_update_info);
4780
4781 if (fail(pm))
4782 return 0;
4783
4784 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4785 PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/,
4786 pm->use_update_info);
4787
4788 if (fail(pm))
4789 return 0;
4790
4791 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4792 PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/,
4793 pm->use_update_info);
4794
4795 if (fail(pm))
4796 return 0;
4797
4798 /* Now validate the interlaced read side - do_interlace true,
4799 * in the progressive case this does actually make a difference
4800 * to the code used in the non-interlaced case too.
4801 */
4802 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4803 PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/,
4804 pm->use_update_info);
4805
4806 if (fail(pm))
4807 return 0;
4808
4809 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4810 PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/,
4811 pm->use_update_info);
4812
4813 if (fail(pm))
4814 return 0;
4815 }
4816 }
4817
4818 return 1; /* keep going */
4819}
4820
4821static void
4822perform_size_test(png_modifier *pm)
4823{
4824 /* Test each colour type over the valid range of bit depths (expressed as
4825 * log2(bit_depth) in turn, stop as soon as any error is detected.
4826 */
4827 if (!test_size(pm, 0, 0, READ_BDHI))
4828 return;
4829
4830 if (!test_size(pm, 2, 3, READ_BDHI))
4831 return;
4832
4833 /* For the moment don't do the palette test - it's a waste of time when
4834 * compared to the grayscale test.
4835 */
4836#if 0
4837 if (!test_size(pm, 3, 0, 3))
4838 return;
4839#endif
4840
4841 if (!test_size(pm, 4, 3, READ_BDHI))
4842 return;
4843
4844 if (!test_size(pm, 6, 3, READ_BDHI))
4845 return;
4846}
4847
4848
4849/******************************* TRANSFORM TESTS ******************************/
4850#ifdef PNG_READ_TRANSFORMS_SUPPORTED
4851/* A set of tests to validate libpng image transforms. The possibilities here
4852 * are legion because the transforms can be combined in a combinatorial
4853 * fashion. To deal with this some measure of restraint is required, otherwise
4854 * the tests would take forever.
4855 */
4856typedef struct image_pixel
4857{
4858 /* A local (pngvalid) representation of a PNG pixel, in all its
4859 * various forms.
4860 */
4861 unsigned int red, green, blue, alpha; /* For non-palette images. */
4862 unsigned int palette_index; /* For a palette image. */
4863 png_byte colour_type; /* As in the spec. */
4864 png_byte bit_depth; /* Defines bit size in row */
4865 png_byte sample_depth; /* Scale of samples */
4866 int have_tRNS; /* tRNS chunk may need processing */
4867
4868 /* For checking the code calculates double precision floating point values
4869 * along with an error value, accumulated from the transforms. Because an
4870 * sBIT setting allows larger error bounds (indeed, by the spec, apparently
4871 * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each
4872 * channel is stored. This sBIT value is folded in to the stored error value
4873 * at the end of the application of the transforms to the pixel.
4874 */
4875 double redf, greenf, bluef, alphaf;
4876 double rede, greene, bluee, alphae;
4877 png_byte red_sBIT, green_sBIT, blue_sBIT, alpha_sBIT;
4878} image_pixel;
4879
4880/* Shared utility function, see below. */
4881static void
4882image_pixel_setf(image_pixel *this, unsigned int max)
4883{
4884 this->redf = this->red / (double)max;
4885 this->greenf = this->green / (double)max;
4886 this->bluef = this->blue / (double)max;
4887 this->alphaf = this->alpha / (double)max;
4888
4889 if (this->red < max)
4890 this->rede = this->redf * DBL_EPSILON;
4891 else
4892 this->rede = 0;
4893 if (this->green < max)
4894 this->greene = this->greenf * DBL_EPSILON;
4895 else
4896 this->greene = 0;
4897 if (this->blue < max)
4898 this->bluee = this->bluef * DBL_EPSILON;
4899 else
4900 this->bluee = 0;
4901 if (this->alpha < max)
4902 this->alphae = this->alphaf * DBL_EPSILON;
4903 else
4904 this->alphae = 0;
4905}
4906
4907/* Initialize the structure for the next pixel - call this before doing any
4908 * transforms and call it for each pixel since all the fields may need to be
4909 * reset.
4910 */
4911static void
4912image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type,
4913 png_byte bit_depth, png_uint_32 x, store_palette palette)
4914{
4915 PNG_CONST png_byte sample_depth = (png_byte)(colour_type ==
4916 PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth);
4917 PNG_CONST unsigned int max = (1U<<sample_depth)-1;
4918
4919 /* Initially just set everything to the same number and the alpha to opaque.
4920 * Note that this currently assumes a simple palette where entry x has colour
4921 * rgb(x,x,x)!
4922 */
4923 this->palette_index = this->red = this->green = this->blue =
4924 sample(row, colour_type, bit_depth, x, 0);
4925 this->alpha = max;
4926 this->red_sBIT = this->green_sBIT = this->blue_sBIT = this->alpha_sBIT =
4927 sample_depth;
4928
4929 /* Then override as appropriate: */
4930 if (colour_type == 3) /* palette */
4931 {
4932 /* This permits the caller to default to the sample value. */
4933 if (palette != 0)
4934 {
4935 PNG_CONST unsigned int i = this->palette_index;
4936
4937 this->red = palette[i].red;
4938 this->green = palette[i].green;
4939 this->blue = palette[i].blue;
4940 this->alpha = palette[i].alpha;
4941 }
4942 }
4943
4944 else /* not palette */
4945 {
4946 unsigned int i = 0;
4947
4948 if (colour_type & 2)
4949 {
4950 this->green = sample(row, colour_type, bit_depth, x, 1);
4951 this->blue = sample(row, colour_type, bit_depth, x, 2);
4952 i = 2;
4953 }
4954 if (colour_type & 4)
4955 this->alpha = sample(row, colour_type, bit_depth, x, ++i);
4956 }
4957
4958 /* Calculate the scaled values, these are simply the values divided by
4959 * 'max' and the error is initialized to the double precision epsilon value
4960 * from the header file.
4961 */
4962 image_pixel_setf(this, max);
4963
4964 /* Store the input information for use in the transforms - these will
4965 * modify the information.
4966 */
4967 this->colour_type = colour_type;
4968 this->bit_depth = bit_depth;
4969 this->sample_depth = sample_depth;
4970 this->have_tRNS = 0;
4971}
4972
4973/* Convert a palette image to an rgb image. This necessarily converts the tRNS
4974 * chunk at the same time, because the tRNS will be in palette form. The way
4975 * palette validation works means that the original palette is never updated,
4976 * instead the image_pixel value from the row contains the RGB of the
4977 * corresponding palette entry and *this* is updated. Consequently this routine
4978 * only needs to change the colour type information.
4979 */
4980static void
4981image_pixel_convert_PLTE(image_pixel *this)
4982{
4983 if (this->colour_type == PNG_COLOR_TYPE_PALETTE)
4984 {
4985 if (this->have_tRNS)
4986 {
4987 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
4988 this->have_tRNS = 0;
4989 }
4990 else
4991 this->colour_type = PNG_COLOR_TYPE_RGB;
4992
4993 /* The bit depth of the row changes at this point too (notice that this is
4994 * the row format, not the sample depth, which is separate.)
4995 */
4996 this->bit_depth = 8;
4997 }
4998}
4999
5000/* Add an alpha channel; this will import the tRNS information because tRNS is
5001 * not valid in an alpha image. The bit depth will invariably be set to at
5002 * least 8. Palette images will be converted to alpha (using the above API).
5003 */
5004static void
5005image_pixel_add_alpha(image_pixel *this, PNG_CONST standard_display *display)
5006{
5007 if (this->colour_type == PNG_COLOR_TYPE_PALETTE)
5008 image_pixel_convert_PLTE(this);
5009
5010 if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0)
5011 {
5012 if (this->colour_type == PNG_COLOR_TYPE_GRAY)
5013 {
5014 if (this->bit_depth < 8)
5015 this->bit_depth = 8;
5016
5017 if (this->have_tRNS)
5018 {
5019 this->have_tRNS = 0;
5020
5021 /* Check the input, original, channel value here against the
5022 * original tRNS gray chunk valie.
5023 */
5024 if (this->red == display->transparent.red)
5025 this->alphaf = 0;
5026 else
5027 this->alphaf = 1;
5028 }
5029 else
5030 this->alphaf = 1;
5031
5032 this->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA;
5033 }
5034
5035 else if (this->colour_type == PNG_COLOR_TYPE_RGB)
5036 {
5037 if (this->have_tRNS)
5038 {
5039 this->have_tRNS = 0;
5040
5041 /* Again, check the exact input values, not the current transformed
5042 * value!
5043 */
5044 if (this->red == display->transparent.red &&
5045 this->green == display->transparent.green &&
5046 this->blue == display->transparent.blue)
5047 this->alphaf = 0;
5048 else
5049 this->alphaf = 1;
5050
5051 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
5052 }
5053 }
5054
5055 /* The error in the alpha is zero and the sBIT value comes from the
5056 * original sBIT data (actually it will always be the original bit depth).
5057 */
5058 this->alphae = 0;
5059 this->alpha_sBIT = display->alpha_sBIT;
5060 }
5061}
5062
5063struct transform_display;
5064typedef struct image_transform
5065{
5066 /* The name of this transform: a string. */
5067 PNG_CONST char *name;
5068
5069 /* Each transform can be disabled from the command line: */
5070 int enable;
5071
5072 /* The global list of transforms; read only. */
5073 struct image_transform *PNG_CONST list;
5074
5075 /* The global count of the number of times this transform has been set on an
5076 * image.
5077 */
5078 unsigned int global_use;
5079
5080 /* The local count of the number of times this transform has been set. */
5081 unsigned int local_use;
5082
5083 /* The next transform in the list, each transform must call its own next
5084 * transform after it has processed the pixel successfully.
5085 */
5086 PNG_CONST struct image_transform *next;
5087
5088 /* A single transform for the image, expressed as a series of function
5089 * callbacks and some space for values.
5090 *
5091 * First a callback to add any required modifications to the png_modifier;
5092 * this gets called just before the modifier is set up for read.
5093 */
5094 void (*ini)(PNG_CONST struct image_transform *this,
5095 struct transform_display *that);
5096
5097 /* And a callback to set the transform on the current png_read_struct:
5098 */
5099 void (*set)(PNG_CONST struct image_transform *this,
5100 struct transform_display *that, png_structp pp, png_infop pi);
5101
5102 /* Then a transform that takes an input pixel in one PNG format or another
5103 * and modifies it by a pngvalid implementation of the transform (thus
5104 * duplicating the libpng intent without, we hope, duplicating the bugs
5105 * in the libpng implementation!) The png_structp is solely to allow error
5106 * reporting via png_error and png_warning.
5107 */
5108 void (*mod)(PNG_CONST struct image_transform *this, image_pixel *that,
5109 png_structp pp, PNG_CONST struct transform_display *display);
5110
5111 /* Add this transform to the list and return true if the transform is
5112 * meaningful for this colour type and bit depth - if false then the
5113 * transform should have no effect on the image so there's not a lot of
5114 * point running it.
5115 */
5116 int (*add)(struct image_transform *this,
5117 PNG_CONST struct image_transform **that, png_byte colour_type,
5118 png_byte bit_depth);
5119} image_transform;
5120
5121typedef struct transform_display
5122{
5123 standard_display this;
5124
5125 /* Parameters */
5126 png_modifier* pm;
5127 PNG_CONST image_transform* transform_list;
5128
5129 /* Local variables */
5130 png_byte output_colour_type;
5131 png_byte output_bit_depth;
5132
5133 /* Modifications (not necessarily used.) */
5134 gama_modification gama_mod;
5135 chrm_modification chrm_mod;
5136 srgb_modification srgb_mod;
5137} transform_display;
5138
5139/* Set sRGB, cHRM and gAMA transforms as required by the current encoding. */
5140static void
5141transform_set_encoding(transform_display *this)
5142{
5143 /* Set up the png_modifier '_current' fields then use these to determine how
5144 * to add appropriate chunks.
5145 */
5146 png_modifier *pm = this->pm;
5147
5148 modifier_set_encoding(pm);
5149
5150 if (modifier_color_encoding_is_set(pm))
5151 {
5152 if (modifier_color_encoding_is_sRGB(pm))
5153 srgb_modification_init(&this->srgb_mod, pm, PNG_sRGB_INTENT_ABSOLUTE);
5154
5155 else
5156 {
5157 /* Set gAMA and cHRM separately. */
5158 gama_modification_init(&this->gama_mod, pm, pm->current_gamma);
5159
5160 if (pm->current_encoding != 0)
5161 chrm_modification_init(&this->chrm_mod, pm, pm->current_encoding);
5162 }
5163 }
5164}
5165
5166/* Three functions to end the list: */
5167static void
5168image_transform_ini_end(PNG_CONST image_transform *this,
5169 transform_display *that)
5170{
5171 UNUSED(this)
5172 UNUSED(that)
5173}
5174
5175static void
5176image_transform_set_end(PNG_CONST image_transform *this,
5177 transform_display *that, png_structp pp, png_infop pi)
5178{
5179 UNUSED(this)
5180 UNUSED(that)
5181 UNUSED(pp)
5182 UNUSED(pi)
5183}
5184
5185/* At the end of the list recalculate the output image pixel value from the
5186 * double precision values set up by the preceding 'mod' calls:
5187 */
5188static unsigned int
5189sample_scale(double sample_value, unsigned int scale)
5190{
5191 sample_value = floor(sample_value * scale + .5);
5192
5193 /* Return NaN as 0: */
5194 if (!(sample_value > 0))
5195 sample_value = 0;
5196 else if (sample_value > scale)
5197 sample_value = scale;
5198
5199 return (unsigned int)sample_value;
5200}
5201
5202static void
5203image_transform_mod_end(PNG_CONST image_transform *this, image_pixel *that,
5204 png_structp pp, PNG_CONST transform_display *display)
5205{
5206 PNG_CONST unsigned int scale = (1U<<that->sample_depth)-1;
5207
5208 UNUSED(this)
5209 UNUSED(pp)
5210 UNUSED(display)
5211
5212 /* At the end recalculate the digitized red green and blue values according
5213 * to the current sample_depth of the pixel.
5214 *
5215 * The sample value is simply scaled to the maximum, checking for over
5216 * and underflow (which can both happen for some image transforms,
5217 * including simple size scaling, though libpng doesn't do that at present.
5218 */
5219 that->red = sample_scale(that->redf, scale);
5220
5221 /* The error value is increased, at the end, according to the lowest sBIT
5222 * value seen. Common sense tells us that the intermediate integer
5223 * representations are no more accurate than +/- 0.5 in the integral values,
5224 * the sBIT allows the implementation to be worse than this. In addition the
5225 * PNG specification actually permits any error within the range (-1..+1),
5226 * but that is ignored here. Instead the final digitized value is compared,
5227 * below to the digitized value of the error limits - this has the net effect
5228 * of allowing (almost) +/-1 in the output value. It's difficult to see how
5229 * any algorithm that digitizes intermediate results can be more accurate.
5230 */
5231 that->rede += 1./(2*((1U<<that->red_sBIT)-1));
5232
5233 if (that->colour_type & PNG_COLOR_MASK_COLOR)
5234 {
5235 that->green = sample_scale(that->greenf, scale);
5236 that->blue = sample_scale(that->bluef, scale);
5237 that->greene += 1./(2*((1U<<that->green_sBIT)-1));
5238 that->bluee += 1./(2*((1U<<that->blue_sBIT)-1));
5239 }
5240 else
5241 {
5242 that->blue = that->green = that->red;
5243 that->bluef = that->greenf = that->redf;
5244 that->bluee = that->greene = that->rede;
5245 }
5246
5247 if ((that->colour_type & PNG_COLOR_MASK_ALPHA) ||
5248 that->colour_type == PNG_COLOR_TYPE_PALETTE)
5249 {
5250 that->alpha = sample_scale(that->alphaf, scale);
5251 that->alphae += 1./(2*((1U<<that->alpha_sBIT)-1));
5252 }
5253 else
5254 {
5255 that->alpha = scale; /* opaque */
5256 that->alpha = 1; /* Override this. */
5257 that->alphae = 0; /* It's exact ;-) */
5258 }
5259}
5260
5261/* Static 'end' structure: */
5262static image_transform image_transform_end =
5263{
5264 "(end)", /* name */
5265 1, /* enable */
5266 0, /* list */
5267 0, /* global_use */
5268 0, /* local_use */
5269 0, /* next */
5270 image_transform_ini_end,
5271 image_transform_set_end,
5272 image_transform_mod_end,
5273 0 /* never called, I want it to crash if it is! */
5274};
5275
5276/* Reader callbacks and implementations, where they differ from the standard
5277 * ones.
5278 */
5279static void
5280transform_display_init(transform_display *dp, png_modifier *pm, png_uint_32 id,
5281 PNG_CONST image_transform *transform_list)
5282{
5283 memset(dp, 0, sizeof *dp);
5284
5285 /* Standard fields */
5286 standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/,
5287 pm->use_update_info);
5288
5289 /* Parameter fields */
5290 dp->pm = pm;
5291 dp->transform_list = transform_list;
5292
5293 /* Local variable fields */
5294 dp->output_colour_type = 255; /* invalid */
5295 dp->output_bit_depth = 255; /* invalid */
5296}
5297
5298static void
5299transform_info_imp(transform_display *dp, png_structp pp, png_infop pi)
5300{
5301 /* Reuse the standard stuff as appropriate. */
5302 standard_info_part1(&dp->this, pp, pi);
5303
5304 /* Now set the list of transforms. */
5305 dp->transform_list->set(dp->transform_list, dp, pp, pi);
5306
5307 /* Update the info structure for these transforms: */
5308 {
5309 int i = dp->this.use_update_info;
5310 /* Always do one call, even if use_update_info is 0. */
5311 do
5312 png_read_update_info(pp, pi);
5313 while (--i > 0);
5314 }
5315
5316 /* And get the output information into the standard_display */
5317 standard_info_part2(&dp->this, pp, pi, 1/*images*/);
5318
5319 /* Plus the extra stuff we need for the transform tests: */
5320 dp->output_colour_type = png_get_color_type(pp, pi);
5321 dp->output_bit_depth = png_get_bit_depth(pp, pi);
5322
5323 /* Validate the combination of colour type and bit depth that we are getting
5324 * out of libpng; the semantics of something not in the PNG spec are, at
5325 * best, unclear.
5326 */
5327 switch (dp->output_colour_type)
5328 {
5329 case PNG_COLOR_TYPE_PALETTE:
5330 if (dp->output_bit_depth > 8) goto error;
5331 /*FALL THROUGH*/
5332 case PNG_COLOR_TYPE_GRAY:
5333 if (dp->output_bit_depth == 1 || dp->output_bit_depth == 2 ||
5334 dp->output_bit_depth == 4)
5335 break;
5336 /*FALL THROUGH*/
5337 default:
5338 if (dp->output_bit_depth == 8 || dp->output_bit_depth == 16)
5339 break;
5340 /*FALL THROUGH*/
5341 error:
5342 {
5343 char message[128];
5344 size_t pos;
5345
5346 pos = safecat(message, sizeof message, 0,
5347 "invalid final bit depth: colour type(");
5348 pos = safecatn(message, sizeof message, pos, dp->output_colour_type);
5349 pos = safecat(message, sizeof message, pos, ") with bit depth: ");
5350 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
5351
5352 png_error(pp, message);
5353 }
5354 }
5355
5356 /* Use a test pixel to check that the output agrees with what we expect -
5357 * this avoids running the whole test if the output is unexpected.
5358 */
5359 {
5360 image_pixel test_pixel;
5361
5362 memset(&test_pixel, 0, sizeof test_pixel);
5363 test_pixel.colour_type = dp->this.colour_type; /* input */
5364 test_pixel.bit_depth = dp->this.bit_depth;
5365 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE)
5366 test_pixel.sample_depth = 8;
5367 else
5368 test_pixel.sample_depth = test_pixel.bit_depth;
5369 /* Don't need sBIT here, but it must be set to non-zero to avoid
5370 * arithmetic overflows.
5371 */
5372 test_pixel.have_tRNS = dp->this.is_transparent;
5373 test_pixel.red_sBIT = test_pixel.green_sBIT = test_pixel.blue_sBIT =
5374 test_pixel.alpha_sBIT = test_pixel.sample_depth;
5375
5376 dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp);
5377
5378 if (test_pixel.colour_type != dp->output_colour_type)
5379 {
5380 char message[128];
5381 size_t pos = safecat(message, sizeof message, 0, "colour type ");
5382
5383 pos = safecatn(message, sizeof message, pos, dp->output_colour_type);
5384 pos = safecat(message, sizeof message, pos, " expected ");
5385 pos = safecatn(message, sizeof message, pos, test_pixel.colour_type);
5386
5387 png_error(pp, message);
5388 }
5389
5390 if (test_pixel.bit_depth != dp->output_bit_depth)
5391 {
5392 char message[128];
5393 size_t pos = safecat(message, sizeof message, 0, "bit depth ");
5394
5395 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
5396 pos = safecat(message, sizeof message, pos, " expected ");
5397 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth);
5398
5399 png_error(pp, message);
5400 }
5401
5402 /* If both bit depth and colour type are correct check the sample depth.
5403 * I believe these are both internal errors.
5404 */
5405 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE)
5406 {
5407 if (test_pixel.sample_depth != 8) /* oops - internal error! */
5408 png_error(pp, "pngvalid: internal: palette sample depth not 8");
5409 }
5410 else if (test_pixel.sample_depth != dp->output_bit_depth)
5411 {
5412 char message[128];
5413 size_t pos = safecat(message, sizeof message, 0,
5414 "internal: sample depth ");
5415
5416 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
5417 pos = safecat(message, sizeof message, pos, " expected ");
5418 pos = safecatn(message, sizeof message, pos, test_pixel.sample_depth);
5419
5420 png_error(pp, message);
5421 }
5422 }
5423}
5424
5425static void
5426transform_info(png_structp pp, png_infop pi)
5427{
5428 transform_info_imp(voidcast(transform_display*, png_get_progressive_ptr(pp)),
5429 pp, pi);
5430}
5431
5432static void
5433transform_range_check(png_structp pp, unsigned int r, unsigned int g,
5434 unsigned int b, unsigned int a, unsigned int in_digitized, double in,
5435 unsigned int out, png_byte sample_depth, double err, double limit,
5436 PNG_CONST char *name, double digitization_error)
5437{
5438 /* Compare the scaled, digitzed, values of our local calculation (in+-err)
5439 * with the digitized values libpng produced; 'sample_depth' is the actual
5440 * digitization depth of the libpng output colors (the bit depth except for
5441 * palette images where it is always 8.) The check on 'err' is to detect
5442 * internal errors in pngvalid itself.
5443 */
5444 unsigned int max = (1U<<sample_depth)-1;
5445 double in_min = ceil((in-err)*max - digitization_error);
5446 double in_max = floor((in+err)*max + digitization_error);
5447 if (err > limit || !(out >= in_min && out <= in_max))
5448 {
5449 char message[256];
5450 size_t pos;
5451
5452 pos = safecat(message, sizeof message, 0, name);
5453 pos = safecat(message, sizeof message, pos, " output value error: rgba(");
5454 pos = safecatn(message, sizeof message, pos, r);
5455 pos = safecat(message, sizeof message, pos, ",");
5456 pos = safecatn(message, sizeof message, pos, g);
5457 pos = safecat(message, sizeof message, pos, ",");
5458 pos = safecatn(message, sizeof message, pos, b);
5459 pos = safecat(message, sizeof message, pos, ",");
5460 pos = safecatn(message, sizeof message, pos, a);
5461 pos = safecat(message, sizeof message, pos, "): ");
5462 pos = safecatn(message, sizeof message, pos, out);
5463 pos = safecat(message, sizeof message, pos, " expected: ");
5464 pos = safecatn(message, sizeof message, pos, in_digitized);
5465 pos = safecat(message, sizeof message, pos, " (");
5466 pos = safecatd(message, sizeof message, pos, (in-err)*max, 3);
5467 pos = safecat(message, sizeof message, pos, "..");
5468 pos = safecatd(message, sizeof message, pos, (in+err)*max, 3);
5469 pos = safecat(message, sizeof message, pos, ")");
5470
5471 png_error(pp, message);
5472 }
5473}
5474
5475static void
5476transform_image_validate(transform_display *dp, png_structp pp, png_infop pi)
5477{
5478 /* Constants for the loop below: */
5479 PNG_CONST png_store* PNG_CONST ps = dp->this.ps;
5480 PNG_CONST png_byte in_ct = dp->this.colour_type;
5481 PNG_CONST png_byte in_bd = dp->this.bit_depth;
5482 PNG_CONST png_uint_32 w = dp->this.w;
5483 PNG_CONST png_uint_32 h = dp->this.h;
5484 PNG_CONST png_byte out_ct = dp->output_colour_type;
5485 PNG_CONST png_byte out_bd = dp->output_bit_depth;
5486 PNG_CONST png_byte sample_depth = (png_byte)(out_ct ==
5487 PNG_COLOR_TYPE_PALETTE ? 8 : out_bd);
5488 PNG_CONST png_byte red_sBIT = dp->this.red_sBIT;
5489 PNG_CONST png_byte green_sBIT = dp->this.green_sBIT;
5490 PNG_CONST png_byte blue_sBIT = dp->this.blue_sBIT;
5491 PNG_CONST png_byte alpha_sBIT = dp->this.alpha_sBIT;
5492 PNG_CONST int have_tRNS = dp->this.is_transparent;
5493 double digitization_error;
5494
5495 store_palette out_palette;
5496 png_uint_32 y;
5497
5498 UNUSED(pi)
5499
5500 /* Check for row overwrite errors */
5501 store_image_check(dp->this.ps, pp, 0);
5502
5503 /* Read the palette corresponding to the output if the output colour type
5504 * indicates a palette, othewise set out_palette to garbage.
5505 */
5506 if (out_ct == PNG_COLOR_TYPE_PALETTE)
5507 {
5508 /* Validate that the palette count itself has not changed - this is not
5509 * expected.
5510 */
5511 int npalette = (-1);
5512
5513 (void)read_palette(out_palette, &npalette, pp, pi);
5514 if (npalette != dp->this.npalette)
5515 png_error(pp, "unexpected change in palette size");
5516
5517 digitization_error = .5;
5518 }
5519 else
5520 {
5521 png_byte in_sample_depth;
5522
5523 memset(out_palette, 0x5e, sizeof out_palette);
5524
5525 /* assume-8-bit-calculations means assume that if the input has 8 bit
5526 * (or less) samples and the output has 16 bit samples the calculations
5527 * will be done with 8 bit precision, not 16.
5528 *
5529 * TODO: fix this in libpng; png_set_expand_16 should cause 16 bit
5530 * calculations to be used throughout.
5531 */
5532 if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16)
5533 in_sample_depth = 8;
5534 else
5535 in_sample_depth = in_bd;
5536
5537 if (sample_depth != 16 || in_sample_depth > 8 ||
5538 !dp->pm->calculations_use_input_precision)
5539 digitization_error = .5;
5540
5541 /* Else errors are at 8 bit precision, scale .5 in 8 bits to the 16 bits:
5542 */
5543 else
5544 digitization_error = .5 * 257;
5545 }
5546
5547 for (y=0; y<h; ++y)
5548 {
5549 png_const_bytep PNG_CONST pRow = store_image_row(ps, pp, 0, y);
5550 png_uint_32 x;
5551
5552 /* The original, standard, row pre-transforms. */
5553 png_byte std[STANDARD_ROWMAX];
5554
5555 transform_row(pp, std, in_ct, in_bd, y);
5556
5557 /* Go through each original pixel transforming it and comparing with what
5558 * libpng did to the same pixel.
5559 */
5560 for (x=0; x<w; ++x)
5561 {
5562 image_pixel in_pixel, out_pixel;
5563 unsigned int r, g, b, a;
5564
5565 /* Find out what we think the pixel should be: */
5566 image_pixel_init(&in_pixel, std, in_ct, in_bd, x, dp->this.palette);
5567
5568 in_pixel.red_sBIT = red_sBIT;
5569 in_pixel.green_sBIT = green_sBIT;
5570 in_pixel.blue_sBIT = blue_sBIT;
5571 in_pixel.alpha_sBIT = alpha_sBIT;
5572 in_pixel.have_tRNS = have_tRNS;
5573
5574 /* For error detection, below. */
5575 r = in_pixel.red;
5576 g = in_pixel.green;
5577 b = in_pixel.blue;
5578 a = in_pixel.alpha;
5579
5580 dp->transform_list->mod(dp->transform_list, &in_pixel, pp, dp);
5581
5582 /* Read the output pixel and compare it to what we got, we don't
5583 * use the error field here, so no need to update sBIT.
5584 */
5585 image_pixel_init(&out_pixel, pRow, out_ct, out_bd, x, out_palette);
5586
5587 /* We don't expect changes to the index here even if the bit depth is
5588 * changed.
5589 */
5590 if (in_ct == PNG_COLOR_TYPE_PALETTE &&
5591 out_ct == PNG_COLOR_TYPE_PALETTE)
5592 {
5593 if (in_pixel.palette_index != out_pixel.palette_index)
5594 png_error(pp, "unexpected transformed palette index");
5595 }
5596
5597 /* Check the colours for palette images too - in fact the palette could
5598 * be separately verified itself in most cases.
5599 */
5600 if (in_pixel.red != out_pixel.red)
5601 transform_range_check(pp, r, g, b, a, in_pixel.red, in_pixel.redf,
5602 out_pixel.red, sample_depth, in_pixel.rede,
5603 dp->pm->limit + 1./(2*((1U<<in_pixel.red_sBIT)-1)), "red/gray",
5604 digitization_error);
5605
5606 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 &&
5607 in_pixel.green != out_pixel.green)
5608 transform_range_check(pp, r, g, b, a, in_pixel.green,
5609 in_pixel.greenf, out_pixel.green, sample_depth, in_pixel.greene,
5610 dp->pm->limit + 1./(2*((1U<<in_pixel.green_sBIT)-1)), "green",
5611 digitization_error);
5612
5613 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 &&
5614 in_pixel.blue != out_pixel.blue)
5615 transform_range_check(pp, r, g, b, a, in_pixel.blue, in_pixel.bluef,
5616 out_pixel.blue, sample_depth, in_pixel.bluee,
5617 dp->pm->limit + 1./(2*((1U<<in_pixel.blue_sBIT)-1)), "blue",
5618 digitization_error);
5619
5620 if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0 &&
5621 in_pixel.alpha != out_pixel.alpha)
5622 transform_range_check(pp, r, g, b, a, in_pixel.alpha,
5623 in_pixel.alphaf, out_pixel.alpha, sample_depth, in_pixel.alphae,
5624 dp->pm->limit + 1./(2*((1U<<in_pixel.alpha_sBIT)-1)), "alpha",
5625 digitization_error);
5626 } /* pixel (x) loop */
5627 } /* row (y) loop */
5628
5629 /* Record that something was actually checked to avoid a false positive. */
5630 dp->this.ps->validated = 1;
5631}
5632
5633static void
5634transform_end(png_structp pp, png_infop pi)
5635{
5636 transform_display *dp = voidcast(transform_display*,
5637 png_get_progressive_ptr(pp));
5638
5639 if (!dp->this.speed)
5640 transform_image_validate(dp, pp, pi);
5641 else
5642 dp->this.ps->validated = 1;
5643}
5644
5645/* A single test run. */
5646static void
5647transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn,
5648 PNG_CONST image_transform* transform_listIn, PNG_CONST char * volatile name)
5649{
5650 transform_display d;
5651 context(&pmIn->this, fault);
5652
5653 transform_display_init(&d, pmIn, idIn, transform_listIn);
5654
5655 Try
5656 {
5657 size_t pos = 0;
5658 png_structp pp;
5659 png_infop pi;
5660 char full_name[256];
5661
5662 /* Make sure the encoding fields are correct and enter the required
5663 * modifications.
5664 */
5665 transform_set_encoding(&d);
5666
5667 /* Add any modifications required by the transform list. */
5668 d.transform_list->ini(d.transform_list, &d);
5669
5670 /* Add the color space information, if any, to the name. */
5671 pos = safecat(full_name, sizeof full_name, pos, name);
5672 pos = safecat_current_encoding(full_name, sizeof full_name, pos, d.pm);
5673
5674 /* Get a png_struct for reading the image. */
5675 pp = set_modifier_for_read(d.pm, &pi, d.this.id, full_name);
5676 standard_palette_init(&d.this);
5677
5678# if 0
5679 /* Logging (debugging only) */
5680 {
5681 char buffer[256];
5682
5683 (void)store_message(&d.pm->this, pp, buffer, sizeof buffer, 0,
5684 "running test");
5685
5686 fprintf(stderr, "%s\n", buffer);
5687 }
5688# endif
5689
5690 /* Introduce the correct read function. */
5691 if (d.pm->this.progressive)
5692 {
5693 /* Share the row function with the standard implementation. */
5694 png_set_progressive_read_fn(pp, &d, transform_info, progressive_row,
5695 transform_end);
5696
5697 /* Now feed data into the reader until we reach the end: */
5698 modifier_progressive_read(d.pm, pp, pi);
5699 }
5700 else
5701 {
5702 /* modifier_read expects a png_modifier* */
5703 png_set_read_fn(pp, d.pm, modifier_read);
5704
5705 /* Check the header values: */
5706 png_read_info(pp, pi);
5707
5708 /* Process the 'info' requirements. Only one image is generated */
5709 transform_info_imp(&d, pp, pi);
5710
5711 sequential_row(&d.this, pp, pi, -1, 0);
5712
5713 if (!d.this.speed)
5714 transform_image_validate(&d, pp, pi);
5715 else
5716 d.this.ps->validated = 1;
5717 }
5718
5719 modifier_reset(d.pm);
5720 }
5721
5722 Catch(fault)
5723 {
5724 modifier_reset((png_modifier*)fault);
5725 }
5726}
5727
5728/* The transforms: */
5729#define ITSTRUCT(name) image_transform_##name
5730#define ITDATA(name) image_transform_data_##name
5731#define image_transform_ini image_transform_default_ini
5732#define IT(name)\
5733static image_transform ITSTRUCT(name) =\
5734{\
5735 #name,\
5736 1, /*enable*/\
5737 &PT, /*list*/\
5738 0, /*global_use*/\
5739 0, /*local_use*/\
5740 0, /*next*/\
5741 image_transform_ini,\
5742 image_transform_png_set_##name##_set,\
5743 image_transform_png_set_##name##_mod,\
5744 image_transform_png_set_##name##_add\
5745}
5746#define PT ITSTRUCT(end) /* stores the previous transform */
5747
5748/* To save code: */
5749static void
5750image_transform_default_ini(PNG_CONST image_transform *this,
5751 transform_display *that)
5752{
5753 this->next->ini(this->next, that);
5754}
5755
5756static int
5757image_transform_default_add(image_transform *this,
5758 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5759{
5760 UNUSED(colour_type)
5761 UNUSED(bit_depth)
5762
5763 this->next = *that;
5764 *that = this;
5765
5766 return 1;
5767}
5768
5769#ifdef PNG_READ_EXPAND_SUPPORTED
5770/* png_set_palette_to_rgb */
5771static void
5772image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform *this,
5773 transform_display *that, png_structp pp, png_infop pi)
5774{
5775 png_set_palette_to_rgb(pp);
5776 this->next->set(this->next, that, pp, pi);
5777}
5778
5779static void
5780image_transform_png_set_palette_to_rgb_mod(PNG_CONST image_transform *this,
5781 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
5782{
5783 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
5784 image_pixel_convert_PLTE(that);
5785
5786 this->next->mod(this->next, that, pp, display);
5787}
5788
5789static int
5790image_transform_png_set_palette_to_rgb_add(image_transform *this,
5791 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5792{
5793 UNUSED(bit_depth)
5794
5795 this->next = *that;
5796 *that = this;
5797
5798 return colour_type == PNG_COLOR_TYPE_PALETTE;
5799}
5800
5801IT(palette_to_rgb);
5802#undef PT
5803#define PT ITSTRUCT(palette_to_rgb)
5804#endif /* PNG_READ_EXPAND_SUPPORTED */
5805
5806#ifdef PNG_READ_EXPAND_SUPPORTED
5807/* png_set_tRNS_to_alpha */
5808static void
5809image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this,
5810 transform_display *that, png_structp pp, png_infop pi)
5811{
5812 png_set_tRNS_to_alpha(pp);
5813 this->next->set(this->next, that, pp, pi);
5814}
5815
5816static void
5817image_transform_png_set_tRNS_to_alpha_mod(PNG_CONST image_transform *this,
5818 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
5819{
5820 /* LIBPNG BUG: this always forces palette images to RGB. */
5821 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
5822 image_pixel_convert_PLTE(that);
5823
5824 /* This effectively does an 'expand' only if there is some transparency to
5825 * convert to an alpha channel.
5826 */
5827 if (that->have_tRNS)
5828 image_pixel_add_alpha(that, &display->this);
5829
5830 /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */
5831 else
5832 {
5833 if (that->bit_depth < 8)
5834 that->bit_depth =8;
5835 if (that->sample_depth < 8)
5836 that->sample_depth = 8;
5837 }
5838
5839 this->next->mod(this->next, that, pp, display);
5840}
5841
5842static int
5843image_transform_png_set_tRNS_to_alpha_add(image_transform *this,
5844 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5845{
5846 UNUSED(bit_depth)
5847
5848 this->next = *that;
5849 *that = this;
5850
5851 /* We don't know yet whether there will be a tRNS chunk, but we know that
5852 * this transformation should do nothing if there already is an alpha
5853 * channel.
5854 */
5855 return (colour_type & PNG_COLOR_MASK_ALPHA) == 0;
5856}
5857
5858IT(tRNS_to_alpha);
5859#undef PT
5860#define PT ITSTRUCT(tRNS_to_alpha)
5861#endif /* PNG_READ_EXPAND_SUPPORTED */
5862
5863#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
5864/* png_set_gray_to_rgb */
5865static void
5866image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this,
5867 transform_display *that, png_structp pp, png_infop pi)
5868{
5869 png_set_gray_to_rgb(pp);
5870 this->next->set(this->next, that, pp, pi);
5871}
5872
5873static void
5874image_transform_png_set_gray_to_rgb_mod(PNG_CONST image_transform *this,
5875 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
5876{
5877 /* NOTE: we can actually pend the tRNS processing at this point because we
5878 * can correctly recognize the original pixel value even though we have
5879 * mapped the one gray channel to the three RGB ones, but in fact libpng
5880 * doesn't do this, so we don't either.
5881 */
5882 if ((that->colour_type & PNG_COLOR_MASK_COLOR) == 0 && that->have_tRNS)
5883 image_pixel_add_alpha(that, &display->this);
5884
5885 /* Simply expand the bit depth and alter the colour type as required. */
5886 if (that->colour_type == PNG_COLOR_TYPE_GRAY)
5887 {
5888 /* RGB images have a bit depth at least equal to '8' */
5889 if (that->bit_depth < 8)
5890 that->sample_depth = that->bit_depth = 8;
5891
5892 /* And just changing the colour type works here because the green and blue
5893 * channels are being maintained in lock-step with the red/gray:
5894 */
5895 that->colour_type = PNG_COLOR_TYPE_RGB;
5896 }
5897
5898 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
5899 that->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
5900
5901 this->next->mod(this->next, that, pp, display);
5902}
5903
5904static int
5905image_transform_png_set_gray_to_rgb_add(image_transform *this,
5906 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5907{
5908 UNUSED(bit_depth)
5909
5910 this->next = *that;
5911 *that = this;
5912
5913 return (colour_type & PNG_COLOR_MASK_COLOR) == 0;
5914}
5915
5916IT(gray_to_rgb);
5917#undef PT
5918#define PT ITSTRUCT(gray_to_rgb)
5919#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
5920
5921#ifdef PNG_READ_EXPAND_SUPPORTED
5922/* png_set_expand */
5923static void
5924image_transform_png_set_expand_set(PNG_CONST image_transform *this,
5925 transform_display *that, png_structp pp, png_infop pi)
5926{
5927 png_set_expand(pp);
5928 this->next->set(this->next, that, pp, pi);
5929}
5930
5931static void
5932image_transform_png_set_expand_mod(PNG_CONST image_transform *this,
5933 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
5934{
5935 /* The general expand case depends on what the colour type is: */
5936 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
5937 image_pixel_convert_PLTE(that);
5938 else if (that->bit_depth < 8) /* grayscale */
5939 that->sample_depth = that->bit_depth = 8;
5940
5941 if (that->have_tRNS)
5942 image_pixel_add_alpha(that, &display->this);
5943
5944 this->next->mod(this->next, that, pp, display);
5945}
5946
5947static int
5948image_transform_png_set_expand_add(image_transform *this,
5949 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5950{
5951 UNUSED(bit_depth)
5952
5953 this->next = *that;
5954 *that = this;
5955
5956 /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit
5957 * depth is at least 8 already.
5958 */
5959 return (colour_type & PNG_COLOR_MASK_ALPHA) == 0;
5960}
5961
5962IT(expand);
5963#undef PT
5964#define PT ITSTRUCT(expand)
5965#endif /* PNG_READ_EXPAND_SUPPORTED */
5966
5967#ifdef PNG_READ_EXPAND_SUPPORTED
5968/* png_set_expand_gray_1_2_4_to_8
5969 * LIBPNG BUG: this just does an 'expand'
5970 */
5971static void
5972image_transform_png_set_expand_gray_1_2_4_to_8_set(
5973 PNG_CONST image_transform *this, transform_display *that, png_structp pp,
5974 png_infop pi)
5975{
5976 png_set_expand_gray_1_2_4_to_8(pp);
5977 this->next->set(this->next, that, pp, pi);
5978}
5979
5980static void
5981image_transform_png_set_expand_gray_1_2_4_to_8_mod(
5982 PNG_CONST image_transform *this, image_pixel *that, png_structp pp,
5983 PNG_CONST transform_display *display)
5984{
5985 image_transform_png_set_expand_mod(this, that, pp, display);
5986}
5987
5988static int
5989image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this,
5990 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5991{
5992 return image_transform_png_set_expand_add(this, that, colour_type,
5993 bit_depth);
5994}
5995
5996IT(expand_gray_1_2_4_to_8);
5997#undef PT
5998#define PT ITSTRUCT(expand_gray_1_2_4_to_8)
5999#endif /* PNG_READ_EXPAND_SUPPORTED */
6000
6001#ifdef PNG_READ_EXPAND_16_SUPPORTED
6002/* png_set_expand_16 */
6003static void
6004image_transform_png_set_expand_16_set(PNG_CONST image_transform *this,
6005 transform_display *that, png_structp pp, png_infop pi)
6006{
6007 png_set_expand_16(pp);
6008 this->next->set(this->next, that, pp, pi);
6009}
6010
6011static void
6012image_transform_png_set_expand_16_mod(PNG_CONST image_transform *this,
6013 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6014{
6015 /* Expect expand_16 to expand everything to 16 bits as a result of also
6016 * causing 'expand' to happen.
6017 */
6018 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
6019 image_pixel_convert_PLTE(that);
6020
6021 if (that->have_tRNS)
6022 image_pixel_add_alpha(that, &display->this);
6023
6024 if (that->bit_depth < 16)
6025 that->sample_depth = that->bit_depth = 16;
6026
6027 this->next->mod(this->next, that, pp, display);
6028}
6029
6030static int
6031image_transform_png_set_expand_16_add(image_transform *this,
6032 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6033{
6034 UNUSED(colour_type)
6035
6036 this->next = *that;
6037 *that = this;
6038
6039 /* expand_16 does something unless the bit depth is already 16. */
6040 return bit_depth < 16;
6041}
6042
6043IT(expand_16);
6044#undef PT
6045#define PT ITSTRUCT(expand_16)
6046#endif /* PNG_READ_EXPAND_16_SUPPORTED */
6047
6048#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* API added in 1.5.4 */
6049/* png_set_scale_16 */
6050static void
6051image_transform_png_set_scale_16_set(PNG_CONST image_transform *this,
6052 transform_display *that, png_structp pp, png_infop pi)
6053{
6054 png_set_scale_16(pp);
6055 this->next->set(this->next, that, pp, pi);
6056}
6057
6058static void
6059image_transform_png_set_scale_16_mod(PNG_CONST image_transform *this,
6060 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6061{
6062 if (that->bit_depth == 16)
6063 {
6064 that->sample_depth = that->bit_depth = 8;
6065 if (that->red_sBIT > 8) that->red_sBIT = 8;
6066 if (that->green_sBIT > 8) that->green_sBIT = 8;
6067 if (that->blue_sBIT > 8) that->blue_sBIT = 8;
6068 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8;
6069 }
6070
6071 this->next->mod(this->next, that, pp, display);
6072}
6073
6074static int
6075image_transform_png_set_scale_16_add(image_transform *this,
6076 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6077{
6078 UNUSED(colour_type)
6079
6080 this->next = *that;
6081 *that = this;
6082
6083 return bit_depth > 8;
6084}
6085
6086IT(scale_16);
6087#undef PT
6088#define PT ITSTRUCT(scale_16)
6089#endif /* PNG_READ_SCALE_16_TO_8_SUPPORTED (1.5.4 on) */
6090
6091#ifdef PNG_READ_16_TO_8_SUPPORTED /* the default before 1.5.4 */
6092/* png_set_strip_16 */
6093static void
6094image_transform_png_set_strip_16_set(PNG_CONST image_transform *this,
6095 transform_display *that, png_structp pp, png_infop pi)
6096{
6097 png_set_strip_16(pp);
6098 this->next->set(this->next, that, pp, pi);
6099}
6100
6101static void
6102image_transform_png_set_strip_16_mod(PNG_CONST image_transform *this,
6103 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6104{
6105 if (that->bit_depth == 16)
6106 {
6107 that->sample_depth = that->bit_depth = 8;
6108 if (that->red_sBIT > 8) that->red_sBIT = 8;
6109 if (that->green_sBIT > 8) that->green_sBIT = 8;
6110 if (that->blue_sBIT > 8) that->blue_sBIT = 8;
6111 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8;
6112
6113 /* Prior to 1.5.4 png_set_strip_16 would use an 'accurate' method if this
6114 * configuration option is set. From 1.5.4 the flag is never set and the
6115 * 'scale' API (above) must be used.
6116 */
6117# ifdef PNG_READ_ACCURATE_SCALE_SUPPORTED
6118# if PNG_LIBPNG_VER >= 10504
6119# error PNG_READ_ACCURATE_SCALE should not be set
6120# endif
6121
6122 /* The strip 16 algorithm drops the low 8 bits rather than calculating
6123 * 1/257, so we need to adjust the permitted errors appropriately:
6124 * Notice that this is only relevant prior to the addition of the
6125 * png_set_scale_16 API in 1.5.4 (but 1.5.4+ always defines the above!)
6126 */
6127 {
6128 PNG_CONST double d = (255-128.5)/65535;
6129 that->rede += d;
6130 that->greene += d;
6131 that->bluee += d;
6132 that->alphae += d;
6133 }
6134# endif
6135 }
6136
6137 this->next->mod(this->next, that, pp, display);
6138}
6139
6140static int
6141image_transform_png_set_strip_16_add(image_transform *this,
6142 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6143{
6144 UNUSED(colour_type)
6145
6146 this->next = *that;
6147 *that = this;
6148
6149 return bit_depth > 8;
6150}
6151
6152IT(strip_16);
6153#undef PT
6154#define PT ITSTRUCT(strip_16)
6155#endif /* PNG_READ_16_TO_8_SUPPORTED */
6156
6157#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
6158/* png_set_strip_alpha */
6159static void
6160image_transform_png_set_strip_alpha_set(PNG_CONST image_transform *this,
6161 transform_display *that, png_structp pp, png_infop pi)
6162{
6163 png_set_strip_alpha(pp);
6164 this->next->set(this->next, that, pp, pi);
6165}
6166
6167static void
6168image_transform_png_set_strip_alpha_mod(PNG_CONST image_transform *this,
6169 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6170{
6171 if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6172 that->colour_type = PNG_COLOR_TYPE_GRAY;
6173 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
6174 that->colour_type = PNG_COLOR_TYPE_RGB;
6175
6176 that->have_tRNS = 0;
6177 that->alphaf = 1;
6178
6179 this->next->mod(this->next, that, pp, display);
6180}
6181
6182static int
6183image_transform_png_set_strip_alpha_add(image_transform *this,
6184 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6185{
6186 UNUSED(bit_depth)
6187
6188 this->next = *that;
6189 *that = this;
6190
6191 return (colour_type & PNG_COLOR_MASK_ALPHA) != 0;
6192}
6193
6194IT(strip_alpha);
6195#undef PT
6196#define PT ITSTRUCT(strip_alpha)
6197#endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */
6198
6199#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
6200/* png_set_rgb_to_gray(png_structp, int err_action, double red, double green)
6201 * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red,
6202 * png_fixed_point green)
6203 * png_get_rgb_to_gray_status
6204 *
6205 * The 'default' test here uses values known to be used inside libpng:
6206 *
6207 * red: 6968
6208 * green: 23434
6209 * blue: 2366
6210 *
6211 * These values are being retained for compatibility, along with the somewhat
6212 * broken truncation calculation in the fast-and-inaccurate code path. Older
6213 * versions of libpng will fail the accuracy tests below because they use the
6214 * truncation algorithm everywhere.
6215 */
6216#define data ITDATA(rgb_to_gray)
6217static struct
6218{
6219 double gamma; /* File gamma to use in processing */
6220
6221 /* The following are the parameters for png_set_rgb_to_gray: */
6222# ifdef PNG_FLOATING_POINT_SUPPORTED
6223 double red_to_set;
6224 double green_to_set;
6225# else
6226 png_fixed_point red_to_set;
6227 png_fixed_point green_to_set;
6228# endif
6229
6230 /* The actual coefficients: */
6231 double red_coefficient;
6232 double green_coefficient;
6233 double blue_coefficient;
6234
6235 /* Set if the coeefficients have been overridden. */
6236 int coefficients_overridden;
6237} data;
6238
6239#undef image_transform_ini
6240#define image_transform_ini image_transform_png_set_rgb_to_gray_ini
6241static void
6242image_transform_png_set_rgb_to_gray_ini(PNG_CONST image_transform *this,
6243 transform_display *that)
6244{
6245 png_modifier *pm = that->pm;
6246 PNG_CONST color_encoding *e = pm->current_encoding;
6247
6248 UNUSED(this)
6249
6250 /* Since we check the encoding this flag must be set: */
6251 pm->test_uses_encoding = 1;
6252
6253 /* If 'e' is not NULL chromaticity information is present and either a cHRM
6254 * or an sRGB chunk will be inserted.
6255 */
6256 if (e != 0)
6257 {
6258 /* Coefficients come from the encoding, but may need to be normalized to a
6259 * white point Y of 1.0
6260 */
6261 PNG_CONST double whiteY = e->red.Y + e->green.Y + e->blue.Y;
6262
6263 data.red_coefficient = e->red.Y;
6264 data.green_coefficient = e->green.Y;
6265 data.blue_coefficient = e->blue.Y;
6266
6267 if (whiteY != 1)
6268 {
6269 data.red_coefficient /= whiteY;
6270 data.green_coefficient /= whiteY;
6271 data.blue_coefficient /= whiteY;
6272 }
6273 }
6274
6275 else
6276 {
6277 /* The default (built in) coeffcients, as above: */
6278 data.red_coefficient = 6968 / 32768.;
6279 data.green_coefficient = 23434 / 32768.;
6280 data.blue_coefficient = 2366 / 32768.;
6281 }
6282
6283 data.gamma = pm->current_gamma;
6284
6285 /* If not set then the calculations assume linear encoding (implicitly): */
6286 if (data.gamma == 0)
6287 data.gamma = 1;
6288
6289 /* The arguments to png_set_rgb_to_gray can override the coefficients implied
6290 * by the color space encoding. If doing exhaustive checks do the override
6291 * in each case, otherwise do it randomly.
6292 */
6293 if (pm->test_exhaustive)
6294 {
6295 /* First time in coefficients_overridden is 0, the following sets it to 1,
6296 * so repeat if it is set. If a test fails this may mean we subsequently
6297 * skip a non-override test, ignore that.
6298 */
6299 data.coefficients_overridden = !data.coefficients_overridden;
6300 pm->repeat = data.coefficients_overridden != 0;
6301 }
6302
6303 else
6304 data.coefficients_overridden = random_choice();
6305
6306 if (data.coefficients_overridden)
6307 {
6308 /* These values override the color encoding defaults, simply use random
6309 * numbers.
6310 */
6311 png_uint_32 ru;
6312 double total;
6313
6314 RANDOMIZE(ru);
6315 data.green_coefficient = total = (ru & 0xffff) / 65535.;
6316 ru >>= 16;
6317 data.red_coefficient = (1 - total) * (ru & 0xffff) / 65535.;
6318 total += data.red_coefficient;
6319 data.blue_coefficient = 1 - total;
6320
6321# ifdef PNG_FLOATING_POINT_SUPPORTED
6322 data.red_to_set = data.red_coefficient;
6323 data.green_to_set = data.green_coefficient;
6324# else
6325 data.red_to_set = fix(data.red_coefficient);
6326 data.green_to_set = fix(data.green_coefficient);
6327# endif
6328
6329 /* The following just changes the error messages: */
6330 pm->encoding_ignored = 1;
6331 }
6332
6333 else
6334 {
6335 data.red_to_set = -1;
6336 data.green_to_set = -1;
6337 }
6338
6339 /* Adjust the error limit in the png_modifier because of the larger errors
6340 * produced in the digitization during the gamma handling.
6341 */
6342 if (data.gamma != 1) /* Use gamma tables */
6343 {
6344 if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations)
6345 {
6346 /* The 16 bit case ends up producing a maximum error of about
6347 * +/-5 in 65535, allow for +/-8 with the given gamma.
6348 */
6349 that->pm->limit += pow(8./65535, data.gamma);
6350 }
6351
6352 else
6353 {
6354 /* Rounding to 8 bits in the linear space causes massive errors which
6355 * will trigger the error check in transform_range_check. Fix that
6356 * here by taking the gamma encoding into account.
6357 */
6358 that->pm->limit += pow(1./255, data.gamma);
6359 }
6360 }
6361
6362 else
6363 {
6364 /* With no gamma correction a large error comes from the truncation of the
6365 * calculation in the 8 bit case, allow for that here.
6366 */
6367 if (that->this.bit_depth != 16)
6368 that->pm->limit += 4E-3;
6369 }
6370}
6371
6372static void
6373image_transform_png_set_rgb_to_gray_set(PNG_CONST image_transform *this,
6374 transform_display *that, png_structp pp, png_infop pi)
6375{
6376 PNG_CONST int error_action = 1; /* no error, no defines in png.h */
6377
6378# ifdef PNG_FLOATING_POINT_SUPPORTED
6379 png_set_rgb_to_gray(pp, error_action, data.red_to_set, data.green_to_set);
6380# else
6381 png_set_rgb_to_gray_fixed(pp, error_action, data.red_to_set,
6382 data.green_to_set);
6383# endif
6384
6385# ifdef PNG_READ_cHRM_SUPPORTED
6386 if (that->pm->current_encoding != 0)
6387 {
6388 /* We have an encoding so a cHRM chunk may have been set; if so then
6389 * check that the libpng APIs give the correct (X,Y,Z) values within
6390 * some margin of error for the round trip through the chromaticity
6391 * form.
6392 */
6393# ifdef PNG_FLOATING_POINT_SUPPORTED
6394# define API_function png_get_cHRM_XYZ
6395# define API_form "FP"
6396# define API_type double
6397# define API_cvt(x) (x)
6398# else
6399# define API_function png_get_cHRM_XYZ_fixed
6400# define API_form "fixed"
6401# define API_type png_fixed_point
6402# define API_cvt(x) ((double)(x)/PNG_FP_1)
6403# endif
6404
6405 API_type rX, gX, bX;
6406 API_type rY, gY, bY;
6407 API_type rZ, gZ, bZ;
6408
6409 if ((API_function(pp, pi, &rX, &rY, &rZ, &gX, &gY, &gZ, &bX, &bY, &bZ)
6410 & PNG_INFO_cHRM) != 0)
6411 {
6412 double maxe;
6413 PNG_CONST char *el;
6414 color_encoding e, o;
6415
6416 /* Expect libpng to return a normalized result, but the original
6417 * color space encoding may not be normalized.
6418 */
6419 modifier_current_encoding(that->pm, &o);
6420 normalize_color_encoding(&o);
6421
6422 /* Sanity check the pngvalid code - the coefficients should match
6423 * the normalized Y values of the encoding unless they were
6424 * overridden.
6425 */
6426 if (data.red_to_set == -1 && data.green_to_set == -1 &&
6427 (fabs(o.red.Y - data.red_coefficient) > DBL_EPSILON ||
6428 fabs(o.green.Y - data.green_coefficient) > DBL_EPSILON ||
6429 fabs(o.blue.Y - data.blue_coefficient) > DBL_EPSILON))
6430 png_error(pp, "internal pngvalid cHRM coefficient error");
6431
6432 /* Generate a colour space encoding. */
6433 e.gamma = o.gamma; /* not used */
6434 e.red.X = API_cvt(rX);
6435 e.red.Y = API_cvt(rY);
6436 e.red.Z = API_cvt(rZ);
6437 e.green.X = API_cvt(gX);
6438 e.green.Y = API_cvt(gY);
6439 e.green.Z = API_cvt(gZ);
6440 e.blue.X = API_cvt(bX);
6441 e.blue.Y = API_cvt(bY);
6442 e.blue.Z = API_cvt(bZ);
6443
6444 /* This should match the original one from the png_modifier, within
6445 * the range permitted by the libpng fixed point representation.
6446 */
6447 maxe = 0;
6448 el = "-"; /* Set to element name with error */
6449
6450# define CHECK(col,x)\
6451 {\
6452 double err = fabs(o.col.x - e.col.x);\
6453 if (err > maxe)\
6454 {\
6455 maxe = err;\
6456 el = #col "(" #x ")";\
6457 }\
6458 }
6459
6460 CHECK(red,X)
6461 CHECK(red,Y)
6462 CHECK(red,Z)
6463 CHECK(green,X)
6464 CHECK(green,Y)
6465 CHECK(green,Z)
6466 CHECK(blue,X)
6467 CHECK(blue,Y)
6468 CHECK(blue,Z)
6469
6470 /* Here in both fixed and floating cases to check the values read
6471 * from the cHRm chunk. PNG uses fixed point in the cHRM chunk, so
6472 * we can't expect better than +/-.5E-5 on the result, allow 1E-5.
6473 */
6474 if (maxe >= 1E-5)
6475 {
6476 size_t pos = 0;
6477 char buffer[256];
6478
6479 pos = safecat(buffer, sizeof buffer, pos, API_form);
6480 pos = safecat(buffer, sizeof buffer, pos, " cHRM ");
6481 pos = safecat(buffer, sizeof buffer, pos, el);
6482 pos = safecat(buffer, sizeof buffer, pos, " error: ");
6483 pos = safecatd(buffer, sizeof buffer, pos, maxe, 7);
6484 pos = safecat(buffer, sizeof buffer, pos, " ");
6485 /* Print the color space without the gamma value: */
6486 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &o, 0);
6487 pos = safecat(buffer, sizeof buffer, pos, " -> ");
6488 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &e, 0);
6489
6490 png_error(pp, buffer);
6491 }
6492 }
6493 }
6494# endif /* READ_cHRM */
6495
6496 this->next->set(this->next, that, pp, pi);
6497}
6498
6499static void
6500image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
6501 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6502{
6503 if ((that->colour_type & PNG_COLOR_MASK_COLOR) != 0)
6504 {
6505 double gray, err;
6506
6507 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
6508 image_pixel_convert_PLTE(that);
6509
6510 /* Image now has RGB channels... */
6511 {
6512 PNG_CONST png_modifier *pm = display->pm;
6513 PNG_CONST unsigned int sample_depth = that->sample_depth;
6514 int isgray;
6515 double r, g, b;
6516 double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi;
6517
6518 /* Do this using interval arithmetic, otherwise it is too difficult to
6519 * handle the errors correctly.
6520 *
6521 * To handle the gamma correction work out the upper and lower bounds
6522 * of the digitized value. Assume rounding here - normally the values
6523 * will be identical after this operation if there is only one
6524 * transform, feel free to delete the png_error checks on this below in
6525 * the future (this is just me trying to ensure it works!)
6526 */
6527 r = rlo = rhi = that->redf;
6528 rlo -= that->rede;
6529 rlo = digitize(pm, rlo, sample_depth, 1/*round*/);
6530 rhi += that->rede;
6531 rhi = digitize(pm, rhi, sample_depth, 1/*round*/);
6532
6533 g = glo = ghi = that->greenf;
6534 glo -= that->greene;
6535 glo = digitize(pm, glo, sample_depth, 1/*round*/);
6536 ghi += that->greene;
6537 ghi = digitize(pm, ghi, sample_depth, 1/*round*/);
6538
6539 b = blo = bhi = that->bluef;
6540 blo -= that->bluee;
6541 blo = digitize(pm, blo, sample_depth, 1/*round*/);
6542 bhi += that->greene;
6543 bhi = digitize(pm, bhi, sample_depth, 1/*round*/);
6544
6545 isgray = r==g && g==b;
6546
6547 if (data.gamma != 1)
6548 {
6549 PNG_CONST double power = 1/data.gamma;
6550 PNG_CONST double abse = abserr(pm, sample_depth, sample_depth);
6551
6552 /* 'abse' is the absolute error permitted in linear calculations. It
6553 * is used here to capture the error permitted in the handling
6554 * (undoing) of the gamma encoding. Once again digitization occurs
6555 * to handle the upper and lower bounds of the values. This is
6556 * where the real errors are introduced.
6557 */
6558 r = pow(r, power);
6559 rlo = digitize(pm, pow(rlo, power)-abse, sample_depth, 1);
6560 rhi = digitize(pm, pow(rhi, power)+abse, sample_depth, 1);
6561
6562 g = pow(g, power);
6563 glo = digitize(pm, pow(glo, power)-abse, sample_depth, 1);
6564 ghi = digitize(pm, pow(ghi, power)+abse, sample_depth, 1);
6565
6566 b = pow(b, power);
6567 blo = digitize(pm, pow(blo, power)-abse, sample_depth, 1);
6568 bhi = digitize(pm, pow(bhi, power)+abse, sample_depth, 1);
6569 }
6570
6571 /* Now calculate the actual gray values. Although the error in the
6572 * coefficients depends on whether they were specified on the command
6573 * line (in which case truncation to 15 bits happened) or not (rounding
6574 * was used) the maxium error in an individual coefficient is always
6575 * 1/32768, because even in the rounding case the requirement that
6576 * coefficients add up to 32768 can cause a larger rounding error.
6577 *
6578 * The only time when rounding doesn't occur in 1.5.5 and later is when
6579 * the non-gamma code path is used for less than 16 bit data.
6580 */
6581 gray = r * data.red_coefficient + g * data.green_coefficient +
6582 b * data.blue_coefficient;
6583
6584 {
6585 PNG_CONST int do_round = data.gamma != 1 || sample_depth == 16;
6586 PNG_CONST double ce = 1. / 32768;
6587
6588 graylo = digitize(pm, rlo * (data.red_coefficient-ce) +
6589 glo * (data.green_coefficient-ce) +
6590 blo * (data.blue_coefficient-ce), sample_depth, do_round);
6591 if (graylo <= 0)
6592 graylo = 0;
6593
6594 grayhi = digitize(pm, rhi * (data.red_coefficient+ce) +
6595 ghi * (data.green_coefficient+ce) +
6596 bhi * (data.blue_coefficient+ce), sample_depth, do_round);
6597 if (grayhi >= 1)
6598 grayhi = 1;
6599 }
6600
6601 /* And invert the gamma. */
6602 if (data.gamma != 1)
6603 {
6604 PNG_CONST double power = data.gamma;
6605
6606 gray = pow(gray, power);
6607 graylo = digitize(pm, pow(graylo, power), sample_depth, 1);
6608 grayhi = digitize(pm, pow(grayhi, power), sample_depth, 1);
6609 }
6610
6611 /* Now the error can be calculated.
6612 *
6613 * If r==g==b because there is no overall gamma correction libpng
6614 * currently preserves the original value.
6615 */
6616 if (isgray)
6617 err = (that->rede + that->greene + that->bluee)/3;
6618
6619 else
6620 {
6621 err = fabs(grayhi-gray);
6622 if (fabs(gray - graylo) > err)
6623 err = fabs(graylo-gray);
6624
6625 /* Check that this worked: */
6626 if (err > display->pm->limit)
6627 {
6628 size_t pos = 0;
6629 char buffer[128];
6630
6631 pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error ");
6632 pos = safecatd(buffer, sizeof buffer, pos, err, 6);
6633 pos = safecat(buffer, sizeof buffer, pos, " exceeds limit ");
6634 pos = safecatd(buffer, sizeof buffer, pos,
6635 display->pm->limit, 6);
6636 png_error(pp, buffer);
6637 }
6638 }
6639 }
6640
6641 that->bluef = that->greenf = that->redf = gray;
6642 that->bluee = that->greene = that->rede = err;
6643
6644 /* The sBIT is the minium of the three colour channel sBITs. */
6645 if (that->red_sBIT > that->green_sBIT)
6646 that->red_sBIT = that->green_sBIT;
6647 if (that->red_sBIT > that->blue_sBIT)
6648 that->red_sBIT = that->blue_sBIT;
6649 that->blue_sBIT = that->green_sBIT = that->red_sBIT;
6650
6651 /* And remove the colour bit in the type: */
6652 if (that->colour_type == PNG_COLOR_TYPE_RGB)
6653 that->colour_type = PNG_COLOR_TYPE_GRAY;
6654 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
6655 that->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA;
6656 }
6657
6658 this->next->mod(this->next, that, pp, display);
6659}
6660
6661static int
6662image_transform_png_set_rgb_to_gray_add(image_transform *this,
6663 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6664{
6665 UNUSED(bit_depth)
6666
6667 this->next = *that;
6668 *that = this;
6669
6670 return (colour_type & PNG_COLOR_MASK_COLOR) != 0;
6671}
6672
6673#undef data
6674IT(rgb_to_gray);
6675#undef PT
6676#define PT ITSTRUCT(rgb_to_gray)
6677#undef image_transform_ini
6678#define image_transform_ini image_transform_default_ini
6679#endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */
6680
6681#ifdef PNG_READ_BACKGROUND_SUPPORTED
6682/* png_set_background(png_structp, png_const_color_16p background_color,
6683 * int background_gamma_code, int need_expand, double background_gamma)
6684 * png_set_background_fixed(png_structp, png_const_color_16p background_color,
6685 * int background_gamma_code, int need_expand,
6686 * png_fixed_point background_gamma)
6687 *
6688 * As with rgb_to_gray this ignores the gamma (at present.)
6689*/
6690#define data ITDATA(background)
6691static image_pixel data;
6692
6693static void
6694image_transform_png_set_background_set(PNG_CONST image_transform *this,
6695 transform_display *that, png_structp pp, png_infop pi)
6696{
6697 png_byte colour_type, bit_depth;
6698 png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */
6699 png_color_16 back;
6700
6701 /* We need a background colour, because we don't know exactly what transforms
6702 * have been set we have to supply the colour in the original file format and
6703 * so we need to know what that is! The background colour is stored in the
6704 * transform_display.
6705 */
6706 RANDOMIZE(random_bytes);
6707
6708 /* Read the random value, for colour type 3 the background colour is actually
6709 * expressed as a 24bit rgb, not an index.
6710 */
6711 colour_type = that->this.colour_type;
6712 if (colour_type == 3)
6713 {
6714 colour_type = PNG_COLOR_TYPE_RGB;
6715 bit_depth = 8;
6716 }
6717
6718 else
6719 bit_depth = that->this.bit_depth;
6720
6721 image_pixel_init(&data, random_bytes, colour_type,
6722 bit_depth, 0/*x*/, 0/*unused: palette*/);
6723
6724 /* Extract the background colour from this image_pixel, but make sure the
6725 * unused fields of 'back' are garbage.
6726 */
6727 RANDOMIZE(back);
6728
6729 if (colour_type & PNG_COLOR_MASK_COLOR)
6730 {
6731 back.red = (png_uint_16)data.red;
6732 back.green = (png_uint_16)data.green;
6733 back.blue = (png_uint_16)data.blue;
6734 }
6735
6736 else
6737 back.gray = (png_uint_16)data.red;
6738
6739# ifdef PNG_FLOATING_POINT_SUPPORTED
6740 png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1/*need expand*/,
6741 0);
6742# else
6743 png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE,
6744 1/*need expand*/, 0);
6745# endif
6746
6747 this->next->set(this->next, that, pp, pi);
6748}
6749
6750static void
6751image_transform_png_set_background_mod(PNG_CONST image_transform *this,
6752 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6753{
6754 /* Check for tRNS first: */
6755 if (that->have_tRNS && that->colour_type != PNG_COLOR_TYPE_PALETTE)
6756 image_pixel_add_alpha(that, &display->this);
6757
6758 /* This is only necessary if the alpha value is less than 1. */
6759 if (that->alphaf < 1)
6760 {
6761 /* Now we do the background calculation without any gamma correction. */
6762 if (that->alphaf <= 0)
6763 {
6764 that->redf = data.redf;
6765 that->greenf = data.greenf;
6766 that->bluef = data.bluef;
6767
6768 that->rede = data.rede;
6769 that->greene = data.greene;
6770 that->bluee = data.bluee;
6771
6772 that->red_sBIT= data.red_sBIT;
6773 that->green_sBIT= data.green_sBIT;
6774 that->blue_sBIT= data.blue_sBIT;
6775 }
6776
6777 else /* 0 < alpha < 1 */
6778 {
6779 double alf = 1 - that->alphaf;
6780
6781 that->redf = that->redf * that->alphaf + data.redf * alf;
6782 that->rede = that->rede * that->alphaf + data.rede * alf +
6783 DBL_EPSILON;
6784 that->greenf = that->greenf * that->alphaf + data.greenf * alf;
6785 that->greene = that->greene * that->alphaf + data.greene * alf +
6786 DBL_EPSILON;
6787 that->bluef = that->bluef * that->alphaf + data.bluef * alf;
6788 that->bluee = that->bluee * that->alphaf + data.bluee * alf +
6789 DBL_EPSILON;
6790 }
6791
6792 /* Remove the alpha type and set the alpha (not in that order.) */
6793 that->alphaf = 1;
6794 that->alphae = 0;
6795
6796 if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
6797 that->colour_type = PNG_COLOR_TYPE_RGB;
6798 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6799 that->colour_type = PNG_COLOR_TYPE_GRAY;
6800 /* PNG_COLOR_TYPE_PALETTE is not changed */
6801 }
6802
6803 this->next->mod(this->next, that, pp, display);
6804}
6805
6806#define image_transform_png_set_background_add image_transform_default_add
6807
6808#undef data
6809IT(background);
6810#undef PT
6811#define PT ITSTRUCT(background)
6812#endif /* PNG_READ_BACKGROUND_SUPPORTED */
6813
6814/* This may just be 'end' if all the transforms are disabled! */
6815static image_transform *PNG_CONST image_transform_first = &PT;
6816
6817static void
6818transform_enable(PNG_CONST char *name)
6819{
6820 /* Everything starts out enabled, so if we see an 'enable' disabled
6821 * everything else the first time round.
6822 */
6823 static int all_disabled = 0;
6824 int found_it = 0;
6825 image_transform *list = image_transform_first;
6826
6827 while (list != &image_transform_end)
6828 {
6829 if (strcmp(list->name, name) == 0)
6830 {
6831 list->enable = 1;
6832 found_it = 1;
6833 }
6834 else if (!all_disabled)
6835 list->enable = 0;
6836
6837 list = list->list;
6838 }
6839
6840 all_disabled = 1;
6841
6842 if (!found_it)
6843 {
6844 fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n",
6845 name);
6846 exit(1);
6847 }
6848}
6849
6850static void
6851transform_disable(PNG_CONST char *name)
6852{
6853 image_transform *list = image_transform_first;
6854
6855 while (list != &image_transform_end)
6856 {
6857 if (strcmp(list->name, name) == 0)
6858 {
6859 list->enable = 0;
6860 return;
6861 }
6862
6863 list = list->list;
6864 }
6865
6866 fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n",
6867 name);
6868 exit(1);
6869}
6870
6871static void
6872image_transform_reset_count(void)
6873{
6874 image_transform *next = image_transform_first;
6875 int count = 0;
6876
6877 while (next != &image_transform_end)
6878 {
6879 next->local_use = 0;
6880 next->next = 0;
6881 next = next->list;
6882 ++count;
6883 }
6884
6885 /* This can only happen if we every have more than 32 transforms (excluding
6886 * the end) in the list.
6887 */
6888 if (count > 32) abort();
6889}
6890
6891static int
6892image_transform_test_counter(png_uint_32 counter, unsigned int max)
6893{
6894 /* Test the list to see if there is any point contining, given a current
6895 * counter and a 'max' value.
6896 */
6897 image_transform *next = image_transform_first;
6898
6899 while (next != &image_transform_end)
6900 {
6901 /* For max 0 or 1 continue until the counter overflows: */
6902 counter >>= 1;
6903
6904 /* Continue if any entry hasn't reacked the max. */
6905 if (max > 1 && next->local_use < max)
6906 return 1;
6907 next = next->list;
6908 }
6909
6910 return max <= 1 && counter == 0;
6911}
6912
6913static png_uint_32
6914image_transform_add(PNG_CONST image_transform **this, unsigned int max,
6915 png_uint_32 counter, char *name, size_t sizeof_name, size_t *pos,
6916 png_byte colour_type, png_byte bit_depth)
6917{
6918 for (;;) /* until we manage to add something */
6919 {
6920 png_uint_32 mask;
6921 image_transform *list;
6922
6923 /* Find the next counter value, if the counter is zero this is the start
6924 * of the list. This routine always returns the current counter (not the
6925 * next) so it returns 0 at the end and expects 0 at the beginning.
6926 */
6927 if (counter == 0) /* first time */
6928 {
6929 image_transform_reset_count();
6930 if (max <= 1)
6931 counter = 1;
6932 else
6933 counter = random_32();
6934 }
6935 else /* advance the counter */
6936 {
6937 switch (max)
6938 {
6939 case 0: ++counter; break;
6940 case 1: counter <<= 1; break;
6941 default: counter = random_32(); break;
6942 }
6943 }
6944
6945 /* Now add all these items, if possible */
6946 *this = &image_transform_end;
6947 list = image_transform_first;
6948 mask = 1;
6949
6950 /* Go through the whole list adding anything that the counter selects: */
6951 while (list != &image_transform_end)
6952 {
6953 if ((counter & mask) != 0 && list->enable &&
6954 (max == 0 || list->local_use < max))
6955 {
6956 /* Candidate to add: */
6957 if (list->add(list, this, colour_type, bit_depth) || max == 0)
6958 {
6959 /* Added, so add to the name too. */
6960 *pos = safecat(name, sizeof_name, *pos, " +");
6961 *pos = safecat(name, sizeof_name, *pos, list->name);
6962 }
6963
6964 else
6965 {
6966 /* Not useful and max>0, so remove it from *this: */
6967 *this = list->next;
6968 list->next = 0;
6969
6970 /* And, since we know it isn't useful, stop it being added again
6971 * in this run:
6972 */
6973 list->local_use = max;
6974 }
6975 }
6976
6977 mask <<= 1;
6978 list = list->list;
6979 }
6980
6981 /* Now if anything was added we have something to do. */
6982 if (*this != &image_transform_end)
6983 return counter;
6984
6985 /* Nothing added, but was there anything in there to add? */
6986 if (!image_transform_test_counter(counter, max))
6987 return 0;
6988 }
6989}
6990
6991#ifdef THIS_IS_THE_PROFORMA
6992static void
6993image_transform_png_set_@_set(PNG_CONST image_transform *this,
6994 transform_display *that, png_structp pp, png_infop pi)
6995{
6996 png_set_@(pp);
6997 this->next->set(this->next, that, pp, pi);
6998}
6999
7000static void
7001image_transform_png_set_@_mod(PNG_CONST image_transform *this,
7002 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
7003{
7004 this->next->mod(this->next, that, pp, display);
7005}
7006
7007static int
7008image_transform_png_set_@_add(image_transform *this,
7009 PNG_CONST image_transform **that, char *name, size_t sizeof_name,
7010 size_t *pos, png_byte colour_type, png_byte bit_depth)
7011{
7012 this->next = *that;
7013 *that = this;
7014
7015 *pos = safecat(name, sizeof_name, *pos, " +@");
7016
7017 return 1;
7018}
7019
7020IT(@);
7021#endif
7022
7023/* png_set_quantize(png_structp, png_colorp palette, int num_palette,
7024 * int maximum_colors, png_const_uint_16p histogram, int full_quantize)
7025 *
7026 * Very difficult to validate this!
7027 */
7028/*NOTE: TBD NYI */
7029
7030/* The data layout transforms are handled by swapping our own channel data,
7031 * necessarily these need to happen at the end of the transform list because the
7032 * semantic of the channels changes after these are executed. Some of these,
7033 * like set_shift and set_packing, can't be done at present because they change
7034 * the layout of the data at the sub-sample level so sample() won't get the
7035 * right answer.
7036 */
7037/* png_set_invert_alpha */
7038/*NOTE: TBD NYI */
7039
7040/* png_set_bgr */
7041/*NOTE: TBD NYI */
7042
7043/* png_set_swap_alpha */
7044/*NOTE: TBD NYI */
7045
7046/* png_set_swap */
7047/*NOTE: TBD NYI */
7048
7049/* png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); */
7050/*NOTE: TBD NYI */
7051
7052/* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */
7053/*NOTE: TBD NYI */
7054
7055/* png_set_packing */
7056/*NOTE: TBD NYI */
7057
7058/* png_set_packswap */
7059/*NOTE: TBD NYI */
7060
7061/* png_set_invert_mono */
7062/*NOTE: TBD NYI */
7063
7064/* png_set_shift(png_structp, png_const_color_8p true_bits) */
7065/*NOTE: TBD NYI */
7066
7067static void
7068perform_transform_test(png_modifier *pm)
7069{
7070 png_byte colour_type = 0;
7071 png_byte bit_depth = 0;
7072 int palette_number = 0;
7073
7074 while (next_format(&colour_type, &bit_depth, &palette_number))
7075 {
7076 png_uint_32 counter = 0;
7077 size_t base_pos;
7078 char name[64];
7079
7080 base_pos = safecat(name, sizeof name, 0, "transform:");
7081
7082 for (;;)
7083 {
7084 size_t pos = base_pos;
7085 PNG_CONST image_transform *list = 0;
7086
7087 /* 'max' is currently hardwired to '1'; this should be settable on the
7088 * command line.
7089 */
7090 counter = image_transform_add(&list, 1/*max*/, counter,
7091 name, sizeof name, &pos, colour_type, bit_depth);
7092
7093 if (counter == 0)
7094 break;
7095
7096 /* The command line can change this to checking interlaced images. */
7097 do
7098 {
7099 pm->repeat = 0;
7100 transform_test(pm, FILEID(colour_type, bit_depth, palette_number,
7101 pm->interlace_type, 0, 0, 0), list, name);
7102
7103 if (fail(pm))
7104 return;
7105 }
7106 while (pm->repeat);
7107 }
7108 }
7109}
7110#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
7111
7112/********************************* GAMMA TESTS ********************************/
7113#ifdef PNG_READ_GAMMA_SUPPORTED
7114/* Reader callbacks and implementations, where they differ from the standard
7115 * ones.
7116 */
7117typedef struct gamma_display
7118{
7119 standard_display this;
7120
7121 /* Parameters */
7122 png_modifier* pm;
7123 double file_gamma;
7124 double screen_gamma;
7125 double background_gamma;
7126 png_byte sbit;
7127 int threshold_test;
7128 int use_input_precision;
7129 int scale16;
7130 int expand16;
7131 int do_background;
7132 png_color_16 background_color;
7133
7134 /* Local variables */
7135 double maxerrout;
7136 double maxerrpc;
7137 double maxerrabs;
7138} gamma_display;
7139
7140#define ALPHA_MODE_OFFSET 4
7141
7142static void
7143gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id,
7144 double file_gamma, double screen_gamma, png_byte sbit, int threshold_test,
7145 int use_input_precision, int scale16, int expand16,
7146 int do_background, PNG_CONST png_color_16 *pointer_to_the_background_color,
7147 double background_gamma)
7148{
7149 /* Standard fields */
7150 standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/,
7151 pm->use_update_info);
7152
7153 /* Parameter fields */
7154 dp->pm = pm;
7155 dp->file_gamma = file_gamma;
7156 dp->screen_gamma = screen_gamma;
7157 dp->background_gamma = background_gamma;
7158 dp->sbit = sbit;
7159 dp->threshold_test = threshold_test;
7160 dp->use_input_precision = use_input_precision;
7161 dp->scale16 = scale16;
7162 dp->expand16 = expand16;
7163 dp->do_background = do_background;
7164 if (do_background && pointer_to_the_background_color != 0)
7165 dp->background_color = *pointer_to_the_background_color;
7166 else
7167 memset(&dp->background_color, 0, sizeof dp->background_color);
7168
7169 /* Local variable fields */
7170 dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0;
7171}
7172
7173static void
7174gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi)
7175{
7176 /* Reuse the standard stuff as appropriate. */
7177 standard_info_part1(&dp->this, pp, pi);
7178
7179 /* If requested strip 16 to 8 bits - this is handled automagically below
7180 * because the output bit depth is read from the library. Note that there
7181 * are interactions with sBIT but, internally, libpng makes sbit at most
7182 * PNG_MAX_GAMMA_8 when doing the following.
7183 */
7184 if (dp->scale16)
7185# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
7186 png_set_scale_16(pp);
7187# else
7188 /* The following works both in 1.5.4 and earlier versions: */
7189# ifdef PNG_READ_16_TO_8_SUPPORTED
7190 png_set_strip_16(pp);
7191# else
7192 png_error(pp, "scale16 (16 to 8 bit conversion) not supported");
7193# endif
7194# endif
7195
7196 if (dp->expand16)
7197# ifdef PNG_READ_EXPAND_16_SUPPORTED
7198 png_set_expand_16(pp);
7199# else
7200 png_error(pp, "expand16 (8 to 16 bit conversion) not supported");
7201# endif
7202
7203 if (dp->do_background >= ALPHA_MODE_OFFSET)
7204 {
7205# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7206 {
7207 /* This tests the alpha mode handling, if supported. */
7208 int mode = dp->do_background - ALPHA_MODE_OFFSET;
7209
7210 /* The gamma value is the output gamma, and is in the standard,
7211 * non-inverted, represenation. It provides a default for the PNG file
7212 * gamma, but since the file has a gAMA chunk this does not matter.
7213 */
7214 PNG_CONST double sg = dp->screen_gamma;
7215# ifndef PNG_FLOATING_POINT_SUPPORTED
7216 PNG_CONST png_fixed_point g = fix(sg);
7217# endif
7218
7219# ifdef PNG_FLOATING_POINT_SUPPORTED
7220 png_set_alpha_mode(pp, mode, sg);
7221# else
7222 png_set_alpha_mode_fixed(pp, mode, g);
7223# endif
7224
7225 /* However, for the standard Porter-Duff algorithm the output defaults
7226 * to be linear, so if the test requires non-linear output it must be
7227 * corrected here.
7228 */
7229 if (mode == PNG_ALPHA_STANDARD && sg != 1)
7230 {
7231# ifdef PNG_FLOATING_POINT_SUPPORTED
7232 png_set_gamma(pp, sg, dp->file_gamma);
7233# else
7234 png_fixed_point f = fix(dp->file_gamma);
7235 png_set_gamma_fixed(pp, g, f);
7236# endif
7237 }
7238 }
7239# else
7240 png_error(pp, "alpha mode handling not supported");
7241# endif
7242 }
7243
7244 else
7245 {
7246 /* Set up gamma processing. */
7247# ifdef PNG_FLOATING_POINT_SUPPORTED
7248 png_set_gamma(pp, dp->screen_gamma, dp->file_gamma);
7249# else
7250 {
7251 png_fixed_point s = fix(dp->screen_gamma);
7252 png_fixed_point f = fix(dp->file_gamma);
7253 png_set_gamma_fixed(pp, s, f);
7254 }
7255# endif
7256
7257 if (dp->do_background)
7258 {
7259# ifdef PNG_READ_BACKGROUND_SUPPORTED
7260 /* NOTE: this assumes the caller provided the correct background gamma!
7261 */
7262 PNG_CONST double bg = dp->background_gamma;
7263# ifndef PNG_FLOATING_POINT_SUPPORTED
7264 PNG_CONST png_fixed_point g = fix(bg);
7265# endif
7266
7267# ifdef PNG_FLOATING_POINT_SUPPORTED
7268 png_set_background(pp, &dp->background_color, dp->do_background,
7269 0/*need_expand*/, bg);
7270# else
7271 png_set_background_fixed(pp, &dp->background_color,
7272 dp->do_background, 0/*need_expand*/, g);
7273# endif
7274# else
7275 png_error(pp, "png_set_background not supported");
7276# endif
7277 }
7278 }
7279
7280 {
7281 int i = dp->this.use_update_info;
7282 /* Always do one call, even if use_update_info is 0. */
7283 do
7284 png_read_update_info(pp, pi);
7285 while (--i > 0);
7286 }
7287
7288 /* Now we may get a different cbRow: */
7289 standard_info_part2(&dp->this, pp, pi, 1 /*images*/);
7290}
7291
7292static void
7293gamma_info(png_structp pp, png_infop pi)
7294{
7295 gamma_info_imp(voidcast(gamma_display*, png_get_progressive_ptr(pp)), pp,
7296 pi);
7297}
7298
7299/* Validate a single component value - the routine gets the input and output
7300 * sample values as unscaled PNG component values along with a cache of all the
7301 * information required to validate the values.
7302 */
7303typedef struct validate_info
7304{
7305 png_structp pp;
7306 gamma_display *dp;
7307 png_byte sbit;
7308 int use_input_precision;
7309 int do_background;
7310 int scale16;
7311 unsigned int sbit_max;
7312 unsigned int isbit_shift;
7313 unsigned int outmax;
7314
7315 double gamma_correction; /* Overall correction required. */
7316 double file_inverse; /* Inverse of file gamma. */
7317 double screen_gamma;
7318 double screen_inverse; /* Inverse of screen gamma. */
7319
7320 double background_red; /* Linear background value, red or gray. */
7321 double background_green;
7322 double background_blue;
7323
7324 double maxabs;
7325 double maxpc;
7326 double maxcalc;
7327 double maxout;
7328 double maxout_total; /* Total including quantization error */
7329 double outlog;
7330 int outquant;
7331}
7332validate_info;
7333
7334static void
7335init_validate_info(validate_info *vi, gamma_display *dp, png_struct *pp,
7336 int in_depth, int out_depth)
7337{
7338 PNG_CONST unsigned int outmax = (1U<<out_depth)-1;
7339
7340 vi->pp = pp;
7341 vi->dp = dp;
7342
7343 if (dp->sbit > 0 && dp->sbit < in_depth)
7344 {
7345 vi->sbit = dp->sbit;
7346 vi->isbit_shift = in_depth - dp->sbit;
7347 }
7348
7349 else
7350 {
7351 vi->sbit = (png_byte)in_depth;
7352 vi->isbit_shift = 0;
7353 }
7354
7355 vi->sbit_max = (1U << vi->sbit)-1;
7356
7357 /* This mimics the libpng threshold test, '0' is used to prevent gamma
7358 * correction in the validation test.
7359 */
7360 vi->screen_gamma = dp->screen_gamma;
7361 if (fabs(vi->screen_gamma-1) < PNG_GAMMA_THRESHOLD)
7362 vi->screen_gamma = vi->screen_inverse = 0;
7363 else
7364 vi->screen_inverse = 1/vi->screen_gamma;
7365
7366 vi->use_input_precision = dp->use_input_precision;
7367 vi->outmax = outmax;
7368 vi->maxabs = abserr(dp->pm, in_depth, out_depth);
7369 vi->maxpc = pcerr(dp->pm, in_depth, out_depth);
7370 vi->maxcalc = calcerr(dp->pm, in_depth, out_depth);
7371 vi->maxout = outerr(dp->pm, in_depth, out_depth);
7372 vi->outquant = output_quantization_factor(dp->pm, in_depth, out_depth);
7373 vi->maxout_total = vi->maxout + vi->outquant * .5;
7374 vi->outlog = outlog(dp->pm, in_depth, out_depth);
7375
7376 if ((dp->this.colour_type & PNG_COLOR_MASK_ALPHA) != 0 ||
7377 (dp->this.colour_type == 3 && dp->this.is_transparent))
7378 {
7379 vi->do_background = dp->do_background;
7380
7381 if (vi->do_background != 0)
7382 {
7383 PNG_CONST double bg_inverse = 1/dp->background_gamma;
7384 double r, g, b;
7385
7386 /* Caller must at least put the gray value into the red channel */
7387 r = dp->background_color.red; r /= outmax;
7388 g = dp->background_color.green; g /= outmax;
7389 b = dp->background_color.blue; b /= outmax;
7390
7391# if 0
7392 /* libpng doesn't do this optimization, if we do pngvalid will fail.
7393 */
7394 if (fabs(bg_inverse-1) >= PNG_GAMMA_THRESHOLD)
7395# endif
7396 {
7397 r = pow(r, bg_inverse);
7398 g = pow(g, bg_inverse);
7399 b = pow(b, bg_inverse);
7400 }
7401
7402 vi->background_red = r;
7403 vi->background_green = g;
7404 vi->background_blue = b;
7405 }
7406 }
7407 else
7408 vi->do_background = 0;
7409
7410 if (vi->do_background == 0)
7411 vi->background_red = vi->background_green = vi->background_blue = 0;
7412
7413 vi->gamma_correction = 1/(dp->file_gamma*dp->screen_gamma);
7414 if (fabs(vi->gamma_correction-1) < PNG_GAMMA_THRESHOLD)
7415 vi->gamma_correction = 0;
7416
7417 vi->file_inverse = 1/dp->file_gamma;
7418 if (fabs(vi->file_inverse-1) < PNG_GAMMA_THRESHOLD)
7419 vi->file_inverse = 0;
7420
7421 vi->scale16 = dp->scale16;
7422}
7423
7424/* This function handles composition of a single non-alpha component. The
7425 * argument is the input sample value, in the range 0..1, and the alpha value.
7426 * The result is the composed, linear, input sample. If alpha is less than zero
7427 * this is the alpha component and the function should not be called!
7428 */
7429static double
7430gamma_component_compose(int do_background, double input_sample, double alpha,
7431 double background, int *compose)
7432{
7433 switch (do_background)
7434 {
7435 case PNG_BACKGROUND_GAMMA_SCREEN:
7436 case PNG_BACKGROUND_GAMMA_FILE:
7437 case PNG_BACKGROUND_GAMMA_UNIQUE:
7438 /* Standard PNG background processing. */
7439 if (alpha < 1)
7440 {
7441 if (alpha > 0)
7442 {
7443 input_sample = input_sample * alpha + background * (1-alpha);
7444 if (compose != NULL)
7445 *compose = 1;
7446 }
7447
7448 else
7449 input_sample = background;
7450 }
7451 break;
7452
7453#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7454 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
7455 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
7456 /* The components are premultiplied in either case and the output is
7457 * gamma encoded (to get standard Porter-Duff we expect the output
7458 * gamma to be set to 1.0!)
7459 */
7460 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
7461 /* The optimization is that the partial-alpha entries are linear
7462 * while the opaque pixels are gamma encoded, but this only affects the
7463 * output encoding.
7464 */
7465 if (alpha < 1)
7466 {
7467 if (alpha > 0)
7468 {
7469 input_sample *= alpha;
7470 if (compose != NULL)
7471 *compose = 1;
7472 }
7473
7474 else
7475 input_sample = 0;
7476 }
7477 break;
7478#endif
7479
7480 default:
7481 /* Standard cases where no compositing is done (so the component
7482 * value is already correct.)
7483 */
7484 break;
7485 }
7486
7487 return input_sample;
7488}
7489
7490/* This API returns the encoded *input* component, in the range 0..1 */
7491static double
7492gamma_component_validate(PNG_CONST char *name, PNG_CONST validate_info *vi,
7493 PNG_CONST unsigned int id, PNG_CONST unsigned int od,
7494 PNG_CONST double alpha /* <0 for the alpha channel itself */,
7495 PNG_CONST double background /* component background value */)
7496{
7497 PNG_CONST unsigned int isbit = id >> vi->isbit_shift;
7498 PNG_CONST unsigned int sbit_max = vi->sbit_max;
7499 PNG_CONST unsigned int outmax = vi->outmax;
7500 PNG_CONST int do_background = vi->do_background;
7501
7502 double i;
7503
7504 /* First check on the 'perfect' result obtained from the digitized input
7505 * value, id, and compare this against the actual digitized result, 'od'.
7506 * 'i' is the input result in the range 0..1:
7507 */
7508 i = isbit; i /= sbit_max;
7509
7510 /* Check for the fast route: if we don't do any background composition or if
7511 * this is the alpha channel ('alpha' < 0) or if the pixel is opaque then
7512 * just use the gamma_correction field to correct to the final output gamma.
7513 */
7514 if (alpha == 1 /* opaque pixel component */ || !do_background
7515#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7516 || do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_PNG
7517#endif
7518 || (alpha < 0 /* alpha channel */
7519#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7520 && do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN
7521#endif
7522 ))
7523 {
7524 /* Then get the gamma corrected version of 'i' and compare to 'od', any
7525 * error less than .5 is insignificant - just quantization of the output
7526 * value to the nearest digital value (nevertheless the error is still
7527 * recorded - it's interesting ;-)
7528 */
7529 double encoded_sample = i;
7530 double encoded_error;
7531
7532 /* alpha less than 0 indicates the alpha channel, which is always linear
7533 */
7534 if (alpha >= 0 && vi->gamma_correction > 0)
7535 encoded_sample = pow(encoded_sample, vi->gamma_correction);
7536 encoded_sample *= outmax;
7537
7538 encoded_error = fabs(od-encoded_sample);
7539
7540 if (encoded_error > vi->dp->maxerrout)
7541 vi->dp->maxerrout = encoded_error;
7542
7543 if (encoded_error < vi->maxout_total && encoded_error < vi->outlog)
7544 return i;
7545 }
7546
7547 /* The slow route - attempt to do linear calculations. */
7548 /* There may be an error, or background processing is required, so calculate
7549 * the actual sample values - unencoded light intensity values. Note that in
7550 * practice these are not completely unencoded because they include a
7551 * 'viewing correction' to decrease or (normally) increase the perceptual
7552 * contrast of the image. There's nothing we can do about this - we don't
7553 * know what it is - so assume the unencoded value is perceptually linear.
7554 */
7555 {
7556 double input_sample = i; /* In range 0..1 */
7557 double output, error, encoded_sample, encoded_error;
7558 double es_lo, es_hi;
7559 int compose = 0; /* Set to one if composition done */
7560 int output_is_encoded; /* Set if encoded to screen gamma */
7561 int log_max_error = 1; /* Check maximum error values */
7562 png_const_charp pass = 0; /* Reason test passes (or 0 for fail) */
7563
7564 /* Convert to linear light (with the above caveat.) The alpha channel is
7565 * already linear.
7566 */
7567 if (alpha >= 0)
7568 {
7569 int tcompose;
7570
7571 if (vi->file_inverse > 0)
7572 input_sample = pow(input_sample, vi->file_inverse);
7573
7574 /* Handle the compose processing: */
7575 tcompose = 0;
7576 input_sample = gamma_component_compose(do_background, input_sample,
7577 alpha, background, &tcompose);
7578
7579 if (tcompose)
7580 compose = 1;
7581 }
7582
7583 /* And similarly for the output value, but we need to check the background
7584 * handling to linearize it correctly.
7585 */
7586 output = od;
7587 output /= outmax;
7588
7589 output_is_encoded = vi->screen_gamma > 0;
7590
7591 if (alpha < 0) /* The alpha channel */
7592 {
7593#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7594 if (do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN)
7595#endif
7596 {
7597 /* In all other cases the output alpha channel is linear already,
7598 * don't log errors here, they are much larger in linear data.
7599 */
7600 output_is_encoded = 0;
7601 log_max_error = 0;
7602 }
7603 }
7604
7605#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7606 else /* A component */
7607 {
7608 if (do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED &&
7609 alpha < 1) /* the optimized case - linear output */
7610 {
7611 if (alpha > 0) log_max_error = 0;
7612 output_is_encoded = 0;
7613 }
7614 }
7615#endif
7616
7617 if (output_is_encoded)
7618 output = pow(output, vi->screen_gamma);
7619
7620 /* Calculate (or recalculate) the encoded_sample value and repeat the
7621 * check above (unnecessary if we took the fast route, but harmless.)
7622 */
7623 encoded_sample = input_sample;
7624 if (output_is_encoded)
7625 encoded_sample = pow(encoded_sample, vi->screen_inverse);
7626 encoded_sample *= outmax;
7627
7628 encoded_error = fabs(od-encoded_sample);
7629
7630 /* Don't log errors in the alpha channel, or the 'optimized' case,
7631 * neither are significant to the overall perception.
7632 */
7633 if (log_max_error && encoded_error > vi->dp->maxerrout)
7634 vi->dp->maxerrout = encoded_error;
7635
7636 if (encoded_error < vi->maxout_total)
7637 {
7638 if (encoded_error < vi->outlog)
7639 return i;
7640
7641 /* Test passed but error is bigger than the log limit, record why the
7642 * test passed:
7643 */
7644 pass = "less than maxout:\n";
7645 }
7646
7647 /* i: the original input value in the range 0..1
7648 *
7649 * pngvalid calculations:
7650 * input_sample: linear result; i linearized and composed, range 0..1
7651 * encoded_sample: encoded result; input_sample scaled to ouput bit depth
7652 *
7653 * libpng calculations:
7654 * output: linear result; od scaled to 0..1 and linearized
7655 * od: encoded result from libpng
7656 */
7657
7658 /* Now we have the numbers for real errors, both absolute values as as a
7659 * percentage of the correct value (output):
7660 */
7661 error = fabs(input_sample-output);
7662
7663 if (log_max_error && error > vi->dp->maxerrabs)
7664 vi->dp->maxerrabs = error;
7665
7666 /* The following is an attempt to ignore the tendency of quantization to
7667 * dominate the percentage errors for lower result values:
7668 */
7669 if (log_max_error && input_sample > .5)
7670 {
7671 double percentage_error = error/input_sample;
7672 if (percentage_error > vi->dp->maxerrpc)
7673 vi->dp->maxerrpc = percentage_error;
7674 }
7675
7676 /* Now calculate the digitization limits for 'encoded_sample' using the
7677 * 'max' values. Note that maxout is in the encoded space but maxpc and
7678 * maxabs are in linear light space.
7679 *
7680 * First find the maximum error in linear light space, range 0..1:
7681 */
7682 {
7683 double tmp = input_sample * vi->maxpc;
7684 if (tmp < vi->maxabs) tmp = vi->maxabs;
7685 /* If 'compose' is true the composition was done in linear space using
7686 * integer arithmetic. This introduces an extra error of +/- 0.5 (at
7687 * least) in the integer space used. 'maxcalc' records this, taking
7688 * into account the possibility that even for 16 bit output 8 bit space
7689 * may have been used.
7690 */
7691 if (compose && tmp < vi->maxcalc) tmp = vi->maxcalc;
7692
7693 /* The 'maxout' value refers to the encoded result, to compare with
7694 * this encode input_sample adjusted by the maximum error (tmp) above.
7695 */
7696 es_lo = encoded_sample - vi->maxout;
7697
7698 if (es_lo > 0 && input_sample-tmp > 0)
7699 {
7700 double low_value = input_sample-tmp;
7701 if (output_is_encoded)
7702 low_value = pow(low_value, vi->screen_inverse);
7703 low_value *= outmax;
7704 if (low_value < es_lo) es_lo = low_value;
7705
7706 /* Quantize this appropriately: */
7707 es_lo = ceil(es_lo / vi->outquant - .5) * vi->outquant;
7708 }
7709
7710 else
7711 es_lo = 0;
7712
7713 es_hi = encoded_sample + vi->maxout;
7714
7715 if (es_hi < outmax && input_sample+tmp < 1)
7716 {
7717 double high_value = input_sample+tmp;
7718 if (output_is_encoded)
7719 high_value = pow(high_value, vi->screen_inverse);
7720 high_value *= outmax;
7721 if (high_value > es_hi) es_hi = high_value;
7722
7723 es_hi = floor(es_hi / vi->outquant + .5) * vi->outquant;
7724 }
7725
7726 else
7727 es_hi = outmax;
7728 }
7729
7730 /* The primary test is that the final encoded value returned by the
7731 * library should be between the two limits (inclusive) that were
7732 * calculated above.
7733 */
7734 if (od >= es_lo && od <= es_hi)
7735 {
7736 /* The value passes, but we may need to log the information anyway. */
7737 if (encoded_error < vi->outlog)
7738 return i;
7739
7740 if (pass == 0)
7741 pass = "within digitization limits:\n";
7742 }
7743
7744 {
7745 /* There has been an error in processing, or we need to log this
7746 * value.
7747 */
7748 double is_lo, is_hi;
7749
7750 /* pass is set at this point if either of the tests above would have
7751 * passed. Don't do these additional tests here - just log the
7752 * original [es_lo..es_hi] values.
7753 */
7754 if (pass == 0 && vi->use_input_precision)
7755 {
7756 /* Ok, something is wrong - this actually happens in current libpng
7757 * 16-to-8 processing. Assume that the input value (id, adjusted
7758 * for sbit) can be anywhere between value-.5 and value+.5 - quite a
7759 * large range if sbit is low.
7760 */
7761 double tmp = (isbit - .5)/sbit_max;
7762
7763 if (tmp <= 0)
7764 tmp = 0;
7765
7766 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1)
7767 tmp = pow(tmp, vi->file_inverse);
7768
7769 tmp = gamma_component_compose(do_background, tmp, alpha, background,
7770 NULL);
7771
7772 if (output_is_encoded && tmp > 0 && tmp < 1)
7773 tmp = pow(tmp, vi->screen_inverse);
7774
7775 is_lo = ceil(outmax * tmp - vi->maxout_total);
7776
7777 if (is_lo < 0)
7778 is_lo = 0;
7779
7780 tmp = (isbit + .5)/sbit_max;
7781
7782 if (tmp <= 0)
7783 tmp = 0;
7784
7785 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1)
7786 tmp = pow(tmp, vi->file_inverse);
7787
7788 tmp = gamma_component_compose(do_background, tmp, alpha, background,
7789 NULL);
7790
7791 if (output_is_encoded && tmp > 0 && tmp < 1)
7792 tmp = pow(tmp, vi->screen_inverse);
7793
7794 is_hi = floor(outmax * tmp + vi->maxout_total);
7795
7796 if (is_hi > outmax)
7797 is_hi = outmax;
7798
7799 if (!(od < is_lo || od > is_hi))
7800 {
7801 if (encoded_error < vi->outlog)
7802 return i;
7803
7804 pass = "within input precision limits:\n";
7805 }
7806
7807 /* One last chance. If this is an alpha channel and the 16to8
7808 * option has been used and 'inaccurate' scaling is used then the
7809 * bit reduction is obtained by simply using the top 8 bits of the
7810 * value.
7811 *
7812 * This is only done for older libpng versions when the 'inaccurate'
7813 * (chop) method of scaling was used.
7814 */
7815# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
7816# if PNG_LIBPNG_VER < 10504
7817 /* This may be required for other components in the future,
7818 * but at present the presence of gamma correction effectively
7819 * prevents the errors in the component scaling (I don't quite
7820 * understand why, but since it's better this way I care not
7821 * to ask, JB 20110419.)
7822 */
7823 if (pass == 0 && alpha < 0 && vi->scale16 && vi->sbit > 8 &&
7824 vi->sbit + vi->isbit_shift == 16)
7825 {
7826 tmp = ((id >> 8) - .5)/255;
7827
7828 if (tmp > 0)
7829 {
7830 is_lo = ceil(outmax * tmp - vi->maxout_total);
7831 if (is_lo < 0) is_lo = 0;
7832 }
7833
7834 else
7835 is_lo = 0;
7836
7837 tmp = ((id >> 8) + .5)/255;
7838
7839 if (tmp < 1)
7840 {
7841 is_hi = floor(outmax * tmp + vi->maxout_total);
7842 if (is_hi > outmax) is_hi = outmax;
7843 }
7844
7845 else
7846 is_hi = outmax;
7847
7848 if (!(od < is_lo || od > is_hi))
7849 {
7850 if (encoded_error < vi->outlog)
7851 return i;
7852
7853 pass = "within 8 bit limits:\n";
7854 }
7855 }
7856# endif
7857# endif
7858 }
7859 else /* !use_input_precision */
7860 is_lo = es_lo, is_hi = es_hi;
7861
7862 /* Attempt to output a meaningful error/warning message: the message
7863 * output depends on the background/composite operation being performed
7864 * because this changes what parameters were actually used above.
7865 */
7866 {
7867 size_t pos = 0;
7868 /* Need either 1/255 or 1/65535 precision here; 3 or 6 decimal
7869 * places. Just use outmax to work out which.
7870 */
7871 int precision = (outmax >= 1000 ? 6 : 3);
7872 int use_input=1, use_background=0, do_compose=0;
7873 char msg[256];
7874
7875 if (pass != 0)
7876 pos = safecat(msg, sizeof msg, pos, "\n\t");
7877
7878 /* Set up the various flags, the output_is_encoded flag above
7879 * is also used below. do_compose is just a double check.
7880 */
7881 switch (do_background)
7882 {
7883 case PNG_BACKGROUND_GAMMA_SCREEN:
7884 case PNG_BACKGROUND_GAMMA_FILE:
7885 case PNG_BACKGROUND_GAMMA_UNIQUE:
7886 use_background = (alpha >= 0 && alpha < 1);
7887 /*FALL THROUGH*/
7888# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7889 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
7890 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
7891 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
7892# endif /* ALPHA_MODE_SUPPORTED */
7893 do_compose = (alpha > 0 && alpha < 1);
7894 use_input = (alpha != 0);
7895 break;
7896
7897 default:
7898 break;
7899 }
7900
7901 /* Check the 'compose' flag */
7902 if (compose != do_compose)
7903 png_error(vi->pp, "internal error (compose)");
7904
7905 /* 'name' is the component name */
7906 pos = safecat(msg, sizeof msg, pos, name);
7907 pos = safecat(msg, sizeof msg, pos, "(");
7908 pos = safecatn(msg, sizeof msg, pos, id);
7909 if (use_input || pass != 0/*logging*/)
7910 {
7911 if (isbit != id)
7912 {
7913 /* sBIT has reduced the precision of the input: */
7914 pos = safecat(msg, sizeof msg, pos, ", sbit(");
7915 pos = safecatn(msg, sizeof msg, pos, vi->sbit);
7916 pos = safecat(msg, sizeof msg, pos, "): ");
7917 pos = safecatn(msg, sizeof msg, pos, isbit);
7918 }
7919 pos = safecat(msg, sizeof msg, pos, "/");
7920 /* The output is either "id/max" or "id sbit(sbit): isbit/max" */
7921 pos = safecatn(msg, sizeof msg, pos, vi->sbit_max);
7922 }
7923 pos = safecat(msg, sizeof msg, pos, ")");
7924
7925 /* A component may have been multiplied (in linear space) by the
7926 * alpha value, 'compose' says whether this is relevant.
7927 */
7928 if (compose || pass != 0)
7929 {
7930 /* If any form of composition is being done report our
7931 * calculated linear value here (the code above doesn't record
7932 * the input value before composition is performed, so what
7933 * gets reported is the value after composition.)
7934 */
7935 if (use_input || pass != 0)
7936 {
7937 if (vi->file_inverse > 0)
7938 {
7939 pos = safecat(msg, sizeof msg, pos, "^");
7940 pos = safecatd(msg, sizeof msg, pos, vi->file_inverse, 2);
7941 }
7942
7943 else
7944 pos = safecat(msg, sizeof msg, pos, "[linear]");
7945
7946 pos = safecat(msg, sizeof msg, pos, "*(alpha)");
7947 pos = safecatd(msg, sizeof msg, pos, alpha, precision);
7948 }
7949
7950 /* Now record the *linear* background value if it was used
7951 * (this function is not passed the original, non-linear,
7952 * value but it is contained in the test name.)
7953 */
7954 if (use_background)
7955 {
7956 pos = safecat(msg, sizeof msg, pos, use_input ? "+" : " ");
7957 pos = safecat(msg, sizeof msg, pos, "(background)");
7958 pos = safecatd(msg, sizeof msg, pos, background, precision);
7959 pos = safecat(msg, sizeof msg, pos, "*");
7960 pos = safecatd(msg, sizeof msg, pos, 1-alpha, precision);
7961 }
7962 }
7963
7964 /* Report the calculated value (input_sample) and the linearized
7965 * libpng value (output) unless this is just a component gamma
7966 * correction.
7967 */
7968 if (compose || alpha < 0 || pass != 0)
7969 {
7970 pos = safecat(msg, sizeof msg, pos,
7971 pass != 0 ? " =\n\t" : " = ");
7972 pos = safecatd(msg, sizeof msg, pos, input_sample, precision);
7973 pos = safecat(msg, sizeof msg, pos, " (libpng: ");
7974 pos = safecatd(msg, sizeof msg, pos, output, precision);
7975 pos = safecat(msg, sizeof msg, pos, ")");
7976
7977 /* Finally report the output gamma encoding, if any. */
7978 if (output_is_encoded)
7979 {
7980 pos = safecat(msg, sizeof msg, pos, " ^");
7981 pos = safecatd(msg, sizeof msg, pos, vi->screen_inverse, 2);
7982 pos = safecat(msg, sizeof msg, pos, "(to screen) =");
7983 }
7984
7985 else
7986 pos = safecat(msg, sizeof msg, pos, " [screen is linear] =");
7987 }
7988
7989 if ((!compose && alpha >= 0) || pass != 0)
7990 {
7991 if (pass != 0) /* logging */
7992 pos = safecat(msg, sizeof msg, pos, "\n\t[overall:");
7993
7994 /* This is the non-composition case, the internal linear
7995 * values are irrelevant (though the log below will reveal
7996 * them.) Output a much shorter warning/error message and report
7997 * the overall gamma correction.
7998 */
7999 if (vi->gamma_correction > 0)
8000 {
8001 pos = safecat(msg, sizeof msg, pos, " ^");
8002 pos = safecatd(msg, sizeof msg, pos, vi->gamma_correction, 2);
8003 pos = safecat(msg, sizeof msg, pos, "(gamma correction) =");
8004 }
8005
8006 else
8007 pos = safecat(msg, sizeof msg, pos,
8008 " [no gamma correction] =");
8009
8010 if (pass != 0)
8011 pos = safecat(msg, sizeof msg, pos, "]");
8012 }
8013
8014 /* This is our calculated encoded_sample which should (but does
8015 * not) match od:
8016 */
8017 pos = safecat(msg, sizeof msg, pos, pass != 0 ? "\n\t" : " ");
8018 pos = safecatd(msg, sizeof msg, pos, is_lo, 1);
8019 pos = safecat(msg, sizeof msg, pos, " < ");
8020 pos = safecatd(msg, sizeof msg, pos, encoded_sample, 1);
8021 pos = safecat(msg, sizeof msg, pos, " (libpng: ");
8022 pos = safecatn(msg, sizeof msg, pos, od);
8023 pos = safecat(msg, sizeof msg, pos, ")");
8024 pos = safecat(msg, sizeof msg, pos, "/");
8025 pos = safecatn(msg, sizeof msg, pos, outmax);
8026 pos = safecat(msg, sizeof msg, pos, " < ");
8027 pos = safecatd(msg, sizeof msg, pos, is_hi, 1);
8028
8029 if (pass == 0) /* The error condition */
8030 {
8031# ifdef PNG_WARNINGS_SUPPORTED
8032 png_warning(vi->pp, msg);
8033# else
8034 store_warning(vi->pp, msg);
8035# endif
8036 }
8037
8038 else /* logging this value */
8039 store_verbose(&vi->dp->pm->this, vi->pp, pass, msg);
8040 }
8041 }
8042 }
8043
8044 return i;
8045}
8046
8047static void
8048gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi)
8049{
8050 /* Get some constants derived from the input and output file formats: */
8051 PNG_CONST png_store* PNG_CONST ps = dp->this.ps;
8052 PNG_CONST png_byte in_ct = dp->this.colour_type;
8053 PNG_CONST png_byte in_bd = dp->this.bit_depth;
8054 PNG_CONST png_uint_32 w = dp->this.w;
8055 PNG_CONST png_uint_32 h = dp->this.h;
8056 PNG_CONST size_t cbRow = dp->this.cbRow;
8057 PNG_CONST png_byte out_ct = png_get_color_type(pp, pi);
8058 PNG_CONST png_byte out_bd = png_get_bit_depth(pp, pi);
8059
8060 /* There are three sources of error, firstly the quantization in the
8061 * file encoding, determined by sbit and/or the file depth, secondly
8062 * the output (screen) gamma and thirdly the output file encoding.
8063 *
8064 * Since this API receives the screen and file gamma in double
8065 * precision it is possible to calculate an exact answer given an input
8066 * pixel value. Therefore we assume that the *input* value is exact -
8067 * sample/maxsample - calculate the corresponding gamma corrected
8068 * output to the limits of double precision arithmetic and compare with
8069 * what libpng returns.
8070 *
8071 * Since the library must quantize the output to 8 or 16 bits there is
8072 * a fundamental limit on the accuracy of the output of +/-.5 - this
8073 * quantization limit is included in addition to the other limits
8074 * specified by the paramaters to the API. (Effectively, add .5
8075 * everywhere.)
8076 *
8077 * The behavior of the 'sbit' paramter is defined by section 12.5
8078 * (sample depth scaling) of the PNG spec. That section forces the
8079 * decoder to assume that the PNG values have been scaled if sBIT is
8080 * present:
8081 *
8082 * png-sample = floor( input-sample * (max-out/max-in) + .5);
8083 *
8084 * This means that only a subset of the possible PNG values should
8085 * appear in the input. However, the spec allows the encoder to use a
8086 * variety of approximations to the above and doesn't require any
8087 * restriction of the values produced.
8088 *
8089 * Nevertheless the spec requires that the upper 'sBIT' bits of the
8090 * value stored in a PNG file be the original sample bits.
8091 * Consequently the code below simply scales the top sbit bits by
8092 * (1<<sbit)-1 to obtain an original sample value.
8093 *
8094 * Because there is limited precision in the input it is arguable that
8095 * an acceptable result is any valid result from input-.5 to input+.5.
8096 * The basic tests below do not do this, however if 'use_input_precision'
8097 * is set a subsequent test is performed below.
8098 */
8099 PNG_CONST unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U;
8100 int processing;
8101 png_uint_32 y;
8102 PNG_CONST store_palette_entry *in_palette = dp->this.palette;
8103 PNG_CONST int in_is_transparent = dp->this.is_transparent;
8104 int out_npalette = -1;
8105 int out_is_transparent = 0; /* Just refers to the palette case */
8106 store_palette out_palette;
8107 validate_info vi;
8108
8109 /* Check for row overwrite errors */
8110 store_image_check(dp->this.ps, pp, 0);
8111
8112 /* Supply the input and output sample depths here - 8 for an indexed image,
8113 * otherwise the bit depth.
8114 */
8115 init_validate_info(&vi, dp, pp, in_ct==3?8:in_bd, out_ct==3?8:out_bd);
8116
8117 processing = (vi.gamma_correction > 0 && !dp->threshold_test)
8118 || in_bd != out_bd || in_ct != out_ct || vi.do_background;
8119
8120 /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside
8121 * the palette there is no way of finding out, because libpng fails to
8122 * update the palette on png_read_update_info. Indeed, libpng doesn't
8123 * even do the required work until much later, when it doesn't have any
8124 * info pointer. Oops. For the moment 'processing' is turned off if
8125 * out_ct is palette.
8126 */
8127 if (in_ct == 3 && out_ct == 3)
8128 processing = 0;
8129
8130 if (processing && out_ct == 3)
8131 out_is_transparent = read_palette(out_palette, &out_npalette, pp, pi);
8132
8133 for (y=0; y<h; ++y)
8134 {
8135 png_const_bytep pRow = store_image_row(ps, pp, 0, y);
8136 png_byte std[STANDARD_ROWMAX];
8137
8138 transform_row(pp, std, in_ct, in_bd, y);
8139
8140 if (processing)
8141 {
8142 unsigned int x;
8143
8144 for (x=0; x<w; ++x)
8145 {
8146 double alpha = 1; /* serves as a flag value */
8147
8148 /* Record the palette index for index images. */
8149 PNG_CONST unsigned int in_index =
8150 in_ct == 3 ? sample(std, 3, in_bd, x, 0) : 256;
8151 PNG_CONST unsigned int out_index =
8152 out_ct == 3 ? sample(std, 3, out_bd, x, 0) : 256;
8153
8154 /* Handle input alpha - png_set_background will cause the output
8155 * alpha to disappear so there is nothing to check.
8156 */
8157 if ((in_ct & PNG_COLOR_MASK_ALPHA) != 0 || (in_ct == 3 &&
8158 in_is_transparent))
8159 {
8160 PNG_CONST unsigned int input_alpha = in_ct == 3 ?
8161 dp->this.palette[in_index].alpha :
8162 sample(std, in_ct, in_bd, x, samples_per_pixel);
8163
8164 unsigned int output_alpha = 65536 /* as a flag value */;
8165
8166 if (out_ct == 3)
8167 {
8168 if (out_is_transparent)
8169 output_alpha = out_palette[out_index].alpha;
8170 }
8171
8172 else if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0)
8173 output_alpha = sample(pRow, out_ct, out_bd, x,
8174 samples_per_pixel);
8175
8176 if (output_alpha != 65536)
8177 alpha = gamma_component_validate("alpha", &vi, input_alpha,
8178 output_alpha, -1/*alpha*/, 0/*background*/);
8179
8180 else /* no alpha in output */
8181 {
8182 /* This is a copy of the calculation of 'i' above in order to
8183 * have the alpha value to use in the background calculation.
8184 */
8185 alpha = input_alpha >> vi.isbit_shift;
8186 alpha /= vi.sbit_max;
8187 }
8188 }
8189
8190 /* Handle grayscale or RGB components. */
8191 if ((in_ct & PNG_COLOR_MASK_COLOR) == 0) /* grayscale */
8192 (void)gamma_component_validate("gray", &vi,
8193 sample(std, in_ct, in_bd, x, 0),
8194 sample(pRow, out_ct, out_bd, x, 0), alpha/*component*/,
8195 vi.background_red);
8196 else /* RGB or palette */
8197 {
8198 (void)gamma_component_validate("red", &vi,
8199 in_ct == 3 ? in_palette[in_index].red :
8200 sample(std, in_ct, in_bd, x, 0),
8201 out_ct == 3 ? out_palette[out_index].red :
8202 sample(pRow, out_ct, out_bd, x, 0),
8203 alpha/*component*/, vi.background_red);
8204
8205 (void)gamma_component_validate("green", &vi,
8206 in_ct == 3 ? in_palette[in_index].green :
8207 sample(std, in_ct, in_bd, x, 1),
8208 out_ct == 3 ? out_palette[out_index].green :
8209 sample(pRow, out_ct, out_bd, x, 1),
8210 alpha/*component*/, vi.background_green);
8211
8212 (void)gamma_component_validate("blue", &vi,
8213 in_ct == 3 ? in_palette[in_index].blue :
8214 sample(std, in_ct, in_bd, x, 2),
8215 out_ct == 3 ? out_palette[out_index].blue :
8216 sample(pRow, out_ct, out_bd, x, 2),
8217 alpha/*component*/, vi.background_blue);
8218 }
8219 }
8220 }
8221
8222 else if (memcmp(std, pRow, cbRow) != 0)
8223 {
8224 char msg[64];
8225
8226 /* No transform is expected on the threshold tests. */
8227 sprintf(msg, "gamma: below threshold row %d changed", y);
8228
8229 png_error(pp, msg);
8230 }
8231 } /* row (y) loop */
8232
8233 dp->this.ps->validated = 1;
8234}
8235
8236static void
8237gamma_end(png_structp pp, png_infop pi)
8238{
8239 gamma_display *dp = voidcast(gamma_display*, png_get_progressive_ptr(pp));
8240
8241 if (!dp->this.speed)
8242 gamma_image_validate(dp, pp, pi);
8243 else
8244 dp->this.ps->validated = 1;
8245}
8246
8247/* A single test run checking a gamma transformation.
8248 *
8249 * maxabs: maximum absolute error as a fraction
8250 * maxout: maximum output error in the output units
8251 * maxpc: maximum percentage error (as a percentage)
8252 */
8253static void
8254gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn,
8255 PNG_CONST png_byte bit_depthIn, PNG_CONST int palette_numberIn,
8256 PNG_CONST int interlace_typeIn,
8257 PNG_CONST double file_gammaIn, PNG_CONST double screen_gammaIn,
8258 PNG_CONST png_byte sbitIn, PNG_CONST int threshold_testIn,
8259 PNG_CONST char *name,
8260 PNG_CONST int use_input_precisionIn, PNG_CONST int scale16In,
8261 PNG_CONST int expand16In, PNG_CONST int do_backgroundIn,
8262 PNG_CONST png_color_16 *bkgd_colorIn, double bkgd_gammaIn)
8263{
8264 gamma_display d;
8265 context(&pmIn->this, fault);
8266
8267 gamma_display_init(&d, pmIn, FILEID(colour_typeIn, bit_depthIn,
8268 palette_numberIn, interlace_typeIn, 0, 0, 0),
8269 file_gammaIn, screen_gammaIn, sbitIn,
8270 threshold_testIn, use_input_precisionIn, scale16In,
8271 expand16In, do_backgroundIn, bkgd_colorIn, bkgd_gammaIn);
8272
8273 Try
8274 {
8275 png_structp pp;
8276 png_infop pi;
8277 gama_modification gama_mod;
8278 srgb_modification srgb_mod;
8279 sbit_modification sbit_mod;
8280
8281 /* For the moment don't use the png_modifier support here. */
8282 d.pm->encoding_counter = 0;
8283 modifier_set_encoding(d.pm); /* Just resets everything */
8284 d.pm->current_gamma = d.file_gamma;
8285
8286 /* Make an appropriate modifier to set the PNG file gamma to the
8287 * given gamma value and the sBIT chunk to the given precision.
8288 */
8289 d.pm->modifications = NULL;
8290 gama_modification_init(&gama_mod, d.pm, d.file_gamma);
8291 srgb_modification_init(&srgb_mod, d.pm, 127 /*delete*/);
8292 if (d.sbit > 0)
8293 sbit_modification_init(&sbit_mod, d.pm, d.sbit);
8294
8295 modification_reset(d.pm->modifications);
8296
8297 /* Get a png_struct for writing the image. */
8298 pp = set_modifier_for_read(d.pm, &pi, d.this.id, name);
8299 standard_palette_init(&d.this);
8300
8301 /* Introduce the correct read function. */
8302 if (d.pm->this.progressive)
8303 {
8304 /* Share the row function with the standard implementation. */
8305 png_set_progressive_read_fn(pp, &d, gamma_info, progressive_row,
8306 gamma_end);
8307
8308 /* Now feed data into the reader until we reach the end: */
8309 modifier_progressive_read(d.pm, pp, pi);
8310 }
8311 else
8312 {
8313 /* modifier_read expects a png_modifier* */
8314 png_set_read_fn(pp, d.pm, modifier_read);
8315
8316 /* Check the header values: */
8317 png_read_info(pp, pi);
8318
8319 /* Process the 'info' requirements. Only one image is generated */
8320 gamma_info_imp(&d, pp, pi);
8321
8322 sequential_row(&d.this, pp, pi, -1, 0);
8323
8324 if (!d.this.speed)
8325 gamma_image_validate(&d, pp, pi);
8326 else
8327 d.this.ps->validated = 1;
8328 }
8329
8330 modifier_reset(d.pm);
8331
8332 if (d.pm->log && !d.threshold_test && !d.this.speed)
8333 fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n",
8334 d.this.bit_depth, colour_types[d.this.colour_type], name,
8335 d.maxerrout, d.maxerrabs, 100*d.maxerrpc);
8336
8337 /* Log the summary values too. */
8338 if (d.this.colour_type == 0 || d.this.colour_type == 4)
8339 {
8340 switch (d.this.bit_depth)
8341 {
8342 case 1:
8343 break;
8344
8345 case 2:
8346 if (d.maxerrout > d.pm->error_gray_2)
8347 d.pm->error_gray_2 = d.maxerrout;
8348
8349 break;
8350
8351 case 4:
8352 if (d.maxerrout > d.pm->error_gray_4)
8353 d.pm->error_gray_4 = d.maxerrout;
8354
8355 break;
8356
8357 case 8:
8358 if (d.maxerrout > d.pm->error_gray_8)
8359 d.pm->error_gray_8 = d.maxerrout;
8360
8361 break;
8362
8363 case 16:
8364 if (d.maxerrout > d.pm->error_gray_16)
8365 d.pm->error_gray_16 = d.maxerrout;
8366
8367 break;
8368
8369 default:
8370 png_error(pp, "bad bit depth (internal: 1)");
8371 }
8372 }
8373
8374 else if (d.this.colour_type == 2 || d.this.colour_type == 6)
8375 {
8376 switch (d.this.bit_depth)
8377 {
8378 case 8:
8379
8380 if (d.maxerrout > d.pm->error_color_8)
8381 d.pm->error_color_8 = d.maxerrout;
8382
8383 break;
8384
8385 case 16:
8386
8387 if (d.maxerrout > d.pm->error_color_16)
8388 d.pm->error_color_16 = d.maxerrout;
8389
8390 break;
8391
8392 default:
8393 png_error(pp, "bad bit depth (internal: 2)");
8394 }
8395 }
8396
8397 else if (d.this.colour_type == 3)
8398 {
8399 if (d.maxerrout > d.pm->error_indexed)
8400 d.pm->error_indexed = d.maxerrout;
8401 }
8402 }
8403
8404 Catch(fault)
8405 modifier_reset((png_modifier*)fault);
8406}
8407
8408static void gamma_threshold_test(png_modifier *pm, png_byte colour_type,
8409 png_byte bit_depth, int interlace_type, double file_gamma,
8410 double screen_gamma)
8411{
8412 size_t pos = 0;
8413 char name[64];
8414 pos = safecat(name, sizeof name, pos, "threshold ");
8415 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
8416 pos = safecat(name, sizeof name, pos, "/");
8417 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
8418
8419 (void)gamma_test(pm, colour_type, bit_depth, 0/*palette*/, interlace_type,
8420 file_gamma, screen_gamma, 0/*sBIT*/, 1/*threshold test*/, name,
8421 0 /*no input precision*/,
8422 0 /*no scale16*/, 0 /*no expand16*/, 0 /*no background*/, 0 /*hence*/,
8423 0 /*no background gamma*/);
8424}
8425
8426static void
8427perform_gamma_threshold_tests(png_modifier *pm)
8428{
8429 png_byte colour_type = 0;
8430 png_byte bit_depth = 0;
8431 int palette_number = 0;
8432
8433 /* Don't test more than one instance of each palette - it's pointless, in
8434 * fact this test is somewhat excessive since libpng doesn't make this
8435 * decision based on colour type or bit depth!
8436 */
8437 while (next_format(&colour_type, &bit_depth, &palette_number))
8438 if (palette_number == 0)
8439 {
8440 double test_gamma = 1.0;
8441 while (test_gamma >= .4)
8442 {
8443 /* There's little point testing the interlacing vs non-interlacing,
8444 * but this can be set from the command line.
8445 */
8446 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type,
8447 test_gamma, 1/test_gamma);
8448 test_gamma *= .95;
8449 }
8450
8451 /* And a special test for sRGB */
8452 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type,
8453 .45455, 2.2);
8454
8455 if (fail(pm))
8456 return;
8457 }
8458}
8459
8460static void gamma_transform_test(png_modifier *pm,
8461 PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth,
8462 PNG_CONST int palette_number,
8463 PNG_CONST int interlace_type, PNG_CONST double file_gamma,
8464 PNG_CONST double screen_gamma, PNG_CONST png_byte sbit,
8465 PNG_CONST int use_input_precision, PNG_CONST int scale16)
8466{
8467 size_t pos = 0;
8468 char name[64];
8469
8470 if (sbit != bit_depth && sbit != 0)
8471 {
8472 pos = safecat(name, sizeof name, pos, "sbit(");
8473 pos = safecatn(name, sizeof name, pos, sbit);
8474 pos = safecat(name, sizeof name, pos, ") ");
8475 }
8476
8477 else
8478 pos = safecat(name, sizeof name, pos, "gamma ");
8479
8480 if (scale16)
8481 pos = safecat(name, sizeof name, pos, "16to8 ");
8482
8483 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
8484 pos = safecat(name, sizeof name, pos, "->");
8485 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
8486
8487 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type,
8488 file_gamma, screen_gamma, sbit, 0, name, use_input_precision,
8489 scale16, pm->test_gamma_expand16, 0 , 0, 0);
8490}
8491
8492static void perform_gamma_transform_tests(png_modifier *pm)
8493{
8494 png_byte colour_type = 0;
8495 png_byte bit_depth = 0;
8496 int palette_number = 0;
8497
8498 while (next_format(&colour_type, &bit_depth, &palette_number))
8499 {
8500 unsigned int i, j;
8501
8502 for (i=0; i<pm->ngamma_tests; ++i) for (j=0; j<pm->ngamma_tests; ++j)
8503 if (i != j)
8504 {
8505 gamma_transform_test(pm, colour_type, bit_depth, palette_number,
8506 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 0/*sBIT*/,
8507 pm->use_input_precision, 0 /*do not scale16*/);
8508
8509 if (fail(pm))
8510 return;
8511 }
8512 }
8513}
8514
8515static void perform_gamma_sbit_tests(png_modifier *pm)
8516{
8517 png_byte sbit;
8518
8519 /* The only interesting cases are colour and grayscale, alpha is ignored here
8520 * for overall speed. Only bit depths where sbit is less than the bit depth
8521 * are tested.
8522 */
8523 for (sbit=pm->sbitlow; sbit<(1<<READ_BDHI); ++sbit)
8524 {
8525 png_byte colour_type, bit_depth;
8526 int npalette;
8527
8528 colour_type = bit_depth = 0;
8529 npalette = 0;
8530
8531 while (next_format(&colour_type, &bit_depth, &npalette))
8532 if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 &&
8533 ((colour_type == 3 && sbit < 8) ||
8534 (colour_type != 3 && sbit < bit_depth)))
8535 {
8536 unsigned int i;
8537
8538 for (i=0; i<pm->ngamma_tests; ++i)
8539 {
8540 unsigned int j;
8541
8542 for (j=0; j<pm->ngamma_tests; ++j) if (i != j)
8543 {
8544 gamma_transform_test(pm, colour_type, bit_depth, npalette,
8545 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j],
8546 sbit, pm->use_input_precision_sbit, 0 /*scale16*/);
8547
8548 if (fail(pm))
8549 return;
8550 }
8551 }
8552 }
8553 }
8554}
8555
8556/* Note that this requires a 16 bit source image but produces 8 bit output, so
8557 * we only need the 16bit write support, but the 16 bit images are only
8558 * generated if DO_16BIT is defined.
8559 */
8560#ifdef DO_16BIT
8561static void perform_gamma_scale16_tests(png_modifier *pm)
8562{
8563# ifndef PNG_MAX_GAMMA_8
8564# define PNG_MAX_GAMMA_8 11
8565# endif
8566 /* Include the alpha cases here. Note that sbit matches the internal value
8567 * used by the library - otherwise we will get spurious errors from the
8568 * internal sbit style approximation.
8569 *
8570 * The threshold test is here because otherwise the 16 to 8 conversion will
8571 * proceed *without* gamma correction, and the tests above will fail (but not
8572 * by much) - this could be fixed, it only appears with the -g option.
8573 */
8574 unsigned int i, j;
8575 for (i=0; i<pm->ngamma_tests; ++i)
8576 {
8577 for (j=0; j<pm->ngamma_tests; ++j)
8578 {
8579 if (i != j &&
8580 fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD)
8581 {
8582 gamma_transform_test(pm, 0, 16, 0, pm->interlace_type,
8583 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8,
8584 pm->use_input_precision_16to8, 1 /*scale16*/);
8585
8586 if (fail(pm))
8587 return;
8588
8589 gamma_transform_test(pm, 2, 16, 0, pm->interlace_type,
8590 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8,
8591 pm->use_input_precision_16to8, 1 /*scale16*/);
8592
8593 if (fail(pm))
8594 return;
8595
8596 gamma_transform_test(pm, 4, 16, 0, pm->interlace_type,
8597 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8,
8598 pm->use_input_precision_16to8, 1 /*scale16*/);
8599
8600 if (fail(pm))
8601 return;
8602
8603 gamma_transform_test(pm, 6, 16, 0, pm->interlace_type,
8604 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8,
8605 pm->use_input_precision_16to8, 1 /*scale16*/);
8606
8607 if (fail(pm))
8608 return;
8609 }
8610 }
8611 }
8612}
8613#endif /* 16 to 8 bit conversion */
8614
8615#if defined PNG_READ_BACKGROUND_SUPPORTED ||\
8616 defined PNG_READ_ALPHA_MODE_SUPPORTED
8617static void gamma_composition_test(png_modifier *pm,
8618 PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth,
8619 PNG_CONST int palette_number,
8620 PNG_CONST int interlace_type, PNG_CONST double file_gamma,
8621 PNG_CONST double screen_gamma,
8622 PNG_CONST int use_input_precision, PNG_CONST int do_background,
8623 PNG_CONST int expand_16)
8624{
8625 size_t pos = 0;
8626 png_const_charp base;
8627 double bg;
8628 char name[128];
8629 png_color_16 background;
8630
8631 /* Make up a name and get an appropriate background gamma value. */
8632 switch (do_background)
8633 {
8634 default:
8635 base = "";
8636 bg = 4; /* should not be used */
8637 break;
8638 case PNG_BACKGROUND_GAMMA_SCREEN:
8639 base = " bckg(Screen):";
8640 bg = 1/screen_gamma;
8641 break;
8642 case PNG_BACKGROUND_GAMMA_FILE:
8643 base = " bckg(File):";
8644 bg = file_gamma;
8645 break;
8646 case PNG_BACKGROUND_GAMMA_UNIQUE:
8647 base = " bckg(Unique):";
8648 /* This tests the handling of a unique value, the math is such that the
8649 * value tends to be <1, but is neither screen nor file (even if they
8650 * match!)
8651 */
8652 bg = (file_gamma + screen_gamma) / 3;
8653 break;
8654#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
8655 case ALPHA_MODE_OFFSET + PNG_ALPHA_PNG:
8656 base = " alpha(PNG)";
8657 bg = 4; /* should not be used */
8658 break;
8659 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
8660 base = " alpha(Porter-Duff)";
8661 bg = 4; /* should not be used */
8662 break;
8663 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
8664 base = " alpha(Optimized)";
8665 bg = 4; /* should not be used */
8666 break;
8667 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
8668 base = " alpha(Broken)";
8669 bg = 4; /* should not be used */
8670 break;
8671#endif
8672 }
8673
8674 /* Use random background values - the background is always presented in the
8675 * output space (8 or 16 bit components).
8676 */
8677 if (expand_16 || bit_depth == 16)
8678 {
8679 png_uint_32 r = random_32();
8680
8681 background.red = (png_uint_16)r;
8682 background.green = (png_uint_16)(r >> 16);
8683 r = random_32();
8684 background.blue = (png_uint_16)r;
8685 background.gray = (png_uint_16)(r >> 16);
8686 }
8687
8688 else /* 8 bit colors */
8689 {
8690 png_uint_32 r = random_32();
8691
8692 background.red = (png_byte)r;
8693 background.green = (png_byte)(r >> 8);
8694 background.blue = (png_byte)(r >> 16);
8695 background.gray = (png_byte)(r >> 24);
8696 }
8697
8698 background.index = 193; /* rgb(193,193,193) to detect errors */
8699 if (!(colour_type & PNG_COLOR_MASK_COLOR))
8700 {
8701 /* Grayscale input, we do not convert to RGB (TBD), so we must set the
8702 * background to gray - else libpng seems to fail.
8703 */
8704 background.red = background.green = background.blue = background.gray;
8705 }
8706
8707 pos = safecat(name, sizeof name, pos, "gamma ");
8708 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
8709 pos = safecat(name, sizeof name, pos, "->");
8710 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
8711
8712 pos = safecat(name, sizeof name, pos, base);
8713 if (do_background < ALPHA_MODE_OFFSET)
8714 {
8715 /* Include the background color and gamma in the name: */
8716 pos = safecat(name, sizeof name, pos, "(");
8717 /* This assumes no expand gray->rgb - the current code won't handle that!
8718 */
8719 if (colour_type & PNG_COLOR_MASK_COLOR)
8720 {
8721 pos = safecatn(name, sizeof name, pos, background.red);
8722 pos = safecat(name, sizeof name, pos, ",");
8723 pos = safecatn(name, sizeof name, pos, background.green);
8724 pos = safecat(name, sizeof name, pos, ",");
8725 pos = safecatn(name, sizeof name, pos, background.blue);
8726 }
8727 else
8728 pos = safecatn(name, sizeof name, pos, background.gray);
8729 pos = safecat(name, sizeof name, pos, ")^");
8730 pos = safecatd(name, sizeof name, pos, bg, 3);
8731 }
8732
8733 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type,
8734 file_gamma, screen_gamma, 0/*sBIT*/, 0, name, use_input_precision,
8735 0/*strip 16*/, expand_16, do_background, &background, bg);
8736}
8737
8738
8739static void
8740perform_gamma_composition_tests(png_modifier *pm, int do_background,
8741 int expand_16)
8742{
8743 png_byte colour_type = 0;
8744 png_byte bit_depth = 0;
8745 int palette_number = 0;
8746
8747 /* Skip the non-alpha cases - there is no setting of a transparency colour at
8748 * present.
8749 */
8750 while (next_format(&colour_type, &bit_depth, &palette_number))
8751 if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0)
8752 {
8753 unsigned int i, j;
8754
8755 /* Don't skip the i==j case here - it's relevant. */
8756 for (i=0; i<pm->ngamma_tests; ++i) for (j=0; j<pm->ngamma_tests; ++j)
8757 {
8758 gamma_composition_test(pm, colour_type, bit_depth, palette_number,
8759 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j],
8760 pm->use_input_precision, do_background, expand_16);
8761
8762 if (fail(pm))
8763 return;
8764 }
8765 }
8766}
8767#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
8768
8769static void
8770init_gamma_errors(png_modifier *pm)
8771{
8772 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0;
8773 pm->error_color_8 = 0;
8774 pm->error_indexed = 0;
8775 pm->error_gray_16 = pm->error_color_16 = 0;
8776}
8777
8778static void
8779summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth)
8780{
8781 if (who)
8782 printf("Gamma correction with %s:\n", who);
8783
8784 if (low_bit_depth)
8785 {
8786 printf(" 2 bit gray: %.5f\n", pm->error_gray_2);
8787 printf(" 4 bit gray: %.5f\n", pm->error_gray_4);
8788 printf(" 8 bit gray: %.5f\n", pm->error_gray_8);
8789 printf(" 8 bit color: %.5f\n", pm->error_color_8);
8790 printf(" indexed: %.5f\n", pm->error_indexed);
8791 }
8792
8793#ifdef DO_16BIT
8794 printf(" 16 bit gray: %.5f\n", pm->error_gray_16);
8795 printf(" 16 bit color: %.5f\n", pm->error_color_16);
8796#endif
8797}
8798
8799static void
8800perform_gamma_test(png_modifier *pm, int summary)
8801{
8802 /*TODO: remove this*/
8803 /* Save certain values for the temporary overrides below. */
8804 unsigned int calculations_use_input_precision =
8805 pm->calculations_use_input_precision;
8806 double maxout8 = pm->maxout8;
8807
8808 /* First some arbitrary no-transform tests: */
8809 if (!pm->this.speed && pm->test_gamma_threshold)
8810 {
8811 perform_gamma_threshold_tests(pm);
8812
8813 if (fail(pm))
8814 return;
8815 }
8816
8817 /* Now some real transforms. */
8818 if (pm->test_gamma_transform)
8819 {
8820 init_gamma_errors(pm);
8821 /*TODO: remove this. Necessary because the current libpng
8822 * implementation works in 8 bits:
8823 */
8824 if (pm->test_gamma_expand16)
8825 pm->calculations_use_input_precision = 1;
8826 perform_gamma_transform_tests(pm);
8827 if (!calculations_use_input_precision)
8828 pm->calculations_use_input_precision = 0;
8829
8830 if (summary)
8831 {
8832 printf("Gamma correction error summary\n\n");
8833 printf("The printed value is the maximum error in the pixel values\n");
8834 printf("calculated by the libpng gamma correction code. The error\n");
8835 printf("is calculated as the difference between the output pixel\n");
8836 printf("value (always an integer) and the ideal value from the\n");
8837 printf("libpng specification (typically not an integer).\n\n");
8838
8839 printf("Expect this value to be less than .5 for 8 bit formats,\n");
8840 printf("less than 1 for formats with fewer than 8 bits and a small\n");
8841 printf("number (typically less than 5) for the 16 bit formats.\n");
8842 printf("For performance reasons the value for 16 bit formats\n");
8843 printf("increases when the image file includes an sBIT chunk.\n\n");
8844
8845 summarize_gamma_errors(pm, 0/*who*/, 1);
8846 }
8847 }
8848
8849 /* The sbit tests produce much larger errors: */
8850 if (pm->test_gamma_sbit)
8851 {
8852 init_gamma_errors(pm);
8853 perform_gamma_sbit_tests(pm);
8854
8855 if (summary)
8856 summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U);
8857 }
8858
8859#ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */
8860 if (pm->test_gamma_scale16)
8861 {
8862 /* The 16 to 8 bit strip operations: */
8863 init_gamma_errors(pm);
8864 perform_gamma_scale16_tests(pm);
8865
8866 if (summary)
8867 {
8868 printf("Gamma correction with 16 to 8 bit reduction:\n");
8869 printf(" 16 bit gray: %.5f\n", pm->error_gray_16);
8870 printf(" 16 bit color: %.5f\n", pm->error_color_16);
8871 }
8872 }
8873#endif
8874
8875#ifdef PNG_READ_BACKGROUND_SUPPORTED
8876 if (pm->test_gamma_background)
8877 {
8878 init_gamma_errors(pm);
8879
8880 /*TODO: remove this. Necessary because the current libpng
8881 * implementation works in 8 bits:
8882 */
8883 if (pm->test_gamma_expand16)
8884 {
8885 pm->calculations_use_input_precision = 1;
8886 pm->maxout8 = .499; /* because the 16 bit background is smashed */
8887 }
8888 perform_gamma_composition_tests(pm, PNG_BACKGROUND_GAMMA_UNIQUE,
8889 pm->test_gamma_expand16);
8890 if (!calculations_use_input_precision)
8891 pm->calculations_use_input_precision = 0;
8892 pm->maxout8 = maxout8;
8893
8894 if (summary)
8895 summarize_gamma_errors(pm, "background", 1);
8896 }
8897#endif
8898
8899#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
8900 if (pm->test_gamma_alpha_mode)
8901 {
8902 int do_background;
8903
8904 init_gamma_errors(pm);
8905
8906 /*TODO: remove this. Necessary because the current libpng
8907 * implementation works in 8 bits:
8908 */
8909 if (pm->test_gamma_expand16)
8910 pm->calculations_use_input_precision = 1;
8911 for (do_background = ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD;
8912 do_background <= ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN && !fail(pm);
8913 ++do_background)
8914 perform_gamma_composition_tests(pm, do_background,
8915 pm->test_gamma_expand16);
8916 if (!calculations_use_input_precision)
8917 pm->calculations_use_input_precision = 0;
8918
8919 if (summary)
8920 summarize_gamma_errors(pm, "alpha mode", 1);
8921 }
8922#endif
8923}
8924#endif /* PNG_READ_GAMMA_SUPPORTED */
8925
8926/* INTERLACE MACRO VALIDATION */
8927/* This is copied verbatim from the specification, it is simply the pass
8928 * number in which each pixel in each 8x8 tile appears. The array must
8929 * be indexed adam7[y][x] and notice that the pass numbers are based at
8930 * 1, not 0 - the base libpng uses.
8931 */
8932static PNG_CONST
8933png_byte adam7[8][8] =
8934{
8935 { 1,6,4,6,2,6,4,6 },
8936 { 7,7,7,7,7,7,7,7 },
8937 { 5,6,5,6,5,6,5,6 },
8938 { 7,7,7,7,7,7,7,7 },
8939 { 3,6,4,6,3,6,4,6 },
8940 { 7,7,7,7,7,7,7,7 },
8941 { 5,6,5,6,5,6,5,6 },
8942 { 7,7,7,7,7,7,7,7 }
8943};
8944
8945/* This routine validates all the interlace support macros in png.h for
8946 * a variety of valid PNG widths and heights. It uses a number of similarly
8947 * named internal routines that feed off the above array.
8948 */
8949static png_uint_32
8950png_pass_start_row(int pass)
8951{
8952 int x, y;
8953 ++pass;
8954 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass)
8955 return y;
8956 return 0xf;
8957}
8958
8959static png_uint_32
8960png_pass_start_col(int pass)
8961{
8962 int x, y;
8963 ++pass;
8964 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass)
8965 return x;
8966 return 0xf;
8967}
8968
8969static int
8970png_pass_row_shift(int pass)
8971{
8972 int x, y, base=(-1), inc=8;
8973 ++pass;
8974 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass)
8975 {
8976 if (base == (-1))
8977 base = y;
8978 else if (base == y)
8979 {}
8980 else if (inc == y-base)
8981 base=y;
8982 else if (inc == 8)
8983 inc = y-base, base=y;
8984 else if (inc != y-base)
8985 return 0xff; /* error - more than one 'inc' value! */
8986 }
8987
8988 if (base == (-1)) return 0xfe; /* error - no row in pass! */
8989
8990 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
8991 switch (inc)
8992 {
8993case 2: return 1;
8994case 4: return 2;
8995case 8: return 3;
8996default: break;
8997 }
8998
8999 /* error - unrecognized 'inc' */
9000 return (inc << 8) + 0xfd;
9001}
9002
9003static int
9004png_pass_col_shift(int pass)
9005{
9006 int x, y, base=(-1), inc=8;
9007 ++pass;
9008 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass)
9009 {
9010 if (base == (-1))
9011 base = x;
9012 else if (base == x)
9013 {}
9014 else if (inc == x-base)
9015 base=x;
9016 else if (inc == 8)
9017 inc = x-base, base=x;
9018 else if (inc != x-base)
9019 return 0xff; /* error - more than one 'inc' value! */
9020 }
9021
9022 if (base == (-1)) return 0xfe; /* error - no row in pass! */
9023
9024 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
9025 switch (inc)
9026 {
9027case 1: return 0; /* pass 7 has all the columns */
9028case 2: return 1;
9029case 4: return 2;
9030case 8: return 3;
9031default: break;
9032 }
9033
9034 /* error - unrecognized 'inc' */
9035 return (inc << 8) + 0xfd;
9036}
9037
9038static png_uint_32
9039png_row_from_pass_row(png_uint_32 yIn, int pass)
9040{
9041 /* By examination of the array: */
9042 switch (pass)
9043 {
9044case 0: return yIn * 8;
9045case 1: return yIn * 8;
9046case 2: return yIn * 8 + 4;
9047case 3: return yIn * 4;
9048case 4: return yIn * 4 + 2;
9049case 5: return yIn * 2;
9050case 6: return yIn * 2 + 1;
9051default: break;
9052 }
9053
9054 return 0xff; /* bad pass number */
9055}
9056
9057static png_uint_32
9058png_col_from_pass_col(png_uint_32 xIn, int pass)
9059{
9060 /* By examination of the array: */
9061 switch (pass)
9062 {
9063case 0: return xIn * 8;
9064case 1: return xIn * 8 + 4;
9065case 2: return xIn * 4;
9066case 3: return xIn * 4 + 2;
9067case 4: return xIn * 2;
9068case 5: return xIn * 2 + 1;
9069case 6: return xIn;
9070default: break;
9071 }
9072
9073 return 0xff; /* bad pass number */
9074}
9075
9076static int
9077png_row_in_interlace_pass(png_uint_32 y, int pass)
9078{
9079 /* Is row 'y' in pass 'pass'? */
9080 int x;
9081 y &= 7;
9082 ++pass;
9083 for (x=0; x<8; ++x) if (adam7[y][x] == pass)
9084 return 1;
9085
9086 return 0;
9087}
9088
9089static int
9090png_col_in_interlace_pass(png_uint_32 x, int pass)
9091{
9092 /* Is column 'x' in pass 'pass'? */
9093 int y;
9094 x &= 7;
9095 ++pass;
9096 for (y=0; y<8; ++y) if (adam7[y][x] == pass)
9097 return 1;
9098
9099 return 0;
9100}
9101
9102static png_uint_32
9103png_pass_rows(png_uint_32 height, int pass)
9104{
9105 png_uint_32 tiles = height>>3;
9106 png_uint_32 rows = 0;
9107 unsigned int x, y;
9108
9109 height &= 7;
9110 ++pass;
9111 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass)
9112 {
9113 rows += tiles;
9114 if (y < height) ++rows;
9115 break; /* i.e. break the 'x', column, loop. */
9116 }
9117
9118 return rows;
9119}
9120
9121static png_uint_32
9122png_pass_cols(png_uint_32 width, int pass)
9123{
9124 png_uint_32 tiles = width>>3;
9125 png_uint_32 cols = 0;
9126 unsigned int x, y;
9127
9128 width &= 7;
9129 ++pass;
9130 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass)
9131 {
9132 cols += tiles;
9133 if (x < width) ++cols;
9134 break; /* i.e. break the 'y', row, loop. */
9135 }
9136
9137 return cols;
9138}
9139
9140static void
9141perform_interlace_macro_validation(void)
9142{
9143 /* The macros to validate, first those that depend only on pass:
9144 *
9145 * PNG_PASS_START_ROW(pass)
9146 * PNG_PASS_START_COL(pass)
9147 * PNG_PASS_ROW_SHIFT(pass)
9148 * PNG_PASS_COL_SHIFT(pass)
9149 */
9150 int pass;
9151
9152 for (pass=0; pass<7; ++pass)
9153 {
9154 png_uint_32 m, f, v;
9155
9156 m = PNG_PASS_START_ROW(pass);
9157 f = png_pass_start_row(pass);
9158 if (m != f)
9159 {
9160 fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f);
9161 exit(1);
9162 }
9163
9164 m = PNG_PASS_START_COL(pass);
9165 f = png_pass_start_col(pass);
9166 if (m != f)
9167 {
9168 fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f);
9169 exit(1);
9170 }
9171
9172 m = PNG_PASS_ROW_SHIFT(pass);
9173 f = png_pass_row_shift(pass);
9174 if (m != f)
9175 {
9176 fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f);
9177 exit(1);
9178 }
9179
9180 m = PNG_PASS_COL_SHIFT(pass);
9181 f = png_pass_col_shift(pass);
9182 if (m != f)
9183 {
9184 fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f);
9185 exit(1);
9186 }
9187
9188 /* Macros that depend on the image or sub-image height too:
9189 *
9190 * PNG_PASS_ROWS(height, pass)
9191 * PNG_PASS_COLS(width, pass)
9192 * PNG_ROW_FROM_PASS_ROW(yIn, pass)
9193 * PNG_COL_FROM_PASS_COL(xIn, pass)
9194 * PNG_ROW_IN_INTERLACE_PASS(y, pass)
9195 * PNG_COL_IN_INTERLACE_PASS(x, pass)
9196 */
9197 for (v=0;;)
9198 {
9199 /* First the base 0 stuff: */
9200 m = PNG_ROW_FROM_PASS_ROW(v, pass);
9201 f = png_row_from_pass_row(v, pass);
9202 if (m != f)
9203 {
9204 fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n",
9205 v, pass, m, f);
9206 exit(1);
9207 }
9208
9209 m = PNG_COL_FROM_PASS_COL(v, pass);
9210 f = png_col_from_pass_col(v, pass);
9211 if (m != f)
9212 {
9213 fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n",
9214 v, pass, m, f);
9215 exit(1);
9216 }
9217
9218 m = PNG_ROW_IN_INTERLACE_PASS(v, pass);
9219 f = png_row_in_interlace_pass(v, pass);
9220 if (m != f)
9221 {
9222 fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
9223 v, pass, m, f);
9224 exit(1);
9225 }
9226
9227 m = PNG_COL_IN_INTERLACE_PASS(v, pass);
9228 f = png_col_in_interlace_pass(v, pass);
9229 if (m != f)
9230 {
9231 fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
9232 v, pass, m, f);
9233 exit(1);
9234 }
9235
9236 /* Then the base 1 stuff: */
9237 ++v;
9238 m = PNG_PASS_ROWS(v, pass);
9239 f = png_pass_rows(v, pass);
9240 if (m != f)
9241 {
9242 fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n",
9243 v, pass, m, f);
9244 exit(1);
9245 }
9246
9247 m = PNG_PASS_COLS(v, pass);
9248 f = png_pass_cols(v, pass);
9249 if (m != f)
9250 {
9251 fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n",
9252 v, pass, m, f);
9253 exit(1);
9254 }
9255
9256 /* Move to the next v - the stepping algorithm starts skipping
9257 * values above 1024.
9258 */
9259 if (v > 1024)
9260 {
9261 if (v == PNG_UINT_31_MAX)
9262 break;
9263
9264 v = (v << 1) ^ v;
9265 if (v >= PNG_UINT_31_MAX)
9266 v = PNG_UINT_31_MAX-1;
9267 }
9268 }
9269 }
9270}
9271
9272/* Test color encodings. These values are back-calculated from the published
9273 * chromaticities. The values are accurate to about 14 decimal places; 15 are
9274 * given. These values are much more accurate than the ones given in the spec,
9275 * which typically don't exceed 4 decimal places. This allows testing of the
9276 * libpng code to its theoretical accuracy of 4 decimal places. (If pngvalid
9277 * used the published errors the 'slack' permitted would have to be +/-.5E-4 or
9278 * more.)
9279 *
9280 * The png_modifier code assumes that encodings[0] is sRGB and treats it
9281 * specially: do not change the first entry in this list!
9282 */
9283static PNG_CONST color_encoding test_encodings[] =
9284{
9285/* sRGB: must be first in this list! */
9286/*gamma:*/ { 1/2.2,
9287/*red: */ { 0.412390799265959, 0.212639005871510, 0.019330818715592 },
9288/*green:*/ { 0.357584339383878, 0.715168678767756, 0.119194779794626 },
9289/*blue: */ { 0.180480788401834, 0.072192315360734, 0.950532152249660} },
9290/* Kodak ProPhoto (wide gamut) */
9291/*gamma:*/ { 1/1.6 /*approximate: uses 1.8 power law compared to sRGB 2.4*/,
9292/*red: */ { 0.797760489672303, 0.288071128229293, 0.000000000000000 },
9293/*green:*/ { 0.135185837175740, 0.711843217810102, 0.000000000000000 },
9294/*blue: */ { 0.031349349581525, 0.000085653960605, 0.825104602510460} },
9295/* Adobe RGB (1998) */
9296/*gamma:*/ { 1/(2+51./256),
9297/*red: */ { 0.576669042910131, 0.297344975250536, 0.027031361386412 },
9298/*green:*/ { 0.185558237906546, 0.627363566255466, 0.070688852535827 },
9299/*blue: */ { 0.188228646234995, 0.075291458493998, 0.991337536837639} },
9300/* Adobe Wide Gamut RGB */
9301/*gamma:*/ { 1/(2+51./256),
9302/*red: */ { 0.716500716779386, 0.258728243040113, 0.000000000000000 },
9303/*green:*/ { 0.101020574397477, 0.724682314948566, 0.051211818965388 },
9304/*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} },
9305};
9306
9307/* signal handler
9308 *
9309 * This attempts to trap signals and escape without crashing. It needs a
9310 * context pointer so that it can throw an exception (call longjmp) to recover
9311 * from the condition; this is handled by making the png_modifier used by 'main'
9312 * into a global variable.
9313 */
9314static png_modifier pm;
9315
9316static void signal_handler(int signum)
9317{
9318
9319 size_t pos = 0;
9320 char msg[64];
9321
9322 pos = safecat(msg, sizeof msg, pos, "caught signal: ");
9323
9324 switch (signum)
9325 {
9326 case SIGABRT:
9327 pos = safecat(msg, sizeof msg, pos, "abort");
9328 break;
9329
9330 case SIGFPE:
9331 pos = safecat(msg, sizeof msg, pos, "floating point exception");
9332 break;
9333
9334 case SIGILL:
9335 pos = safecat(msg, sizeof msg, pos, "illegal instruction");
9336 break;
9337
9338 case SIGINT:
9339 pos = safecat(msg, sizeof msg, pos, "interrupt");
9340 break;
9341
9342 case SIGSEGV:
9343 pos = safecat(msg, sizeof msg, pos, "invalid memory access");
9344 break;
9345
9346 case SIGTERM:
9347 pos = safecat(msg, sizeof msg, pos, "termination request");
9348 break;
9349
9350 default:
9351 pos = safecat(msg, sizeof msg, pos, "unknown ");
9352 pos = safecatn(msg, sizeof msg, pos, signum);
9353 break;
9354 }
9355
9356 store_log(&pm.this, NULL/*png_structp*/, msg, 1/*error*/);
9357
9358 /* And finally throw an exception so we can keep going, unless this is
9359 * SIGTERM in which case stop now.
9360 */
9361 if (signum != SIGTERM)
9362 {
9363 struct exception_context *the_exception_context =
9364 &pm.this.exception_context;
9365
9366 Throw &pm.this;
9367 }
9368
9369 else
9370 exit(1);
9371}
9372
9373/* main program */
9374int main(int argc, PNG_CONST char **argv)
9375{
9376 volatile int summary = 1; /* Print the error summary at the end */
9377 volatile int memstats = 0; /* Print memory statistics at the end */
9378
9379 /* Create the given output file on success: */
9380 PNG_CONST char *volatile touch = NULL;
9381
9382 /* This is an array of standard gamma values (believe it or not I've seen
9383 * every one of these mentioned somewhere.)
9384 *
9385 * In the following list the most useful values are first!
9386 */
9387 static double
9388 gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9};
9389
9390 /* This records the command and arguments: */
9391 size_t cp = 0;
9392 char command[1024];
9393
9394 anon_context(&pm.this);
9395
9396 /* Add appropriate signal handlers, just the ANSI specified ones: */
9397 signal(SIGABRT, signal_handler);
9398 signal(SIGFPE, signal_handler);
9399 signal(SIGILL, signal_handler);
9400 signal(SIGINT, signal_handler);
9401 signal(SIGSEGV, signal_handler);
9402 signal(SIGTERM, signal_handler);
9403
9404#ifdef HAVE_FEENABLEEXCEPT
9405 /* Only required to enable FP exceptions on platforms where they start off
9406 * disabled; this is not necessary but if it is not done pngvalid will likely
9407 * end up ignoring FP conditions that other platforms fault.
9408 */
9409 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
9410#endif
9411
9412 modifier_init(&pm);
9413
9414 /* Preallocate the image buffer, because we know how big it needs to be,
9415 * note that, for testing purposes, it is deliberately mis-aligned by tag
9416 * bytes either side. All rows have an additional five bytes of padding for
9417 * overwrite checking.
9418 */
9419 store_ensure_image(&pm.this, NULL, 2, TRANSFORM_ROWMAX, TRANSFORM_HEIGHTMAX);
9420
9421 /* Don't give argv[0], it's normally some horrible libtool string: */
9422 cp = safecat(command, sizeof command, cp, "pngvalid");
9423
9424 /* Default to error on warning: */
9425 pm.this.treat_warnings_as_errors = 1;
9426
9427 /* Store the test gammas */
9428 pm.gammas = gammas;
9429 pm.ngammas = (sizeof gammas) / (sizeof gammas[0]);
9430 pm.ngamma_tests = 0; /* default to off */
9431
9432 /* And the test encodings */
9433 pm.encodings = test_encodings;
9434 pm.nencodings = (sizeof test_encodings) / (sizeof test_encodings[0]);
9435
9436 pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */
9437 /* The following allows results to pass if they correspond to anything in the
9438 * transformed range [input-.5,input+.5]; this is is required because of the
9439 * way libpng treates the 16_TO_8 flag when building the gamma tables.
9440 *
9441 * TODO: review this
9442 */
9443 pm.use_input_precision_16to8 = 1U;
9444
9445 /* Some default values (set the behavior for 'make check' here).
9446 * These values simply control the maximum error permitted in the gamma
9447 * transformations. The practial limits for human perception are described
9448 * below (the setting for maxpc16), however for 8 bit encodings it isn't
9449 * possible to meet the accepted capabilities of human vision - i.e. 8 bit
9450 * images can never be good enough, regardless of encoding.
9451 */
9452 pm.maxout8 = .1; /* Arithmetic error in *encoded* value */
9453 pm.maxabs8 = .00005; /* 1/20000 */
9454 pm.maxcalc8 = .004; /* +/-1 in 8 bits for compose errors */
9455 pm.maxpc8 = .499; /* I.e., .499% fractional error */
9456 pm.maxout16 = .499; /* Error in *encoded* value */
9457 pm.maxabs16 = .00005;/* 1/20000 */
9458 pm.maxcalc16 =.000015;/* +/-1 in 16 bits for compose errors */
9459
9460 /* NOTE: this is a reasonable perceptual limit. We assume that humans can
9461 * perceive light level differences of 1% over a 100:1 range, so we need to
9462 * maintain 1 in 10000 accuracy (in linear light space), which is what the
9463 * following guarantees. It also allows significantly higher errors at
9464 * higher 16 bit values, which is important for performance. The actual
9465 * maximum 16 bit error is about +/-1.9 in the fixed point implementation but
9466 * this is only allowed for values >38149 by the following:
9467 */
9468 pm.maxpc16 = .005; /* I.e., 1/200% - 1/20000 */
9469
9470 /* Now parse the command line options. */
9471 while (--argc >= 1)
9472 {
9473 int catmore = 0; /* Set if the argument has an argument. */
9474
9475 /* Record each argument for posterity: */
9476 cp = safecat(command, sizeof command, cp, " ");
9477 cp = safecat(command, sizeof command, cp, *++argv);
9478
9479 if (strcmp(*argv, "-v") == 0)
9480 pm.this.verbose = 1;
9481
9482 else if (strcmp(*argv, "-l") == 0)
9483 pm.log = 1;
9484
9485 else if (strcmp(*argv, "-q") == 0)
9486 summary = pm.this.verbose = pm.log = 0;
9487
9488 else if (strcmp(*argv, "-w") == 0)
9489 pm.this.treat_warnings_as_errors = 0;
9490
9491 else if (strcmp(*argv, "--speed") == 0)
9492 pm.this.speed = 1, pm.ngamma_tests = pm.ngammas, pm.test_standard = 0,
9493 summary = 0;
9494
9495 else if (strcmp(*argv, "--memory") == 0)
9496 memstats = 1;
9497
9498 else if (strcmp(*argv, "--size") == 0)
9499 pm.test_size = 1;
9500
9501 else if (strcmp(*argv, "--nosize") == 0)
9502 pm.test_size = 0;
9503
9504 else if (strcmp(*argv, "--standard") == 0)
9505 pm.test_standard = 1;
9506
9507 else if (strcmp(*argv, "--nostandard") == 0)
9508 pm.test_standard = 0;
9509
9510 else if (strcmp(*argv, "--transform") == 0)
9511 pm.test_transform = 1;
9512
9513 else if (strcmp(*argv, "--notransform") == 0)
9514 pm.test_transform = 0;
9515
9516#ifdef PNG_READ_TRANSFORMS_SUPPORTED
9517 else if (strncmp(*argv, "--transform-disable=",
9518 sizeof "--transform-disable") == 0)
9519 {
9520 pm.test_transform = 1;
9521 transform_disable(*argv + sizeof "--transform-disable");
9522 }
9523
9524 else if (strncmp(*argv, "--transform-enable=",
9525 sizeof "--transform-enable") == 0)
9526 {
9527 pm.test_transform = 1;
9528 transform_enable(*argv + sizeof "--transform-enable");
9529 }
9530#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
9531
9532 else if (strcmp(*argv, "--gamma") == 0)
9533 {
9534 /* Just do two gamma tests here (2.2 and linear) for speed: */
9535 pm.ngamma_tests = 2U;
9536 pm.test_gamma_threshold = 1;
9537 pm.test_gamma_transform = 1;
9538 pm.test_gamma_sbit = 1;
9539 pm.test_gamma_scale16 = 1;
9540 pm.test_gamma_background = 1;
9541 pm.test_gamma_alpha_mode = 1;
9542 }
9543
9544 else if (strcmp(*argv, "--nogamma") == 0)
9545 pm.ngamma_tests = 0;
9546
9547 else if (strcmp(*argv, "--gamma-threshold") == 0)
9548 pm.ngamma_tests = 2U, pm.test_gamma_threshold = 1;
9549
9550 else if (strcmp(*argv, "--nogamma-threshold") == 0)
9551 pm.test_gamma_threshold = 0;
9552
9553 else if (strcmp(*argv, "--gamma-transform") == 0)
9554 pm.ngamma_tests = 2U, pm.test_gamma_transform = 1;
9555
9556 else if (strcmp(*argv, "--nogamma-transform") == 0)
9557 pm.test_gamma_transform = 0;
9558
9559 else if (strcmp(*argv, "--gamma-sbit") == 0)
9560 pm.ngamma_tests = 2U, pm.test_gamma_sbit = 1;
9561
9562 else if (strcmp(*argv, "--nogamma-sbit") == 0)
9563 pm.test_gamma_sbit = 0;
9564
9565 else if (strcmp(*argv, "--gamma-16-to-8") == 0)
9566 pm.ngamma_tests = 2U, pm.test_gamma_scale16 = 1;
9567
9568 else if (strcmp(*argv, "--nogamma-16-to-8") == 0)
9569 pm.test_gamma_scale16 = 0;
9570
9571 else if (strcmp(*argv, "--gamma-background") == 0)
9572 pm.ngamma_tests = 2U, pm.test_gamma_background = 1;
9573
9574 else if (strcmp(*argv, "--nogamma-background") == 0)
9575 pm.test_gamma_background = 0;
9576
9577 else if (strcmp(*argv, "--gamma-alpha-mode") == 0)
9578 pm.ngamma_tests = 2U, pm.test_gamma_alpha_mode = 1;
9579
9580 else if (strcmp(*argv, "--nogamma-alpha-mode") == 0)
9581 pm.test_gamma_alpha_mode = 0;
9582
9583 else if (strcmp(*argv, "--expand16") == 0)
9584 pm.test_gamma_expand16 = 1;
9585
9586 else if (strcmp(*argv, "--noexpand16") == 0)
9587 pm.test_gamma_expand16 = 0;
9588
9589 else if (strcmp(*argv, "--more-gammas") == 0)
9590 pm.ngamma_tests = 3U;
9591
9592 else if (strcmp(*argv, "--all-gammas") == 0)
9593 pm.ngamma_tests = pm.ngammas;
9594
9595 else if (strcmp(*argv, "--progressive-read") == 0)
9596 pm.this.progressive = 1;
9597
9598 else if (strcmp(*argv, "--use-update-info") == 0)
9599 ++pm.use_update_info; /* Can call multiple times */
9600
9601 else if (strcmp(*argv, "--interlace") == 0)
9602 pm.interlace_type = PNG_INTERLACE_ADAM7;
9603
9604 else if (strcmp(*argv, "--use-input-precision") == 0)
9605 pm.use_input_precision = 1;
9606
9607 else if (strcmp(*argv, "--calculations-use-input-precision") == 0)
9608 pm.calculations_use_input_precision = 1;
9609
9610 else if (strcmp(*argv, "--assume-16-bit-calculations") == 0)
9611 pm.assume_16_bit_calculations = 1;
9612
9613 else if (strcmp(*argv, "--calculations-follow-bit-depth") == 0)
9614 pm.calculations_use_input_precision =
9615 pm.assume_16_bit_calculations = 0;
9616
9617 else if (strcmp(*argv, "--exhaustive") == 0)
9618 pm.test_exhaustive = 1;
9619
9620 else if (argc > 1 && strcmp(*argv, "--sbitlow") == 0)
9621 --argc, pm.sbitlow = (png_byte)atoi(*++argv), catmore = 1;
9622
9623 else if (argc > 1 && strcmp(*argv, "--touch") == 0)
9624 --argc, touch = *++argv, catmore = 1;
9625
9626 else if (argc > 1 && strncmp(*argv, "--max", 5) == 0)
9627 {
9628 --argc;
9629
9630 if (strcmp(5+*argv, "abs8") == 0)
9631 pm.maxabs8 = atof(*++argv);
9632
9633 else if (strcmp(5+*argv, "abs16") == 0)
9634 pm.maxabs16 = atof(*++argv);
9635
9636 else if (strcmp(5+*argv, "calc8") == 0)
9637 pm.maxcalc8 = atof(*++argv);
9638
9639 else if (strcmp(5+*argv, "calc16") == 0)
9640 pm.maxcalc16 = atof(*++argv);
9641
9642 else if (strcmp(5+*argv, "out8") == 0)
9643 pm.maxout8 = atof(*++argv);
9644
9645 else if (strcmp(5+*argv, "out16") == 0)
9646 pm.maxout16 = atof(*++argv);
9647
9648 else if (strcmp(5+*argv, "pc8") == 0)
9649 pm.maxpc8 = atof(*++argv);
9650
9651 else if (strcmp(5+*argv, "pc16") == 0)
9652 pm.maxpc16 = atof(*++argv);
9653
9654 else
9655 {
9656 fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv);
9657 exit(1);
9658 }
9659
9660 catmore = 1;
9661 }
9662
9663 else if (strcmp(*argv, "--log8") == 0)
9664 --argc, pm.log8 = atof(*++argv), catmore = 1;
9665
9666 else if (strcmp(*argv, "--log16") == 0)
9667 --argc, pm.log16 = atof(*++argv), catmore = 1;
9668
9669 else
9670 {
9671 fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv);
9672 exit(1);
9673 }
9674
9675 if (catmore) /* consumed an extra *argv */
9676 {
9677 cp = safecat(command, sizeof command, cp, " ");
9678 cp = safecat(command, sizeof command, cp, *argv);
9679 }
9680 }
9681
9682 /* If pngvalid is run with no arguments default to a reasonable set of the
9683 * tests.
9684 */
9685 if (pm.test_standard == 0 && pm.test_size == 0 && pm.test_transform == 0 &&
9686 pm.ngamma_tests == 0)
9687 {
9688 /* Make this do all the tests done in the test shell scripts with the same
9689 * parameters, where possible. The limitation is that all the progressive
9690 * read and interlace stuff has to be done in separate runs, so only the
9691 * basic 'standard' and 'size' tests are done.
9692 */
9693 pm.test_standard = 1;
9694 pm.test_size = 1;
9695 pm.test_transform = 1;
9696 pm.ngamma_tests = 2U;
9697 }
9698
9699 if (pm.ngamma_tests > 0 &&
9700 pm.test_gamma_threshold == 0 && pm.test_gamma_transform == 0 &&
9701 pm.test_gamma_sbit == 0 && pm.test_gamma_scale16 == 0 &&
9702 pm.test_gamma_background == 0 && pm.test_gamma_alpha_mode == 0)
9703 {
9704 pm.test_gamma_threshold = 1;
9705 pm.test_gamma_transform = 1;
9706 pm.test_gamma_sbit = 1;
9707 pm.test_gamma_scale16 = 1;
9708 pm.test_gamma_background = 1;
9709 pm.test_gamma_alpha_mode = 1;
9710 }
9711
9712 else if (pm.ngamma_tests == 0)
9713 {
9714 /* Nothing to test so turn everything off: */
9715 pm.test_gamma_threshold = 0;
9716 pm.test_gamma_transform = 0;
9717 pm.test_gamma_sbit = 0;
9718 pm.test_gamma_scale16 = 0;
9719 pm.test_gamma_background = 0;
9720 pm.test_gamma_alpha_mode = 0;
9721 }
9722
9723 Try
9724 {
9725 /* Make useful base images */
9726 make_transform_images(&pm.this);
9727
9728 /* Perform the standard and gamma tests. */
9729 if (pm.test_standard)
9730 {
9731 perform_interlace_macro_validation();
9732 perform_formatting_test(&pm.this);
9733 perform_standard_test(&pm);
9734 perform_error_test(&pm);
9735 }
9736
9737 /* Various oddly sized images: */
9738 if (pm.test_size)
9739 {
9740 make_size_images(&pm.this);
9741 perform_size_test(&pm);
9742 }
9743
9744#ifdef PNG_READ_TRANSFORMS_SUPPORTED
9745 /* Combinatorial transforms: */
9746 if (pm.test_transform)
9747 perform_transform_test(&pm);
9748#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
9749
9750#ifdef PNG_READ_GAMMA_SUPPORTED
9751 if (pm.ngamma_tests > 0)
9752 perform_gamma_test(&pm, summary);
9753#endif
9754 }
9755
9756 Catch_anonymous
9757 {
9758 fprintf(stderr, "pngvalid: test aborted (probably failed in cleanup)\n");
9759 if (!pm.this.verbose)
9760 {
9761 if (pm.this.error[0] != 0)
9762 fprintf(stderr, "pngvalid: first error: %s\n", pm.this.error);
9763
9764 fprintf(stderr, "pngvalid: run with -v to see what happened\n");
9765 }
9766 exit(1);
9767 }
9768
9769 if (summary)
9770 {
9771 printf("%s: %s (%s point arithmetic)\n",
9772 (pm.this.nerrors || (pm.this.treat_warnings_as_errors &&
9773 pm.this.nwarnings)) ? "FAIL" : "PASS",
9774 command,
9775#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500
9776 "floating"
9777#else
9778 "fixed"
9779#endif
9780 );
9781 }
9782
9783 if (memstats)
9784 {
9785 printf("Allocated memory statistics (in bytes):\n"
9786 "\tread %lu maximum single, %lu peak, %lu total\n"
9787 "\twrite %lu maximum single, %lu peak, %lu total\n",
9788 (unsigned long)pm.this.read_memory_pool.max_max,
9789 (unsigned long)pm.this.read_memory_pool.max_limit,
9790 (unsigned long)pm.this.read_memory_pool.max_total,
9791 (unsigned long)pm.this.write_memory_pool.max_max,
9792 (unsigned long)pm.this.write_memory_pool.max_limit,
9793 (unsigned long)pm.this.write_memory_pool.max_total);
9794 }
9795
9796 /* Do this here to provoke memory corruption errors in memory not directly
9797 * allocated by libpng - not a complete test, but better than nothing.
9798 */
9799 store_delete(&pm.this);
9800
9801 /* Error exit if there are any errors, and maybe if there are any
9802 * warnings.
9803 */
9804 if (pm.this.nerrors || (pm.this.treat_warnings_as_errors &&
9805 pm.this.nwarnings))
9806 {
9807 if (!pm.this.verbose)
9808 fprintf(stderr, "pngvalid: %s\n", pm.this.error);
9809
9810 fprintf(stderr, "pngvalid: %d errors, %d warnings\n", pm.this.nerrors,
9811 pm.this.nwarnings);
9812
9813 exit(1);
9814 }
9815
9816 /* Success case. */
9817 if (touch != NULL)
9818 {
9819 FILE *fsuccess = fopen(touch, "wt");
9820
9821 if (fsuccess != NULL)
9822 {
9823 int error = 0;
9824 fprintf(fsuccess, "PNG validation succeeded\n");
9825 fflush(fsuccess);
9826 error = ferror(fsuccess);
9827
9828 if (fclose(fsuccess) || error)
9829 {
9830 fprintf(stderr, "%s: write failed\n", touch);
9831 exit(1);
9832 }
9833 }
9834 }
9835
9836 return 0;
9837}
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/README b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/README
new file mode 100644
index 0000000..86583cc
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/README
@@ -0,0 +1,10 @@
1This demonstrates the use of PNG_USER_CONFIG, pngusr.h and pngusr.dfa
2
3The makefile builds a minimal read-only decoder with embedded libpng
4and zlib.
5
6Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC
7on the make command line.
8
9If you prefer to use the shared libraries, go to contrib/pngminus
10and build the png2pnm application there.
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/makefile b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/makefile
new file mode 100644
index 0000000..9692e0a
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/makefile
@@ -0,0 +1,150 @@
1# Makefile for PngMinus (pngm2pnm)
2# Linux / Unix
3
4#CC=cc
5CC=gcc
6LD=$(CC)
7
8# If awk fails try
9# make AWK=nawk
10
11# If cpp fails try
12# make CPP=/lib/cpp
13
14RM=rm -f
15COPY=cp
16
17CFLAGS=-DPNG_USER_CONFIG -DNO_GZCOMPRESS -DNO_GZIP -I. -O1
18
19C=.c
20O=.o
21L=.a
22E=
23
24# Where to find the source code:
25PNGSRC =../../..
26ZLIBSRC=$(PNGSRC)/../zlib
27PROGSRC=$(PNGSRC)/contrib/pngminus
28
29# Zlib (minimal inflate requirements - crc32 is used by libpng)
30# zutil can be eliminated if you provide your own zcalloc and zcfree
31ZSRCS = adler32$(C) crc32$(C) \
32 inffast$(C) inflate$(C) inftrees$(C) \
33 zutil$(C)
34
35# Standard headers
36ZH = zlib.h crc32.h inffast.h inffixed.h \
37 inflate.h inftrees.h zutil.h
38
39# Machine generated headers
40ZCONF = zconf.h
41
42# Headers callers use
43ZINC = zlib.h $(ZCONF)
44
45# Headers the Zlib source uses
46ZHDRS = $(ZH) $(ZCONF)
47
48ZOBJS = adler32$(O) crc32$(O) \
49 inffast$(O) inflate$(O) inftrees$(O) \
50 zutil$(O)
51
52# libpng
53PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \
54 pngread$(C) pngrio$(C) pngrtran$(C) pngrutil$(C) \
55 pngset$(C) pngtrans$(C)
56
57# Standard headers
58PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h
59
60# Machine generated headers
61PNGCONF=pnglibconf.h
62
63# Headers callers use
64PNGINC= png.h pngconf.h pngusr.h $(PNGCONF)
65
66# Headers the PNG library uses
67PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h
68
69PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \
70 pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) \
71 pngset$(O) pngtrans$(O)
72
73PROGSRCS= pngm2pnm$(C)
74PROGHDRS=
75PROGDOCS=
76PROGOBJS= pngm2pnm$(O)
77
78OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS)
79
80# implicit make rules -------------------------------------------------------
81
82# note: dependencies do not work on implicit rule lines
83.c$(O):
84 $(CC) -c $(CFLAGS) $<
85
86# dependencies
87
88all: pngm2pnm$(E)
89
90pngm2pnm$(E): $(OBJS)
91 $(LD) -o pngm2pnm$(E) $(OBJS)
92
93# The DFA_XTRA setting turns all libpng options off then
94# turns on those required for this minimal build.
95# The CPP_FLAGS setting causes pngusr.h to be included in
96# both the build of pnglibconf.h and, subsequently, when
97# building libpng itself.
98$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\
99 $(PNGSRC)/scripts/pnglibconf.dfa \
100 $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa
101 $(RM) pnglibconf.h pnglibconf.dfn
102 $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\
103 srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\
104 DFA_XTRA="pngusr.dfa" $@
105
106clean:
107 $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\
108 srcdir=$(PNGSRC) clean
109 $(RM) pngm2pnm$(O)
110 $(RM) pngm2pnm$(E)
111 $(RM) $(OBJS)
112
113# distclean also removes the copied source and headers
114distclean: clean
115 $(RM) -r scripts # historical reasons
116 $(RM) $(PNGSRCS) $(PNGH)
117 $(RM) $(ZSRCS) $(ZH) $(ZCONF)
118 $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS)
119
120# Header file dependencies:
121$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC)
122$(PNGOBJS): $(PNGHDRS) $(ZINC)
123$(ZOBJS): $(ZHDRS)
124
125# Gather the source code from the respective directories
126$(PNGSRCS) $(PNGH): $(PNGSRC)/$@
127 $(RM) $@
128 $(COPY) $(PNGSRC)/$@ $@
129
130# No dependency on the ZLIBSRC target so that it only needs
131# to be specified once.
132$(ZSRCS) $(ZH):
133 $(RM) $@
134 $(COPY) $(ZLIBSRC)/$@ $@
135
136# The unconfigured zconf.h varies in name according to the
137# zlib release
138$(ZCONF):
139 $(RM) $@
140 @for f in zconf.h.in zconf.in.h zconf.h; do\
141 test -r $(ZLIBSRC)/$$f &&\
142 echo $(COPY) $(ZLIBSRC)/$$f $@ &&\
143 $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\
144 done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1
145
146pngm2pnm.c: $(PROGSRC)/png2pnm.c
147 $(RM) $@
148 $(COPY) $(PROGSRC)/png2pnm.c $@
149
150# End of makefile for pngm2pnm
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/pngusr.dfa b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/pngusr.dfa
new file mode 100644
index 0000000..8a66d64
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/pngusr.dfa
@@ -0,0 +1,39 @@
1# pngminim/decoder/pngusr.dfa
2#
3# Copyright (c) 2010-2011 Glenn Randers-Pehrson
4#
5# This code is released under the libpng license.
6# For conditions of distribution and use, see the disclaimer
7# and license in png.h
8
9# First all the build options off:
10
11everything = off
12
13# All that is required is some read code. This example switches
14# on the sequential read code (see ../preader for a progressive
15# read example).
16
17option SEQUENTIAL_READ on
18
19# You must choose fixed or floating point arithmetic:
20# option FLOATING_POINT on
21
22option FIXED_POINT on
23
24# You must chose the internal fixed point implementation or to
25# use the system floating point. The latter is considerably
26# smaller (by about 1kbyte on an x86 system):
27# option FLOATING_ARITHMETIC on
28
29option FLOATING_ARITHMETIC off
30
31# Your program will probably need other options. The example
32# program here, pngm2pnm, requires the following. Take a look
33# at pnglibconf.h to find out the full set of what has to be
34# enabled to make the following work.
35
36option SETJMP on
37option STDIO on
38option READ_EXPAND on
39option READ_STRIP_16_TO_8 on
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/pngusr.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/pngusr.h
new file mode 100644
index 0000000..2991c17
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/decoder/pngusr.h
@@ -0,0 +1,24 @@
1/* minrdpngconf.h: headers to make a minimal png-read-only library
2 *
3 * Copyright (c) 2007, 2010-2011 Glenn Randers-Pehrson
4 *
5 * This code is released under the libpng license.
6 * For conditions of distribution and use, see the disclaimer
7 * and license in png.h
8 *
9 * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson
10 */
11
12#ifndef MINRDPNGCONF_H
13#define MINRDPNGCONF_H
14
15/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */
16
17/* List options to turn off features of the build that do not
18 * affect the API (so are not recorded in pnglibconf.h)
19 */
20
21#define PNG_NO_WARNINGS
22#define PNG_ALIGN_TYPE PNG_ALIGN_NONE
23
24#endif /* MINRDPNGCONF_H */
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/README b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/README
new file mode 100644
index 0000000..f8a8b6d
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/README
@@ -0,0 +1,10 @@
1This demonstrates the use of PNG_USER_CONFIG and pngusr.h
2
3The makefile builds a minimal write-only decoder with embedded libpng
4and zlib.
5
6Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC
7on the make command line.
8
9If you prefer to use the shared libraries, go to contrib/pngminus
10and build the pnm2png application there.
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/makefile b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/makefile
new file mode 100644
index 0000000..7374a6c
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/makefile
@@ -0,0 +1,149 @@
1# Makefile for PngMinus (pnm2pngm)
2# Linux / Unix
3
4#CC=cc
5CC=gcc
6LD=$(CC)
7
8# If awk fails try
9# make AWK=nawk
10
11# If cpp fails try
12# make CPP=/lib/cpp
13
14RM=rm -f
15COPY=cp
16
17CFLAGS=-DPNG_USER_CONFIG -DNO_GZIP -I. -O1
18
19C=.c
20O=.o
21L=.a
22E=
23
24# Where to find the source code:
25PNGSRC =../../..
26ZLIBSRC=$(PNGSRC)/../zlib
27PROGSRC=$(PNGSRC)/contrib/pngminus
28
29# Zlib
30ZSRCS = adler32$(C) compress$(C) crc32$(C) deflate$(C) \
31 trees$(C) zutil$(C)
32
33# Standard headers
34#ZH = zlib.h crc32.h deflate.h trees.h zutil.h
35ZH = zlib.h crc32.h deflate.h trees.h zutil.h
36
37# Machine generated headers
38ZCONF = zconf.h
39
40# Headers callers use
41ZINC = zlib.h $(ZCONF)
42
43# Headers the Zlib source uses
44ZHDRS = $(ZH) $(ZCONF)
45
46# compress is not required; it is needed to link the zlib
47# code because deflate defines an unused API function deflateBound
48# which itself calls compressBound from compress.
49ZOBJS = adler32$(O) compress$(O) crc32$(O) deflate$(O) \
50 trees$(O) zutil$(O)
51
52# libpng
53PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \
54 pngset$(C) pngtrans$(C) pngwio$(C) pngwrite$(C) \
55 pngwtran$(C) pngwutil$(C)
56
57# Standard headers
58PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h
59
60# Machine generated headers
61PNGCONF=pnglibconf.h
62
63# Headers callers use
64PNGINC= png.h pngconf.h pngusr.h $(PNGCONF)
65
66# Headers the PNG library uses
67PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h
68
69PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \
70 pngset$(O) pngtrans$(O) pngwio$(O) pngwrite$(O) \
71 pngwtran$(O) pngwutil$(O)
72
73PROGSRCS= pnm2pngm$(C)
74PROGHDRS=
75PROGDOCS=
76PROGOBJS= pnm2pngm$(O)
77
78OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS)
79
80# implicit make rules -------------------------------------------------------
81
82.c$(O):
83 $(CC) -c $(CFLAGS) $<
84
85# dependencies
86
87all: pnm2pngm$(E)
88
89pnm2pngm$(E): $(OBJS)
90 $(LD) -o pnm2pngm$(E) $(OBJS)
91
92# The DFA_XTRA setting turns all libpng options off then
93# turns on those required for this minimal build.
94# The CPP_FLAGS setting causes pngusr.h to be included in
95# both the build of pnglibconf.h and, subsequently, when
96# building libpng itself.
97$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\
98 $(PNGSRC)/scripts/pnglibconf.dfa \
99 $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa
100 $(RM) pnglibconf.h pnglibconf.dfn
101 $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\
102 srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\
103 DFA_XTRA="pngusr.dfa" $@
104
105clean:
106 $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\
107 srcdir=$(PNGSRC) clean
108 $(RM) pnm2pngm$(O)
109 $(RM) pnm2pngm$(E)
110 $(RM) $(OBJS)
111
112# distclean also removes the copied source and headers
113distclean: clean
114 $(RM) -r scripts # historical reasons
115 $(RM) $(PNGSRCS) $(PNGH)
116 $(RM) $(ZSRCS) $(ZH) $(ZCONF)
117 $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS)
118
119# Header file dependencies:
120$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC)
121$(PNGOBJS): $(PNGHDRS) $(ZINC)
122$(ZOBJS): $(ZHDRS)
123
124# Gather the source code from the respective directories
125$(PNGSRCS) $(PNGH): $(PNGSRC)/$@
126 $(RM) $@
127 $(COPY) $(PNGSRC)/$@ $@
128
129# No dependency on the ZLIBSRC target so that it only needs
130# to be specified once.
131$(ZSRCS) $(ZH):
132 $(RM) $@
133 $(COPY) $(ZLIBSRC)/$@ $@
134
135# The unconfigured zconf.h varies in name according to the
136# zlib release
137$(ZCONF):
138 $(RM) $@
139 @for f in zconf.h.in zconf.in.h zconf.h; do\
140 test -r $(ZLIBSRC)/$$f &&\
141 echo $(COPY) $(ZLIBSRC)/$$f $@ &&\
142 $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\
143 done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1
144
145pnm2pngm.c: $(PROGSRC)/pnm2png.c
146 $(RM) $@
147 $(COPY) $(PROGSRC)/pnm2png.c $@
148
149# End of makefile for pnm2pngm
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/pngusr.dfa b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/pngusr.dfa
new file mode 100644
index 0000000..448f821
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/pngusr.dfa
@@ -0,0 +1,35 @@
1# pngminim/encoder/pngusr.dfa
2#
3# Copyright (c) 2010-2011 Glenn Randers-Pehrson
4#
5# This code is released under the libpng license.
6# For conditions of distribution and use, see the disclaimer
7# and license in png.h
8
9# First all the build options off:
10
11everything = off
12
13# Switch on the write code - this makes a minimalist encoder
14
15option WRITE on
16
17# You must choose fixed or floating point arithmetic:
18# option FLOATING_POINT on
19
20option FIXED_POINT on
21
22# You must chose the internal fixed point implementation or to
23# use the system floating point. The latter is considerably
24# smaller (by about 1kbyte on an x86 system):
25# option FLOATING_ARITHMETIC on
26
27option FLOATING_ARITHMETIC off
28
29# Your program will probably need other options. The example
30# program here, pnm2pngm, requires the following. Take a look
31# at pnglibconf.h to find out the full set of what has to be
32# enabled to make the following work.
33
34option SETJMP on
35option STDIO on
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/pngusr.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/pngusr.h
new file mode 100644
index 0000000..bafbf13
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/encoder/pngusr.h
@@ -0,0 +1,24 @@
1/* minwrpngconf.h: headers to make a minimal png-write-only library
2 *
3 * Copyright (c) 2007, 2010-2011 Glenn Randers-Pehrson
4 *
5 * This code is released under the libpng license.
6 * For conditions of distribution and use, see the disclaimer
7 * and license in png.h
8 *
9 * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson
10 */
11
12#ifndef MINWRPNGCONF_H
13#define MINWRPNGCONF_H
14
15/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */
16
17/* List options to turn off features of the build that do not
18 * affect the API (so are not recorded in pnglibconf.h)
19 */
20
21#define PNG_NO_WARNINGS
22#define PNG_ALIGN_TYPE PNG_ALIGN_NONE
23
24#endif /* MINWRPNGCONF_H */
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/README b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/README
new file mode 100644
index 0000000..e40024e
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/README
@@ -0,0 +1,15 @@
1This demonstrates the use of PNG_USER_CONFIG and pngusr.h
2
3The makefile builds a minimal read-only progressive decoder with
4embedded libpng, zlib and your system's X library.
5
6Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC
7on the make command line.
8
9Edit makefile if required, to find your X library and include files,
10then
11
12 make ZLIBSRC=directory
13
14If you prefer to use the shared libraries, go to contrib/gregbook
15and build the rpng2-x application there.
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/makefile b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/makefile
new file mode 100644
index 0000000..a367661
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/makefile
@@ -0,0 +1,165 @@
1# Makefile for PngMinus (rpng2)
2# Linux / Unix
3
4#CC=cc
5CC=gcc
6LD=$(CC)
7
8# If awk fails try
9# make AWK=nawk
10
11# If cpp fails try
12# make CPP=/lib/cpp
13
14RM=rm -f
15COPY=cp
16
17#XINC = -I/usr/include # old-style, stock X distributions
18#XLIB = -L/usr/lib/X11 -lX11 # (including SGI IRIX)
19
20#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows)
21#XLIB = -L/usr/openwin/lib -lX11
22
23XINC = -I/usr/X11R6/include # new X distributions (X.org, etc.)
24XLIB = -L/usr/X11R6/lib -lX11
25#XLIB = -L/usr/X11R6/lib64 -lX11 # e.g., Red Hat on AMD64
26
27#XINC = -I/usr/local/include # FreeBSD
28#XLIB = -L/usr/local/lib -lX11
29
30#LIBS = $(XLIB)
31LIBS = $(XLIB) -lm #platforms that need libm
32
33CFLAGS=-DPNG_USER_CONFIG -DNO_GZCOMPRESS -DNO_GZIP -I. $(XINC) -O1
34
35C=.c
36O=.o
37L=.a
38E=
39
40# Where to find the source code:
41PNGSRC =../../..
42ZLIBSRC=$(PNGSRC)/../zlib
43PROGSRC=$(PNGSRC)/contrib/gregbook
44
45# Zlib (minimal inflate requirements - crc32 is used by libpng)
46# zutil can be eliminated if you provide your own zcalloc and zcfree
47ZSRCS = adler32$(C) crc32$(C) \
48 inffast$(C) inflate$(C) inftrees$(C) \
49 zutil$(C)
50
51# Standard headers
52ZH = zlib.h crc32.h inffast.h inffixed.h \
53 inflate.h inftrees.h zutil.h
54
55# Machine generated headers
56ZCONF = zconf.h
57
58# Headers callers use
59ZINC = zlib.h $(ZCONF)
60
61# Headers the Zlib source uses
62ZHDRS = $(ZH) $(ZCONF)
63
64ZOBJS = adler32$(O) crc32$(O) \
65 inffast$(O) inflate$(O) inftrees$(O) \
66 zutil$(O)
67
68# libpng
69PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \
70 pngpread$(C) pngread$(C) pngrio$(C) pngrtran$(C) pngrutil$(C) \
71 pngset$(C) pngtrans$(C)
72
73# Standard headers
74PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h
75
76# Machine generated headers
77PNGCONF=pnglibconf.h
78
79# Headers callers use
80PNGINC= png.h pngconf.h pngusr.h $(PNGCONF)
81
82# Headers the PNG library uses
83PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h
84
85PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \
86 pngpread$(O) pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) \
87 pngset$(O) pngtrans$(O)
88
89PROGSRCS= rpng2-x$(C) readpng2$(C)
90PROGHDRS= readpng2.h
91PROGDOCS= COPYING LICENSE
92PROGOBJS= rpng2-x$(O) readpng2$(O)
93
94OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS)
95
96# implicit make rules -------------------------------------------------------
97
98.c$(O):
99 $(CC) -c $(CFLAGS) $<
100
101# dependencies
102
103all: $(PROGDOCS) rpng2-x$(E)
104
105rpng2-x$(E): $(OBJS)
106 $(LD) -o rpng2-x$(E) $(OBJS) $(LIBS)
107
108# The DFA_XTRA setting turns all libpng options off then
109# turns on those required for this minimal build.
110# The CPP_FLAGS setting causes pngusr.h to be included in
111# both the build of pnglibconf.h and, subsequently, when
112# building libpng itself.
113$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\
114 $(PNGSRC)/scripts/pnglibconf.dfa \
115 $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa
116 $(RM) pnglibconf.h pnglibconf.dfn
117 $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\
118 srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\
119 DFA_XTRA="pngusr.dfa" $@
120
121clean:
122 $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\
123 srcdir=$(PNGSRC) clean
124 $(RM) rpng2-x$(O)
125 $(RM) rpng2-x$(E)
126 $(RM) $(OBJS)
127
128# distclean also removes the copied source and headers
129distclean: clean
130 $(RM) -r scripts # historical reasons
131 $(RM) $(PNGSRCS) $(PNGH)
132 $(RM) $(ZSRCS) $(ZH) $(ZCONF)
133 $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS)
134
135# Header file dependencies:
136$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC)
137$(PNGOBJS): $(PNGHDRS) $(ZINC)
138$(ZOBJS): $(ZHDRS)
139
140# Gather the source code from the respective directories
141$(PNGSRCS) $(PNGH): $(PNGSRC)/$@
142 $(RM) $@
143 $(COPY) $(PNGSRC)/$@ $@
144
145# No dependency on the ZLIBSRC target so that it only needs
146# to be specified once.
147$(ZSRCS) $(ZH):
148 $(RM) $@
149 $(COPY) $(ZLIBSRC)/$@ $@
150
151# The unconfigured zconf.h varies in name according to the
152# zlib release
153$(ZCONF):
154 $(RM) $@
155 @for f in zconf.h.in zconf.in.h zconf.h; do\
156 test -r $(ZLIBSRC)/$$f &&\
157 echo $(COPY) $(ZLIBSRC)/$$f $@ &&\
158 $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\
159 done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1
160
161$(PROGSRCS) $(PROGHDRS) $(PROGDOCS): $(PROGSRC)/$@
162 $(RM) $@
163 $(COPY) $(PROGSRC)/$@ $@
164
165# End of makefile for rpng2-x
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/pngusr.dfa b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/pngusr.dfa
new file mode 100644
index 0000000..0c991d3
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/pngusr.dfa
@@ -0,0 +1,40 @@
1# pngminim/preader/pngusr.dfa
2#
3# Copyright (c) 2010-2011 Glenn Randers-Pehrson
4#
5# This code is released under the libpng license.
6# For conditions of distribution and use, see the disclaimer
7# and license in png.h
8
9# First all the build options off:
10
11everything = off
12
13# Just switch on the progressive read code
14
15option PROGRESSIVE_READ on
16
17# You may choose fixed or floating point APIs:
18# option FLOATING_POINT on
19
20option FIXED_POINT on
21
22# You must chose the internal fixed point implementation or to
23# use the system floating point. The latter is considerably
24# smaller (by about 1kbyte on an x86 system):
25
26option FLOATING_ARITHMETIC on
27# option FLOATING_ARITHMETIC off
28
29# Your program will probably need other options. The example
30# program here, rpng2-x, requires the following. Take a look
31# at pnglibconf.h to find out the full set of what has to be
32# enabled to make the following work.
33
34option SETJMP on
35option STDIO on
36option READ_bKGD on
37option READ_GAMMA on
38option READ_EXPAND on
39option READ_STRIP_16_TO_8 on
40option READ_GRAY_TO_RGB on
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/pngusr.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/pngusr.h
new file mode 100644
index 0000000..7db806f
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminim/preader/pngusr.h
@@ -0,0 +1,24 @@
1/* minrdpngconf.h: headers to make a minimal png-read-only library
2 *
3 * Copyright (c) 2009, 2010-2011 Glenn Randers-Pehrson
4 *
5 * This code is released under the libpng license.
6 * For conditions of distribution and use, see the disclaimer
7 * and license in png.h
8 *
9 * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson
10 */
11
12#ifndef MINPRDPNGCONF_H
13#define MINPRDPNGCONF_H
14
15/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */
16
17/* List options to turn off features of the build that do not
18 * affect the API (so are not recorded in pnglibconf.h)
19 */
20
21#define PNG_NO_WARNINGS
22#define PNG_ALIGN_TYPE PNG_ALIGN_NONE
23
24#endif /* MINPRDPNGCONF_H */
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/README b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/README
new file mode 100644
index 0000000..b0516ec
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/README
@@ -0,0 +1,153 @@
1PngMinus
2--------
3(copyright Willem van Schaik, 1999)
4
5
6License
7-------
8
9Permission to use, copy, modify, and distribute this software and
10its documentation for any purpose and without fee is hereby granted,
11provided that the above copyright notice appear in all copies and
12that both that copyright notice and this permission notice appear in
13supporting documentation. This software is provided "as is" without
14express or implied warranty.
15
16
17Some history
18------------
19Soon after the creation of PNG in 1995, the need was felt for a set of
20pnmtopng / pngtopnm utilities. Independantly Alexander Lehmann and I
21(Willem van Schaik) started such a project. Luckily we discovered this
22and merged the two together into pnmtopng.tar.gz, which is available
23from a/o ftp://ftp.simplesystems.org/pub/libpng/png/.
24
25These two utilities have many, many options and make use of most of the
26features of PNG, like gamma, alpha, sbit, text-chunks, etc. This makes
27the utilities quite complex and by now not anymore very maintainable.
28When we wrote these programs, libpng was still in an early stage.
29Therefore, lots of the functionality that we put in our software can now
30be done using transform-functions in libpng.
31
32Finally, to compile these programs, you need to have installed and
33compiled three libraries: libpng, zlib and netpbm. Especially the latter
34makes the whole setup a bit bulky. But that's unavoidable given the many
35features of pnmtopng.
36
37
38What now
39--------
40At this moment libpng is in a very stable state and can do much of the
41work done in pnmtopng. Also, pnmtopng needs to be upgraded to the new
42interface of libpng. Hence, it is time for a rewrite from the ground up
43of pnmtopng and pngtopnm. This will happen in the near future (stay
44tuned). The new package will get a different name to distinguish it from
45the old one: PngPlus.
46
47To experiment a bit with the new interface of libpng, I started off with
48a small prototype that contains only the basic functionality. It doesn't
49have any of the options to read or write special chunks and it will do
50no gamma correction. But this makes it also a simple program that is
51quite easy to understand and can serve well as a template for other
52software developments. (By now there are of course a couple of programs,
53like Greg Roelofs' rpng/wpng, that can be used just as good.)
54
55
56Can and can not
57---------------
58As this is the small brother of the future PngPlus, I called this fellow
59PngMinus. Because I started this development in good-old Turbo-C, I
60avoided the use the netpbm library, which requires DOS extenders. Again,
61another reason to call it PngMinus (minus netpbm :-). So, part of the
62program are some elementary routines to read / write pgm- and ppm-files.
63It does not read b&w pbm-files.
64
65The downside of this approach is that you can not use them on images
66that require blocks of memory bigger than 64k (the DOS version). For
67larger images you will get an out-of-memory error.
68
69As said before, PngMinus doesn't correct for gamma. When reading
70png-files you can do this just as well by piping the output of png2pnm
71to pnmgamma, one of the standard PbmPlus tools. This same scenario will
72most probably also be followed in the full-blown future PngPlus, with
73the addition of course of the possibility to create gamma-chunks when
74writing png-files.
75
76On the other hand it supports alpha-channels. When reading a png-image
77you can write the alpha-channel into a pgm-file. And when creating an
78RGB+A png-image, you just combine a ppm-file with a corresponding
79pgm-file containing the alpha-channel. When reading, transparency chunks
80are converted into an alpha-channel and from there on treated the same
81way.
82
83Finally you can opt for writing ascii or binary pgm- and ppm-files. When
84the bit-depth is 16, the format will always be ascii.
85
86
87Using it
88--------
89To distinguish them from pnmtopng and PngPlus, the utilities are named
90png2pnm and pnm2png (2 instead of to). The input- and output-files can
91be given as parameters or through redirection. Therefore the programs
92can be part of a pipe.
93
94To list the options type "png2pnm -h" or "pnm2png -h".
95
96
97Just like Scandinavian furniture
98--------------------------------
99You have to put it together yourself. I did test the software under
100MS-DOS with Turbo-C 3.0 and under RedHat Linux 4.2 with gcc. In both
101cases I used libpng-1.0.4 and zlib-1.1.3. Later versions should be OK,
102however some older libpng versions have a bug in pngmem.c when using
103Turbo-C 3.0 (see below).
104
105You can build it using one of the two makefiles (make -f makefile.###)
106or use the batch/script files pngminus.bat / pngminus.sh. This assumes
107that you have built the libraries in ../libpng and ../zlib. Using Linux,
108make sure that you have built libpng with makefile.std and not
109makefile.linux (also called .lnx in earlier versions of libpng). The
110latter creates a .so shared-library, while the PngMinus makefile assumes
111a normal .a static library.
112
113If you create a ../pngsuite directory and then store the basn####.png
114files from PngSuite (http://www.schaik.com/pngsuite/) in there, you can
115test in one go the proper functioning of PngMinus, see png2pnm.bat and
116pnm2png.bat (or the .sh versions).
117
118
119Warranty
120-------
121Please, remember that this was just a small experiment to learn a few
122things. It will have many unforeseen features <vbg>. Who said bugs? Use
123it when you are in need for something simple or when you want to start
124developing your own stuff.
125
126
127The Turbo bug
128-------------
129** pngmem.old
130 hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
131 hptr += 16L;
132** pngmem.c
133 hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
134 hptr = hptr + 16L;
135**
136
137** pngmem.old
138 png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
139 hptr += (png_uint_32)65536L;
140** pngmem.c
141 png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
142 hptr = hptr + 65536L;
143**
144
145
146The end
147-------
148Willem van Schaik
149mailto:willem@schaik.com
150http://www.schaik.com/png/
151-------
152Oct 1999
153
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makefile.std b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makefile.std
new file mode 100644
index 0000000..a121032
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makefile.std
@@ -0,0 +1,65 @@
1# Makefile for PngMinus (png2pnm and pnm2png)
2# Linux / Unix
3
4#CC=cc
5CC=gcc
6LD=$(CC)
7
8RM=rm -f
9
10#PNGPATH = /usr/local
11#PNGINC = -I$(PNGPATH)/include/libpng15
12#PNGLIB = -L$(PNGPATH)/lib -lpng15
13#PNGLIBS = $(PNGPATH)/lib/libpng15.a
14PNGINC = -I../..
15PNGLIB = -L../.. -lpng
16PNGLIBS = ../../libpng.a
17
18#ZPATH = /usr/local
19#ZINC = -I$(ZPATH)/include
20#ZLIB = -L$(ZPATH)/lib -lz
21#ZLIBS = $(ZPATH)/lib/libz.a
22ZINC = -I../../../zlib
23ZLIB = -L../../../zlib -lz
24ZLIBS = ../../../zlib/libz.a
25
26CFLAGS=$(PNGINC) $(ZINC)
27LDLIBS=$(PNGLIB) $(ZLIB)
28LDLIBSS=$(PNGLIBS) $(ZLIBS)
29C=.c
30O=.o
31L=.a
32E=
33
34# dependencies
35
36#all: png2pnm$(E) pnm2png$(E)
37all: png2pnm$(E) pnm2png$(E) png2pnm-static$(E) pnm2png-static$(E)
38
39png2pnm$(O): png2pnm$(C)
40 $(CC) -c $(CFLAGS) png2pnm$(C)
41
42png2pnm$(E): png2pnm$(O)
43 $(LD) $(LDFLAGS) -o png2pnm$(E) png2pnm$(O) $(LDLIBS) -lm
44
45png2pnm-static$(E): png2pnm$(O)
46 $(LD) $(LDFLAGS) -o png2pnm-static$(E) png2pnm$(O) $(LDLIBSS) -lm
47
48pnm2png$(O): pnm2png$(C)
49 $(CC) -c $(CFLAGS) pnm2png$(C)
50
51pnm2png$(E): pnm2png$(O)
52 $(LD) $(LDFLAGS) -o pnm2png$(E) pnm2png$(O) $(LDLIBS) -lm
53
54pnm2png-static$(E): pnm2png$(O)
55 $(LD) $(LDFLAGS) -o pnm2png-static$(E) pnm2png$(O) $(LDLIBSS) -lm
56
57clean:
58 $(RM) png2pnm$(O)
59 $(RM) pnm2png$(O)
60 $(RM) png2pnm$(E)
61 $(RM) pnm2png$(E)
62 $(RM) png2pnm-static$(E)
63 $(RM) pnm2png-static$(E)
64
65# End of makefile for png2pnm / pnm2png
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makefile.tc3 b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makefile.tc3
new file mode 100644
index 0000000..01062cc
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makefile.tc3
@@ -0,0 +1,38 @@
1# Makefile for PngMinus (png2pnm and pnm2png)
2# TurboC++ 3.0
3
4CC=tcc -Ic:\tc3\inc
5LD=tcc -Lc:\tc3\lib
6LB=tlib
7RM=del
8CP=copy
9MODEL=l
10CCFLAGS=-O -m$(MODEL) -I..\libpng -I..\zlib
11LDFLAGS=-m$(MODEL) -L..\libpng -L..\zlib
12C=.c
13O=.obj
14L=.lib
15E=.exe
16
17# dependencies
18
19all: png2pnm$(E) pnm2png$(E)
20
21png2pnm$(O): png2pnm$(C)
22 $(CC) -c $(CCFLAGS) png2pnm$(C)
23
24png2pnm$(E): png2pnm$(O)
25 $(LD) $(LDFLAGS) png2pnm$(O) libpng$(L) zlib$(L)
26
27pnm2png$(O): pnm2png$(C)
28 $(CC) -c $(CCFLAGS) pnm2png$(C)
29
30pnm2png$(E): pnm2png$(O)
31 $(LD) $(LDFLAGS) pnm2png$(O) libpng$(L) zlib$(L)
32
33clean:
34 $(RM) *$(O)
35 $(RM) *$(E)
36
37# End of makefile for png2pnm / pnm2png
38
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makevms.com b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makevms.com
new file mode 100644
index 0000000..96c3147
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/makevms.com
@@ -0,0 +1,92 @@
1$!------------------------------------------------------------------------------
2$! make Contrib programs of libpng under OpenVMS
3$!
4$!
5$! Look for the compiler used
6$!
7$ zlibsrc = "[---.zlib]"
8$ ccopt="/include=(''zlibsrc',[--])"
9$ if f$getsyi("HW_MODEL").ge.1024
10$ then
11$ ccopt = "/prefix=all"+ccopt
12$ comp = "__decc__=1"
13$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
14$ else
15$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
16$ then
17$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
18$ if f$search("SYS$SYSTEM:VAXC.EXE").eqs.""
19$ then
20$ comp = "__gcc__=1"
21$ CC :== GCC
22$ else
23$ comp = "__vaxc__=1"
24$ endif
25$ else
26$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include:
27$ ccopt = "/decc/prefix=all"+ccopt
28$ comp = "__decc__=1"
29$ endif
30$ endif
31$ open/write lopt lib.opt
32$ write lopt "[--]libpng.olb/lib"
33$ write lopt "''zlibsrc'libz.olb/lib"
34$ close lopt
35$ open/write xopt x11.opt
36$ write xopt "sys$library:decw$xlibshr.exe/share"
37$ close xopt
38$ write sys$output "Compiling PNG contrib programs ..."
39$ write sys$output "Building pnm2png..."
40$ CALL MAKE pnm2png.OBJ "cc ''CCOPT' pnm2png" -
41 pnm2png.c
42$ call make pnm2png.exe -
43 "LINK pnm2png,lib.opt/opt" -
44 pnm2png.obj
45$ write sys$output "Building png2pnm..."
46$ CALL MAKE png2pnm.OBJ "cc ''CCOPT' png2pnm" -
47 png2pnm.c
48$ call make png2pnm.exe -
49 "LINK png2pnm,lib.opt/opt" -
50 png2pnm.obj
51$ exit
52$!
53$!
54$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES
55$ V = 'F$Verify(0)
56$! P1 = What we are trying to make
57$! P2 = Command to make it
58$! P3 - P8 What it depends on
59$
60$ If F$Search(P1) .Eqs. "" Then Goto Makeit
61$ Time = F$CvTime(F$File(P1,"RDT"))
62$arg=3
63$Loop:
64$ Argument = P'arg
65$ If Argument .Eqs. "" Then Goto Exit
66$ El=0
67$Loop2:
68$ File = F$Element(El," ",Argument)
69$ If File .Eqs. " " Then Goto Endl
70$ AFile = ""
71$Loop3:
72$ OFile = AFile
73$ AFile = F$Search(File)
74$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
75$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
76$ Goto Loop3
77$NextEL:
78$ El = El + 1
79$ Goto Loop2
80$EndL:
81$ arg=arg+1
82$ If arg .Le. 8 Then Goto Loop
83$ Goto Exit
84$
85$Makeit:
86$ VV=F$VERIFY(0)
87$ write sys$output P2
88$ 'P2
89$ VV='F$Verify(VV)
90$Exit:
91$ If V Then Set Verify
92$ENDSUBROUTINE
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.bat b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.bat
new file mode 100644
index 0000000..85abe3c
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.bat
@@ -0,0 +1,41 @@
1REM -- grayscale
2png2pnm.exe -noraw ..\pngsuite\basn0g01.png basn0g01.pgm
3png2pnm.exe -noraw ..\pngsuite\basn0g02.png basn0g02.pgm
4png2pnm.exe -noraw ..\pngsuite\basn0g04.png basn0g04.pgm
5png2pnm.exe -noraw ..\pngsuite\basn0g08.png basn0g08.pgm
6png2pnm.exe -noraw ..\pngsuite\basn0g16.png basn0g16.pgm
7REM -- full-color
8png2pnm.exe -noraw ..\pngsuite\basn2c08.png basn2c08.ppm
9png2pnm.exe -noraw ..\pngsuite\basn2c16.png basn2c16.ppm
10REM -- palletted
11png2pnm.exe -noraw ..\pngsuite\basn3p01.png basn3p01.ppm
12png2pnm.exe -noraw ..\pngsuite\basn3p02.png basn3p02.ppm
13png2pnm.exe -noraw ..\pngsuite\basn3p04.png basn3p04.ppm
14png2pnm.exe -noraw ..\pngsuite\basn3p08.png basn3p08.ppm
15REM -- gray with alpha-channel
16png2pnm.exe -noraw ..\pngsuite\basn4a08.png basn4a08.pgm
17png2pnm.exe -noraw ..\pngsuite\basn4a16.png basn4a16.pgm
18REM -- color with alpha-channel
19png2pnm.exe -noraw -alpha basn6a08.pgm ..\pngsuite\basn6a08.png basn6a08.ppm
20png2pnm.exe -noraw -alpha basn6a16.pgm ..\pngsuite\basn6a16.png basn6a16.ppm
21REM -- grayscale
22png2pnm.exe -raw ..\pngsuite\basn0g01.png rawn0g01.pgm
23png2pnm.exe -raw ..\pngsuite\basn0g02.png rawn0g02.pgm
24png2pnm.exe -raw ..\pngsuite\basn0g04.png rawn0g04.pgm
25png2pnm.exe -raw ..\pngsuite\basn0g08.png rawn0g08.pgm
26png2pnm.exe -raw ..\pngsuite\basn0g16.png rawn0g16.pgm
27REM -- full-color
28png2pnm.exe -raw ..\pngsuite\basn2c08.png rawn2c08.ppm
29png2pnm.exe -raw ..\pngsuite\basn2c16.png rawn2c16.ppm
30REM -- palletted
31png2pnm.exe -raw ..\pngsuite\basn3p01.png rawn3p01.ppm
32png2pnm.exe -raw ..\pngsuite\basn3p02.png rawn3p02.ppm
33png2pnm.exe -raw ..\pngsuite\basn3p04.png rawn3p04.ppm
34png2pnm.exe -raw ..\pngsuite\basn3p08.png rawn3p08.ppm
35REM -- gray with alpha-channel
36png2pnm.exe -raw ..\pngsuite\basn4a08.png rawn4a08.pgm
37png2pnm.exe -raw ..\pngsuite\basn4a16.png rawn4a16.pgm
38REM -- color with alpha-channel
39png2pnm.exe -noraw -alpha rawn6a08.pgm ..\pngsuite\basn6a08.png rawn6a08.ppm
40png2pnm.exe -noraw -alpha rawn6a16.pgm ..\pngsuite\basn6a16.png rawn6a16.ppm
41
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.c
new file mode 100644
index 0000000..ef28d90
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.c
@@ -0,0 +1,430 @@
1/*
2 * png2pnm.c --- conversion from PNG-file to PGM/PPM-file
3 * copyright (C) 1999 by Willem van Schaik <willem@schaik.com>
4 *
5 * version 1.0 - 1999.10.15 - First version.
6 *
7 * Permission to use, copy, modify, and distribute this software and
8 * its documentation for any purpose and without fee is hereby granted,
9 * provided that the above copyright notice appear in all copies and
10 * that both that copyright notice and this permission notice appear in
11 * supporting documentation. This software is provided "as is" without
12 * express or implied warranty.
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17#ifdef __TURBOC__
18#include <mem.h>
19#include <fcntl.h>
20#endif
21
22#ifndef BOOL
23#define BOOL unsigned char
24#endif
25#ifndef TRUE
26#define TRUE (BOOL) 1
27#endif
28#ifndef FALSE
29#define FALSE (BOOL) 0
30#endif
31
32#ifdef __TURBOC__
33#define STDIN 0
34#define STDOUT 1
35#define STDERR 2
36#endif
37
38/* to make png2pnm verbose so we can find problems (needs to be before png.h) */
39#ifndef PNG_DEBUG
40#define PNG_DEBUG 0
41#endif
42
43#include "png.h"
44
45/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
46#ifndef png_jmpbuf
47# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
48#endif
49
50/* function prototypes */
51
52int main (int argc, char *argv[]);
53void usage ();
54BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, BOOL raw, BOOL alpha);
55
56/*
57 * main
58 */
59
60int main(int argc, char *argv[])
61{
62 FILE *fp_rd = stdin;
63 FILE *fp_wr = stdout;
64 FILE *fp_al = NULL;
65 BOOL raw = TRUE;
66 BOOL alpha = FALSE;
67 int argi;
68
69 for (argi = 1; argi < argc; argi++)
70 {
71 if (argv[argi][0] == '-')
72 {
73 switch (argv[argi][1])
74 {
75 case 'n':
76 raw = FALSE;
77 break;
78 case 'r':
79 raw = TRUE;
80 break;
81 case 'a':
82 alpha = TRUE;
83 argi++;
84 if ((fp_al = fopen (argv[argi], "wb")) == NULL)
85 {
86 fprintf (stderr, "PNM2PNG\n");
87 fprintf (stderr, "Error: can not create alpha-channel file %s\n", argv[argi]);
88 exit (1);
89 }
90 break;
91 case 'h':
92 case '?':
93 usage();
94 exit(0);
95 break;
96 default:
97 fprintf (stderr, "PNG2PNM\n");
98 fprintf (stderr, "Error: unknown option %s\n", argv[argi]);
99 usage();
100 exit(1);
101 break;
102 } /* end switch */
103 }
104 else if (fp_rd == stdin)
105 {
106 if ((fp_rd = fopen (argv[argi], "rb")) == NULL)
107 {
108 fprintf (stderr, "PNG2PNM\n");
109 fprintf (stderr, "Error: file %s does not exist\n", argv[argi]);
110 exit (1);
111 }
112 }
113 else if (fp_wr == stdout)
114 {
115 if ((fp_wr = fopen (argv[argi], "wb")) == NULL)
116 {
117 fprintf (stderr, "PNG2PNM\n");
118 fprintf (stderr, "Error: can not create file %s\n", argv[argi]);
119 exit (1);
120 }
121 }
122 else
123 {
124 fprintf (stderr, "PNG2PNM\n");
125 fprintf (stderr, "Error: too many parameters\n");
126 usage();
127 exit(1);
128 }
129 } /* end for */
130
131#ifdef __TURBOC__
132 /* set stdin/stdout if required to binary */
133 if (fp_rd == stdin)
134 {
135 setmode (STDIN, O_BINARY);
136 }
137 if ((raw) && (fp_wr == stdout))
138 {
139 setmode (STDOUT, O_BINARY);
140 }
141#endif
142
143 /* call the conversion program itself */
144 if (png2pnm (fp_rd, fp_wr, fp_al, raw, alpha) == FALSE)
145 {
146 fprintf (stderr, "PNG2PNM\n");
147 fprintf (stderr, "Error: unsuccessful conversion of PNG-image\n");
148 exit(1);
149 }
150
151 /* close input file */
152 fclose (fp_rd);
153 /* close output file */
154 fclose (fp_wr);
155 /* close alpha file */
156 if (alpha)
157 fclose (fp_al);
158
159 return 0;
160}
161
162/*
163 * usage
164 */
165
166void usage()
167{
168 fprintf (stderr, "PNG2PNM\n");
169 fprintf (stderr, " by Willem van Schaik, 1999\n");
170#ifdef __TURBOC__
171 fprintf (stderr, " for Turbo-C and Borland-C compilers\n");
172#else
173 fprintf (stderr, " for Linux (and Unix) compilers\n");
174#endif
175 fprintf (stderr, "Usage: png2pnm [options] <file>.png [<file>.pnm]\n");
176 fprintf (stderr, " or: ... | png2pnm [options]\n");
177 fprintf (stderr, "Options:\n");
178 fprintf (stderr, " -r[aw] write pnm-file in binary format (P4/P5/P6) (default)\n");
179 fprintf (stderr, " -n[oraw] write pnm-file in ascii format (P1/P2/P3)\n");
180 fprintf (stderr, " -a[lpha] <file>.pgm write PNG alpha channel as pgm-file\n");
181 fprintf (stderr, " -h | -? print this help-information\n");
182}
183
184/*
185 * png2pnm
186 */
187
188BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, BOOL raw, BOOL alpha)
189{
190 png_struct *png_ptr = NULL;
191 png_info *info_ptr = NULL;
192 png_byte buf[8];
193 png_byte *png_pixels = NULL;
194 png_byte **row_pointers = NULL;
195 png_byte *pix_ptr = NULL;
196 png_uint_32 row_bytes;
197
198 png_uint_32 width;
199 png_uint_32 height;
200 int bit_depth;
201 int channels;
202 int color_type;
203 int alpha_present;
204 int row, col;
205 int ret;
206 int i;
207 long dep_16;
208
209 /* read and check signature in PNG file */
210 ret = fread (buf, 1, 8, png_file);
211 if (ret != 8)
212 return FALSE;
213
214 ret = png_sig_cmp (buf, 0, 8);
215 if (ret)
216 return FALSE;
217
218 /* create png and info structures */
219
220 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
221 NULL, NULL, NULL);
222 if (!png_ptr)
223 return FALSE; /* out of memory */
224
225 info_ptr = png_create_info_struct (png_ptr);
226 if (!info_ptr)
227 {
228 png_destroy_read_struct (&png_ptr, NULL, NULL);
229 return FALSE; /* out of memory */
230 }
231
232 if (setjmp (png_jmpbuf(png_ptr)))
233 {
234 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
235 return FALSE;
236 }
237
238 /* set up the input control for C streams */
239 png_init_io (png_ptr, png_file);
240 png_set_sig_bytes (png_ptr, 8); /* we already read the 8 signature bytes */
241
242 /* read the file information */
243 png_read_info (png_ptr, info_ptr);
244
245 /* get size and bit-depth of the PNG-image */
246 png_get_IHDR (png_ptr, info_ptr,
247 &width, &height, &bit_depth, &color_type,
248 NULL, NULL, NULL);
249
250 /* set-up the transformations */
251
252 /* transform paletted images into full-color rgb */
253 if (color_type == PNG_COLOR_TYPE_PALETTE)
254 png_set_expand (png_ptr);
255 /* expand images to bit-depth 8 (only applicable for grayscale images) */
256 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
257 png_set_expand (png_ptr);
258 /* transform transparency maps into full alpha-channel */
259 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
260 png_set_expand (png_ptr);
261
262#ifdef NJET
263 /* downgrade 16-bit images to 8 bit */
264 if (bit_depth == 16)
265 png_set_strip_16 (png_ptr);
266 /* transform grayscale images into full-color */
267 if (color_type == PNG_COLOR_TYPE_GRAY ||
268 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
269 png_set_gray_to_rgb (png_ptr);
270 /* only if file has a file gamma, we do a correction */
271 if (png_get_gAMA (png_ptr, info_ptr, &file_gamma))
272 png_set_gamma (png_ptr, (double) 2.2, file_gamma);
273#endif
274
275 /* all transformations have been registered; now update info_ptr data,
276 * get rowbytes and channels, and allocate image memory */
277
278 png_read_update_info (png_ptr, info_ptr);
279
280 /* get the new color-type and bit-depth (after expansion/stripping) */
281 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
282 NULL, NULL, NULL);
283
284 /* check for 16-bit files */
285 if (bit_depth == 16)
286 {
287 raw = FALSE;
288#ifdef __TURBOC__
289 pnm_file->flags &= ~((unsigned) _F_BIN);
290#endif
291 }
292
293 /* calculate new number of channels and store alpha-presence */
294 if (color_type == PNG_COLOR_TYPE_GRAY)
295 channels = 1;
296 else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
297 channels = 2;
298 else if (color_type == PNG_COLOR_TYPE_RGB)
299 channels = 3;
300 else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
301 channels = 4;
302 else
303 channels = 0; /* should never happen */
304 alpha_present = (channels - 1) % 2;
305
306 /* check if alpha is expected to be present in file */
307 if (alpha && !alpha_present)
308 {
309 fprintf (stderr, "PNG2PNM\n");
310 fprintf (stderr, "Error: PNG-file doesn't contain alpha channel\n");
311 exit (1);
312 }
313
314 /* row_bytes is the width x number of channels x (bit-depth / 8) */
315 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
316
317 if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) {
318 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
319 return FALSE;
320 }
321
322 if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL)
323 {
324 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
325 free (png_pixels);
326 png_pixels = NULL;
327 return FALSE;
328 }
329
330 /* set the individual row_pointers to point at the correct offsets */
331 for (i = 0; i < (height); i++)
332 row_pointers[i] = png_pixels + i * row_bytes;
333
334 /* now we can go ahead and just read the whole image */
335 png_read_image (png_ptr, row_pointers);
336
337 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
338 png_read_end (png_ptr, info_ptr);
339
340 /* clean up after the read, and free any memory allocated - REQUIRED */
341 png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);
342
343 /* write header of PNM file */
344
345 if ((color_type == PNG_COLOR_TYPE_GRAY) ||
346 (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
347 {
348 fprintf (pnm_file, "%s\n", (raw) ? "P5" : "P2");
349 fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
350 fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
351 }
352 else if ((color_type == PNG_COLOR_TYPE_RGB) ||
353 (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
354 {
355 fprintf (pnm_file, "%s\n", (raw) ? "P6" : "P3");
356 fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
357 fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
358 }
359
360 /* write header of PGM file with alpha channel */
361
362 if ((alpha) &&
363 ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
364 (color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
365 {
366 fprintf (alpha_file, "%s\n", (raw) ? "P5" : "P2");
367 fprintf (alpha_file, "%d %d\n", (int) width, (int) height);
368 fprintf (alpha_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
369 }
370
371 /* write data to PNM file */
372 pix_ptr = png_pixels;
373
374 for (row = 0; row < height; row++)
375 {
376 for (col = 0; col < width; col++)
377 {
378 for (i = 0; i < (channels - alpha_present); i++)
379 {
380 if (raw)
381 fputc ((int) *pix_ptr++ , pnm_file);
382 else
383 if (bit_depth == 16){
384 dep_16 = (long) *pix_ptr++;
385 fprintf (pnm_file, "%ld ", (dep_16 << 8) + ((long) *pix_ptr++));
386 }
387 else
388 fprintf (pnm_file, "%ld ", (long) *pix_ptr++);
389 }
390 if (alpha_present)
391 {
392 if (!alpha)
393 {
394 pix_ptr++; /* alpha */
395 if (bit_depth == 16)
396 pix_ptr++;
397 }
398 else /* output alpha-channel as pgm file */
399 {
400 if (raw)
401 fputc ((int) *pix_ptr++ , alpha_file);
402 else
403 if (bit_depth == 16){
404 dep_16 = (long) *pix_ptr++;
405 fprintf (alpha_file, "%ld ", (dep_16 << 8) + (long) *pix_ptr++);
406 }
407 else
408 fprintf (alpha_file, "%ld ", (long) *pix_ptr++);
409 }
410 } /* if alpha_present */
411
412 if (!raw)
413 if (col % 4 == 3)
414 fprintf (pnm_file, "\n");
415 } /* end for col */
416
417 if (!raw)
418 if (col % 4 != 0)
419 fprintf (pnm_file, "\n");
420 } /* end for row */
421
422 if (row_pointers != (unsigned char**) NULL)
423 free (row_pointers);
424 if (png_pixels != (unsigned char*) NULL)
425 free (png_pixels);
426
427 return TRUE;
428
429} /* end of source */
430
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.sh b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.sh
new file mode 100755
index 0000000..ee39664
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/png2pnm.sh
@@ -0,0 +1,42 @@
1#!/bin/sh
2# -- grayscale
3./png2pnm -noraw ../pngsuite/basn0g01.png basn0g01.pgm
4./png2pnm -noraw ../pngsuite/basn0g02.png basn0g02.pgm
5./png2pnm -noraw ../pngsuite/basn0g04.png basn0g04.pgm
6./png2pnm -noraw ../pngsuite/basn0g08.png basn0g08.pgm
7./png2pnm -noraw ../pngsuite/basn0g16.png basn0g16.pgm
8# -- full-color
9./png2pnm -noraw ../pngsuite/basn2c08.png basn2c08.ppm
10./png2pnm -noraw ../pngsuite/basn2c16.png basn2c16.ppm
11# -- palletted
12./png2pnm -noraw ../pngsuite/basn3p01.png basn3p01.ppm
13./png2pnm -noraw ../pngsuite/basn3p02.png basn3p02.ppm
14./png2pnm -noraw ../pngsuite/basn3p04.png basn3p04.ppm
15./png2pnm -noraw ../pngsuite/basn3p08.png basn3p08.ppm
16# -- gray with alpha-channel
17./png2pnm -noraw ../pngsuite/basn4a08.png basn4a08.pgm
18./png2pnm -noraw ../pngsuite/basn4a16.png basn4a16.pgm
19# -- color with alpha-channel
20./png2pnm -noraw -alpha basn6a08.pgm ../pngsuite/basn6a08.png basn6a08.ppm
21./png2pnm -noraw -alpha basn6a16.pgm ../pngsuite/basn6a16.png basn6a16.ppm
22# -- grayscale
23./png2pnm -raw ../pngsuite/basn0g01.png rawn0g01.pgm
24./png2pnm -raw ../pngsuite/basn0g02.png rawn0g02.pgm
25./png2pnm -raw ../pngsuite/basn0g04.png rawn0g04.pgm
26./png2pnm -raw ../pngsuite/basn0g08.png rawn0g08.pgm
27./png2pnm -raw ../pngsuite/basn0g16.png rawn0g16.pgm
28# -- full-color
29./png2pnm -raw ../pngsuite/basn2c08.png rawn2c08.ppm
30./png2pnm -raw ../pngsuite/basn2c16.png rawn2c16.ppm
31# -- palletted
32./png2pnm -raw ../pngsuite/basn3p01.png rawn3p01.ppm
33./png2pnm -raw ../pngsuite/basn3p02.png rawn3p02.ppm
34./png2pnm -raw ../pngsuite/basn3p04.png rawn3p04.ppm
35./png2pnm -raw ../pngsuite/basn3p08.png rawn3p08.ppm
36# -- gray with alpha-channel
37./png2pnm -raw ../pngsuite/basn4a08.png rawn4a08.pgm
38./png2pnm -raw ../pngsuite/basn4a16.png rawn4a16.pgm
39# -- color with alpha-channel
40./png2pnm -noraw -alpha rawn6a08.pgm ../pngsuite/basn6a08.png rawn6a08.ppm
41./png2pnm -noraw -alpha rawn6a16.pgm ../pngsuite/basn6a16.png rawn6a16.ppm
42
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pngminus.bat b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pngminus.bat
new file mode 100644
index 0000000..5f8d2d4
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pngminus.bat
@@ -0,0 +1,4 @@
1make -f makefile.tc3
2call png2pnm.bat
3call pnm2png.bat
4
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pngminus.sh b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pngminus.sh
new file mode 100755
index 0000000..adcef55
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pngminus.sh
@@ -0,0 +1,5 @@
1#!/bin/sh
2make -f makefile.std
3sh png2pnm.sh
4sh pnm2png.sh
5
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.bat b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.bat
new file mode 100644
index 0000000..5b9977a
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.bat
@@ -0,0 +1,41 @@
1REM -- grayscale
2pnm2png.exe basn0g01.pgm basn0g01.png
3pnm2png.exe basn0g02.pgm basn0g02.png
4pnm2png.exe basn0g04.pgm basn0g04.png
5pnm2png.exe basn0g08.pgm basn0g08.png
6pnm2png.exe basn0g16.pgm basn0g16.png
7REM -- full-color
8pnm2png.exe basn2c08.ppm basn2c08.png
9pnm2png.exe basn2c16.ppm basn2c16.png
10REM -- palletted
11pnm2png.exe basn3p01.ppm basn3p01.png
12pnm2png.exe basn3p02.ppm basn3p02.png
13pnm2png.exe basn3p04.ppm basn3p04.png
14pnm2png.exe basn3p08.ppm basn3p08.png
15REM -- gray with alpha-channel
16pnm2png.exe -alpha basn6a08.pgm basn4a08.pgm basn4a08.png
17pnm2png.exe -alpha basn6a16.pgm basn4a16.pgm basn4a16.png
18REM -- color with alpha-channel
19pnm2png.exe -alpha basn6a08.pgm basn6a08.ppm basn6a08.png
20pnm2png.exe -alpha basn6a16.pgm basn6a16.ppm basn6a16.png
21REM -- grayscale
22pnm2png.exe rawn0g01.pgm rawn0g01.png
23pnm2png.exe rawn0g02.pgm rawn0g02.png
24pnm2png.exe rawn0g04.pgm rawn0g04.png
25pnm2png.exe rawn0g08.pgm rawn0g08.png
26pnm2png.exe rawn0g16.pgm rawn0g16.png
27REM -- full-color
28pnm2png.exe rawn2c08.ppm rawn2c08.png
29pnm2png.exe rawn2c16.ppm rawn2c16.png
30REM -- palletted
31pnm2png.exe rawn3p01.ppm rawn3p01.png
32pnm2png.exe rawn3p02.ppm rawn3p02.png
33pnm2png.exe rawn3p04.ppm rawn3p04.png
34pnm2png.exe rawn3p08.ppm rawn3p08.png
35REM -- gray with alpha-channel
36pnm2png.exe -alpha rawn6a08.pgm rawn4a08.pgm rawn4a08.png
37pnm2png.exe -alpha rawn6a16.pgm rawn4a16.pgm rawn4a16.png
38REM -- color with alpha-channel
39pnm2png.exe -alpha rawn6a08.pgm rawn6a08.ppm rawn6a08.png
40pnm2png.exe -alpha rawn6a16.pgm rawn6a16.ppm rawn6a16.png
41
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.c
new file mode 100644
index 0000000..2f321cc
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.c
@@ -0,0 +1,533 @@
1/*
2 * pnm2png.c --- conversion from PBM/PGM/PPM-file to PNG-file
3 * copyright (C) 1999 by Willem van Schaik <willem@schaik.com>
4 *
5 * version 1.0 - 1999.10.15 - First version.
6 *
7 * Permission to use, copy, modify, and distribute this software and
8 * its documentation for any purpose and without fee is hereby granted,
9 * provided that the above copyright notice appear in all copies and
10 * that both that copyright notice and this permission notice appear in
11 * supporting documentation. This software is provided "as is" without
12 * express or implied warranty.
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17#ifdef __TURBOC__
18#include <mem.h>
19#include <fcntl.h>
20#endif
21
22#ifndef BOOL
23#define BOOL unsigned char
24#endif
25#ifndef TRUE
26#define TRUE (BOOL) 1
27#endif
28#ifndef FALSE
29#define FALSE (BOOL) 0
30#endif
31
32#define STDIN 0
33#define STDOUT 1
34#define STDERR 2
35
36/* to make pnm2png verbose so we can find problems (needs to be before png.h) */
37#ifndef PNG_DEBUG
38#define PNG_DEBUG 0
39#endif
40
41#include "png.h"
42
43/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
44#ifndef png_jmpbuf
45# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
46#endif
47
48/* function prototypes */
49
50int main (int argc, char *argv[]);
51void usage ();
52BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha);
53void get_token(FILE *pnm_file, char *token);
54png_uint_32 get_data (FILE *pnm_file, int depth);
55png_uint_32 get_value (FILE *pnm_file, int depth);
56
57/*
58 * main
59 */
60
61int main(int argc, char *argv[])
62{
63 FILE *fp_rd = stdin;
64 FILE *fp_al = NULL;
65 FILE *fp_wr = stdout;
66 BOOL interlace = FALSE;
67 BOOL alpha = FALSE;
68 int argi;
69
70 for (argi = 1; argi < argc; argi++)
71 {
72 if (argv[argi][0] == '-')
73 {
74 switch (argv[argi][1])
75 {
76 case 'i':
77 interlace = TRUE;
78 break;
79 case 'a':
80 alpha = TRUE;
81 argi++;
82 if ((fp_al = fopen (argv[argi], "rb")) == NULL)
83 {
84 fprintf (stderr, "PNM2PNG\n");
85 fprintf (stderr, "Error: alpha-channel file %s does not exist\n",
86 argv[argi]);
87 exit (1);
88 }
89 break;
90 case 'h':
91 case '?':
92 usage();
93 exit(0);
94 break;
95 default:
96 fprintf (stderr, "PNM2PNG\n");
97 fprintf (stderr, "Error: unknown option %s\n", argv[argi]);
98 usage();
99 exit(1);
100 break;
101 } /* end switch */
102 }
103 else if (fp_rd == stdin)
104 {
105 if ((fp_rd = fopen (argv[argi], "rb")) == NULL)
106 {
107 fprintf (stderr, "PNM2PNG\n");
108 fprintf (stderr, "Error: file %s does not exist\n", argv[argi]);
109 exit (1);
110 }
111 }
112 else if (fp_wr == stdout)
113 {
114 if ((fp_wr = fopen (argv[argi], "wb")) == NULL)
115 {
116 fprintf (stderr, "PNM2PNG\n");
117 fprintf (stderr, "Error: can not create PNG-file %s\n", argv[argi]);
118 exit (1);
119 }
120 }
121 else
122 {
123 fprintf (stderr, "PNM2PNG\n");
124 fprintf (stderr, "Error: too many parameters\n");
125 usage();
126 exit (1);
127 }
128 } /* end for */
129
130#ifdef __TURBOC__
131 /* set stdin/stdout to binary, we're reading the PNM always! in binary format */
132 if (fp_rd == stdin)
133 {
134 setmode (STDIN, O_BINARY);
135 }
136 if (fp_wr == stdout)
137 {
138 setmode (STDOUT, O_BINARY);
139 }
140#endif
141
142 /* call the conversion program itself */
143 if (pnm2png (fp_rd, fp_wr, fp_al, interlace, alpha) == FALSE)
144 {
145 fprintf (stderr, "PNM2PNG\n");
146 fprintf (stderr, "Error: unsuccessful converting to PNG-image\n");
147 exit (1);
148 }
149
150 /* close input file */
151 fclose (fp_rd);
152 /* close output file */
153 fclose (fp_wr);
154 /* close alpha file */
155 if (alpha)
156 fclose (fp_al);
157
158 return 0;
159}
160
161/*
162 * usage
163 */
164
165void usage()
166{
167 fprintf (stderr, "PNM2PNG\n");
168 fprintf (stderr, " by Willem van Schaik, 1999\n");
169#ifdef __TURBOC__
170 fprintf (stderr, " for Turbo-C and Borland-C compilers\n");
171#else
172 fprintf (stderr, " for Linux (and Unix) compilers\n");
173#endif
174 fprintf (stderr, "Usage: pnm2png [options] <file>.<pnm> [<file>.png]\n");
175 fprintf (stderr, " or: ... | pnm2png [options]\n");
176 fprintf (stderr, "Options:\n");
177 fprintf (stderr, " -i[nterlace] write png-file with interlacing on\n");
178 fprintf (stderr, " -a[lpha] <file>.pgm read PNG alpha channel as pgm-file\n");
179 fprintf (stderr, " -h | -? print this help-information\n");
180}
181
182/*
183 * pnm2png
184 */
185
186BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha)
187{
188 png_struct *png_ptr = NULL;
189 png_info *info_ptr = NULL;
190 png_byte *png_pixels = NULL;
191 png_byte **row_pointers = NULL;
192 png_byte *pix_ptr = NULL;
193 png_uint_32 row_bytes;
194
195 char type_token[16];
196 char width_token[16];
197 char height_token[16];
198 char maxval_token[16];
199 int color_type;
200 png_uint_32 width, alpha_width;
201 png_uint_32 height, alpha_height;
202 png_uint_32 maxval;
203 int bit_depth = 0;
204 int channels;
205 int alpha_depth = 0;
206 int alpha_present;
207 int row, col;
208 BOOL raw, alpha_raw = FALSE;
209 png_uint_32 tmp16;
210 int i;
211
212 /* read header of PNM file */
213
214 get_token(pnm_file, type_token);
215 if (type_token[0] != 'P')
216 {
217 return FALSE;
218 }
219 else if ((type_token[1] == '1') || (type_token[1] == '4'))
220 {
221 raw = (type_token[1] == '4');
222 color_type = PNG_COLOR_TYPE_GRAY;
223 bit_depth = 1;
224 }
225 else if ((type_token[1] == '2') || (type_token[1] == '5'))
226 {
227 raw = (type_token[1] == '5');
228 color_type = PNG_COLOR_TYPE_GRAY;
229 get_token(pnm_file, width_token);
230 sscanf (width_token, "%lu", &width);
231 get_token(pnm_file, height_token);
232 sscanf (height_token, "%lu", &height);
233 get_token(pnm_file, maxval_token);
234 sscanf (maxval_token, "%lu", &maxval);
235 if (maxval <= 1)
236 bit_depth = 1;
237 else if (maxval <= 3)
238 bit_depth = 2;
239 else if (maxval <= 15)
240 bit_depth = 4;
241 else if (maxval <= 255)
242 bit_depth = 8;
243 else /* if (maxval <= 65535) */
244 bit_depth = 16;
245 }
246 else if ((type_token[1] == '3') || (type_token[1] == '6'))
247 {
248 raw = (type_token[1] == '6');
249 color_type = PNG_COLOR_TYPE_RGB;
250 get_token(pnm_file, width_token);
251 sscanf (width_token, "%lu", &width);
252 get_token(pnm_file, height_token);
253 sscanf (height_token, "%lu", &height);
254 get_token(pnm_file, maxval_token);
255 sscanf (maxval_token, "%lu", &maxval);
256 if (maxval <= 1)
257 bit_depth = 1;
258 else if (maxval <= 3)
259 bit_depth = 2;
260 else if (maxval <= 15)
261 bit_depth = 4;
262 else if (maxval <= 255)
263 bit_depth = 8;
264 else /* if (maxval <= 65535) */
265 bit_depth = 16;
266 }
267 else
268 {
269 return FALSE;
270 }
271
272 /* read header of PGM file with alpha channel */
273
274 if (alpha)
275 {
276 if (color_type == PNG_COLOR_TYPE_GRAY)
277 color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
278 if (color_type == PNG_COLOR_TYPE_RGB)
279 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
280
281 get_token(alpha_file, type_token);
282 if (type_token[0] != 'P')
283 {
284 return FALSE;
285 }
286 else if ((type_token[1] == '2') || (type_token[1] == '5'))
287 {
288 alpha_raw = (type_token[1] == '5');
289 get_token(alpha_file, width_token);
290 sscanf (width_token, "%lu", &alpha_width);
291 if (alpha_width != width)
292 return FALSE;
293 get_token(alpha_file, height_token);
294 sscanf (height_token, "%lu", &alpha_height);
295 if (alpha_height != height)
296 return FALSE;
297 get_token(alpha_file, maxval_token);
298 sscanf (maxval_token, "%lu", &maxval);
299 if (maxval <= 1)
300 alpha_depth = 1;
301 else if (maxval <= 3)
302 alpha_depth = 2;
303 else if (maxval <= 15)
304 alpha_depth = 4;
305 else if (maxval <= 255)
306 alpha_depth = 8;
307 else /* if (maxval <= 65535) */
308 alpha_depth = 16;
309 if (alpha_depth != bit_depth)
310 return FALSE;
311 }
312 else
313 {
314 return FALSE;
315 }
316 } /* end if alpha */
317
318 /* calculate the number of channels and store alpha-presence */
319 if (color_type == PNG_COLOR_TYPE_GRAY)
320 channels = 1;
321 else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
322 channels = 2;
323 else if (color_type == PNG_COLOR_TYPE_RGB)
324 channels = 3;
325 else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
326 channels = 4;
327 else
328 channels = 0; /* should not happen */
329
330 alpha_present = (channels - 1) % 2;
331
332 /* row_bytes is the width x number of channels x (bit-depth / 8) */
333 row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2);
334
335 if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL)
336 return FALSE;
337
338 /* read data from PNM file */
339 pix_ptr = png_pixels;
340
341 for (row = 0; row < height; row++)
342 {
343 for (col = 0; col < width; col++)
344 {
345 for (i = 0; i < (channels - alpha_present); i++)
346 {
347 if (raw)
348 *pix_ptr++ = get_data (pnm_file, bit_depth);
349 else
350 if (bit_depth <= 8)
351 *pix_ptr++ = get_value (pnm_file, bit_depth);
352 else
353 {
354 tmp16 = get_value (pnm_file, bit_depth);
355 *pix_ptr = (png_byte) ((tmp16 >> 8) & 0xFF);
356 pix_ptr++;
357 *pix_ptr = (png_byte) (tmp16 & 0xFF);
358 pix_ptr++;
359 }
360 }
361
362 if (alpha) /* read alpha-channel from pgm file */
363 {
364 if (alpha_raw)
365 *pix_ptr++ = get_data (alpha_file, alpha_depth);
366 else
367 if (alpha_depth <= 8)
368 *pix_ptr++ = get_value (alpha_file, bit_depth);
369 else
370 {
371 tmp16 = get_value (alpha_file, bit_depth);
372 *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF);
373 *pix_ptr++ = (png_byte) (tmp16 & 0xFF);
374 }
375 } /* if alpha */
376
377 } /* end for col */
378 } /* end for row */
379
380 /* prepare the standard PNG structures */
381 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
382 if (!png_ptr)
383 {
384 return FALSE;
385 }
386 info_ptr = png_create_info_struct (png_ptr);
387 if (!info_ptr)
388 {
389 png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
390 return FALSE;
391 }
392
393 /* setjmp() must be called in every function that calls a PNG-reading libpng function */
394 if (setjmp (png_jmpbuf(png_ptr)))
395 {
396 png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
397 return FALSE;
398 }
399
400 /* initialize the png structure */
401 png_init_io (png_ptr, png_file);
402
403 /* we're going to write more or less the same PNG as the input file */
404 png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type,
405 (!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7,
406 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
407
408 /* write the file header information */
409 png_write_info (png_ptr, info_ptr);
410
411 /* if needed we will allocate memory for an new array of row-pointers */
412 if (row_pointers == (unsigned char**) NULL)
413 {
414 if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL)
415 {
416 png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
417 return FALSE;
418 }
419 }
420
421 /* set the individual row_pointers to point at the correct offsets */
422 for (i = 0; i < (height); i++)
423 row_pointers[i] = png_pixels + i * row_bytes;
424
425 /* write out the entire image data in one call */
426 png_write_image (png_ptr, row_pointers);
427
428 /* write the additional chuncks to the PNG file (not really needed) */
429 png_write_end (png_ptr, info_ptr);
430
431 /* clean up after the write, and free any memory allocated */
432 png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
433
434 if (row_pointers != (unsigned char**) NULL)
435 free (row_pointers);
436 if (png_pixels != (unsigned char*) NULL)
437 free (png_pixels);
438
439 return TRUE;
440} /* end of pnm2png */
441
442/*
443 * get_token() - gets the first string after whitespace
444 */
445
446void get_token(FILE *pnm_file, char *token)
447{
448 int i = 0;
449
450 /* remove white-space */
451 do
452 {
453 token[i] = (unsigned char) fgetc (pnm_file);
454 }
455 while ((token[i] == '\n') || (token[i] == '\r') || (token[i] == ' '));
456
457 /* read string */
458 do
459 {
460 i++;
461 token[i] = (unsigned char) fgetc (pnm_file);
462 }
463 while ((token[i] != '\n') && (token[i] != '\r') && (token[i] != ' '));
464
465 token[i] = '\0';
466
467 return;
468}
469
470/*
471 * get_data() - takes first byte and converts into next pixel value,
472 * taking as much bits as defined by bit-depth and
473 * using the bit-depth to fill up a byte (0Ah -> AAh)
474 */
475
476png_uint_32 get_data (FILE *pnm_file, int depth)
477{
478 static int bits_left = 0;
479 static int old_value = 0;
480 static int mask = 0;
481 int i;
482 png_uint_32 ret_value;
483
484 if (mask == 0)
485 for (i = 0; i < depth; i++)
486 mask = (mask >> 1) | 0x80;
487
488 if (bits_left <= 0)
489 {
490 old_value = fgetc (pnm_file);
491 bits_left = 8;
492 }
493
494 ret_value = old_value & mask;
495 for (i = 1; i < (8 / depth); i++)
496 ret_value = ret_value || (ret_value >> depth);
497
498 old_value = (old_value << depth) & 0xFF;
499 bits_left -= depth;
500
501 return ret_value;
502}
503
504/*
505 * get_value() - takes first (numeric) string and converts into number,
506 * using the bit-depth to fill up a byte (0Ah -> AAh)
507 */
508
509png_uint_32 get_value (FILE *pnm_file, int depth)
510{
511 static png_uint_32 mask = 0;
512 png_byte token[16];
513 png_uint_32 ret_value;
514 int i = 0;
515
516 if (mask == 0)
517 for (i = 0; i < depth; i++)
518 mask = (mask << 1) | 0x01;
519
520 get_token (pnm_file, (char *) token);
521 sscanf ((const char *) token, "%lu", &ret_value);
522
523 ret_value &= mask;
524
525 if (depth < 8)
526 for (i = 0; i < (8 / depth); i++)
527 ret_value = (ret_value << depth) || ret_value;
528
529 return ret_value;
530}
531
532/* end of source */
533
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.sh b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.sh
new file mode 100755
index 0000000..975f047
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngminus/pnm2png.sh
@@ -0,0 +1,42 @@
1#!/bin/sh
2# -- grayscale
3./pnm2png basn0g01.pgm basn0g01.png
4./pnm2png basn0g02.pgm basn0g02.png
5./pnm2png basn0g04.pgm basn0g04.png
6./pnm2png basn0g08.pgm basn0g08.png
7./pnm2png basn0g16.pgm basn0g16.png
8# -- full-color
9./pnm2png basn2c08.ppm basn2c08.png
10./pnm2png basn2c16.ppm basn2c16.png
11# -- palletted
12./pnm2png basn3p01.ppm basn3p01.png
13./pnm2png basn3p02.ppm basn3p02.png
14./pnm2png basn3p04.ppm basn3p04.png
15./pnm2png basn3p08.ppm basn3p08.png
16# -- gray with alpha-channel
17./pnm2png -alpha basn6a08.pgm basn4a08.pgm basn4a08.png
18./pnm2png -alpha basn6a16.pgm basn4a16.pgm basn4a16.png
19# -- color with alpha-channel
20./pnm2png -alpha basn6a08.pgm basn6a08.ppm basn6a08.png
21./pnm2png -alpha basn6a16.pgm basn6a16.ppm basn6a16.png
22# -- grayscale
23./pnm2png rawn0g01.pgm rawn0g01.png
24./pnm2png rawn0g02.pgm rawn0g02.png
25./pnm2png rawn0g04.pgm rawn0g04.png
26./pnm2png rawn0g08.pgm rawn0g08.png
27./pnm2png rawn0g16.pgm rawn0g16.png
28# -- full-color
29./pnm2png rawn2c08.ppm rawn2c08.png
30./pnm2png rawn2c16.ppm rawn2c16.png
31# -- palletted
32./pnm2png rawn3p01.ppm rawn3p01.png
33./pnm2png rawn3p02.ppm rawn3p02.png
34./pnm2png rawn3p04.ppm rawn3p04.png
35./pnm2png rawn3p08.ppm rawn3p08.png
36# -- gray with alpha-channel
37./pnm2png -alpha rawn6a08.pgm rawn4a08.pgm rawn4a08.png
38./pnm2png -alpha rawn6a16.pgm rawn4a16.pgm rawn4a16.png
39# -- color with alpha-channel
40./pnm2png -alpha rawn6a08.pgm rawn6a08.ppm rawn6a08.png
41./pnm2png -alpha rawn6a16.pgm rawn6a16.ppm rawn6a16.png
42
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g01.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g01.png
new file mode 100644
index 0000000..e31e1c7
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g01.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g02.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g02.png
new file mode 100644
index 0000000..68809dd
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g02.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g04.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g04.png
new file mode 100644
index 0000000..6fa089c
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g04.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g08.png
new file mode 100644
index 0000000..bf522ee
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g16.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g16.png
new file mode 100644
index 0000000..318ebca
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn0g16.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn2c08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn2c08.png
new file mode 100644
index 0000000..21d2f91
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn2c08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn2c16.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn2c16.png
new file mode 100644
index 0000000..1bd4a4d
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn2c16.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p01.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p01.png
new file mode 100644
index 0000000..a21db59
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p01.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p02.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p02.png
new file mode 100644
index 0000000..1d0ab61
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p02.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p04.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p04.png
new file mode 100644
index 0000000..6dc6eac
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p04.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p08.png
new file mode 100644
index 0000000..0e07f48
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn3p08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn4a08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn4a08.png
new file mode 100644
index 0000000..3bb0dd0
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn4a08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn4a16.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn4a16.png
new file mode 100644
index 0000000..6dbee9f
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn4a16.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn6a08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn6a08.png
new file mode 100644
index 0000000..6106230
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn6a08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn6a16.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn6a16.png
new file mode 100644
index 0000000..a9bf3cb
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/basn6a16.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn1g04.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn1g04.png
new file mode 100644
index 0000000..39a7050
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn1g04.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn2c16.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn2c16.png
new file mode 100644
index 0000000..dd3168e
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn2c16.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn3p08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn3p08.png
new file mode 100644
index 0000000..0ede357
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbbn3p08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbgn2c16.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbgn2c16.png
new file mode 100644
index 0000000..85cec39
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbgn2c16.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbgn3p08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbgn3p08.png
new file mode 100644
index 0000000..8cf2e6f
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbgn3p08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbrn2c08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbrn2c08.png
new file mode 100644
index 0000000..5cca0d6
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbrn2c08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbwn1g16.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbwn1g16.png
new file mode 100644
index 0000000..99bdeed
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbwn1g16.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbwn3p08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbwn3p08.png
new file mode 100644
index 0000000..eacab7a
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbwn3p08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbyn3p08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbyn3p08.png
new file mode 100644
index 0000000..656db09
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftbyn3p08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n1g08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n1g08.png
new file mode 100644
index 0000000..333465f
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n1g08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n2c08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n2c08.png
new file mode 100644
index 0000000..fc6e42c
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n2c08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n3p08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n3p08.png
new file mode 100644
index 0000000..69a69e58
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp0n3p08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp1n3p08.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp1n3p08.png
new file mode 100644
index 0000000..a6c9f35
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/pngsuite/ftp1n3p08.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/PngFile.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/PngFile.c
new file mode 100644
index 0000000..f3e440a
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/PngFile.c
@@ -0,0 +1,450 @@
1/*-------------------------------------
2 * PNGFILE.C -- Image File Functions
3 *-------------------------------------
4 *
5 * Copyright 2000, Willem van Schaik.
6 *
7 * This code is released under the libpng license.
8 * For conditions of distribution and use, see the disclaimer
9 * and license in png.h
10 */
11
12#include <windows.h>
13#include <commdlg.h>
14#include <stdio.h>
15#include <stdlib.h>
16
17#include "png.h"
18#include "pngfile.h"
19#include "cexcept.h"
20
21define_exception_type(const char *);
22extern struct exception_context the_exception_context[1];
23struct exception_context the_exception_context[1];
24png_const_charp msg;
25
26static OPENFILENAME ofn;
27
28static png_structp png_ptr = NULL;
29static png_infop info_ptr = NULL;
30
31
32/* cexcept interface */
33
34static void
35png_cexcept_error(png_structp png_ptr, png_const_charp msg)
36{
37 if(png_ptr)
38 ;
39#ifdef PNG_CONSOLE_IO_SUPPORTED
40 fprintf(stderr, "libpng error: %s\n", msg);
41#endif
42 {
43 Throw msg;
44 }
45}
46
47/* Windows open-file functions */
48
49void PngFileInitialize (HWND hwnd)
50{
51 static TCHAR szFilter[] = TEXT ("PNG Files (*.PNG)\0*.png\0")
52 TEXT ("All Files (*.*)\0*.*\0\0");
53
54 ofn.lStructSize = sizeof (OPENFILENAME);
55 ofn.hwndOwner = hwnd;
56 ofn.hInstance = NULL;
57 ofn.lpstrFilter = szFilter;
58 ofn.lpstrCustomFilter = NULL;
59 ofn.nMaxCustFilter = 0;
60 ofn.nFilterIndex = 0;
61 ofn.lpstrFile = NULL; /* Set in Open and Close functions */
62 ofn.nMaxFile = MAX_PATH;
63 ofn.lpstrFileTitle = NULL; /* Set in Open and Close functions */
64 ofn.nMaxFileTitle = MAX_PATH;
65 ofn.lpstrInitialDir = NULL;
66 ofn.lpstrTitle = NULL;
67 ofn.Flags = 0; /* Set in Open and Close functions */
68 ofn.nFileOffset = 0;
69 ofn.nFileExtension = 0;
70 ofn.lpstrDefExt = TEXT ("png");
71 ofn.lCustData = 0;
72 ofn.lpfnHook = NULL;
73 ofn.lpTemplateName = NULL;
74}
75
76BOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
77{
78 ofn.hwndOwner = hwnd;
79 ofn.lpstrFile = pstrFileName;
80 ofn.lpstrFileTitle = pstrTitleName;
81 ofn.Flags = OFN_HIDEREADONLY;
82
83 return GetOpenFileName (&ofn);
84}
85
86BOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
87{
88 ofn.hwndOwner = hwnd;
89 ofn.lpstrFile = pstrFileName;
90 ofn.lpstrFileTitle = pstrTitleName;
91 ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
92
93 return GetSaveFileName (&ofn);
94}
95
96/* PNG image handler functions */
97
98BOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData,
99 int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor)
100{
101 static FILE *pfFile;
102 png_byte pbSig[8];
103 int iBitDepth;
104 int iColorType;
105 double dGamma;
106 png_color_16 *pBackground;
107 png_uint_32 ulChannels;
108 png_uint_32 ulRowBytes;
109 png_byte *pbImageData = *ppbImageData;
110 static png_byte **ppbRowPointers = NULL;
111 int i;
112
113 /* open the PNG input file */
114
115 if (!pstrFileName)
116 {
117 *ppbImageData = pbImageData = NULL;
118 return FALSE;
119 }
120
121 if (!(pfFile = fopen(pstrFileName, "rb")))
122 {
123 *ppbImageData = pbImageData = NULL;
124 return FALSE;
125 }
126
127 /* first check the eight byte PNG signature */
128
129 fread(pbSig, 1, 8, pfFile);
130 if (png_sig_cmp(pbSig, 0, 8))
131 {
132 *ppbImageData = pbImageData = NULL;
133 return FALSE;
134 }
135
136 /* create the two png(-info) structures */
137
138 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
139 (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
140 if (!png_ptr)
141 {
142 *ppbImageData = pbImageData = NULL;
143 return FALSE;
144 }
145
146 info_ptr = png_create_info_struct(png_ptr);
147 if (!info_ptr)
148 {
149 png_destroy_read_struct(&png_ptr, NULL, NULL);
150 *ppbImageData = pbImageData = NULL;
151 return FALSE;
152 }
153
154 Try
155 {
156
157 /* initialize the png structure */
158
159#ifdef PNG_STDIO_SUPPORTED
160 png_init_io(png_ptr, pfFile);
161#else
162 png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data);
163#endif
164
165 png_set_sig_bytes(png_ptr, 8);
166
167 /* read all PNG info up to image data */
168
169 png_read_info(png_ptr, info_ptr);
170
171 /* get width, height, bit-depth and color-type */
172
173 png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
174 &iColorType, NULL, NULL, NULL);
175
176 /* expand images of all color-type and bit-depth to 3x8-bit RGB */
177 /* let the library process alpha, transparency, background, etc. */
178
179#ifdef PNG_READ_16_TO_8_SUPPORTED
180 if (iBitDepth == 16)
181# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
182 png_set_scale_16(png_ptr);
183# else
184 png_set_strip_16(png_ptr);
185# endif
186#endif
187 if (iColorType == PNG_COLOR_TYPE_PALETTE)
188 png_set_expand(png_ptr);
189 if (iBitDepth < 8)
190 png_set_expand(png_ptr);
191 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
192 png_set_expand(png_ptr);
193 if (iColorType == PNG_COLOR_TYPE_GRAY ||
194 iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
195 png_set_gray_to_rgb(png_ptr);
196
197 /* set the background color to draw transparent and alpha images over */
198 if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
199 {
200 png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
201 pBkgColor->red = (byte) pBackground->red;
202 pBkgColor->green = (byte) pBackground->green;
203 pBkgColor->blue = (byte) pBackground->blue;
204 }
205 else
206 {
207 pBkgColor = NULL;
208 }
209
210 /* if required set gamma conversion */
211 if (png_get_gAMA(png_ptr, info_ptr, &dGamma))
212 png_set_gamma(png_ptr, (double) 2.2, dGamma);
213
214 /* after the transformations are registered, update info_ptr data */
215
216 png_read_update_info(png_ptr, info_ptr);
217
218 /* get again width, height and the new bit-depth and color-type */
219
220 png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
221 &iColorType, NULL, NULL, NULL);
222
223
224 /* row_bytes is the width x number of channels */
225
226 ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
227 ulChannels = png_get_channels(png_ptr, info_ptr);
228
229 *piChannels = ulChannels;
230
231 /* now we can allocate memory to store the image */
232
233 if (pbImageData)
234 {
235 free (pbImageData);
236 pbImageData = NULL;
237 }
238 if ((pbImageData = (png_byte *) malloc(ulRowBytes * (*piHeight)
239 * sizeof(png_byte))) == NULL)
240 {
241 png_error(png_ptr, "Visual PNG: out of memory");
242 }
243 *ppbImageData = pbImageData;
244
245 /* and allocate memory for an array of row-pointers */
246
247 if ((ppbRowPointers = (png_bytepp) malloc((*piHeight)
248 * sizeof(png_bytep))) == NULL)
249 {
250 png_error(png_ptr, "Visual PNG: out of memory");
251 }
252
253 /* set the individual row-pointers to point at the correct offsets */
254
255 for (i = 0; i < (*piHeight); i++)
256 ppbRowPointers[i] = pbImageData + i * ulRowBytes;
257
258 /* now we can go ahead and just read the whole image */
259
260 png_read_image(png_ptr, ppbRowPointers);
261
262 /* read the additional chunks in the PNG file (not really needed) */
263
264 png_read_end(png_ptr, NULL);
265
266 /* and we're done */
267
268 free (ppbRowPointers);
269 ppbRowPointers = NULL;
270
271 /* yepp, done */
272 }
273
274 Catch (msg)
275 {
276 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
277
278 *ppbImageData = pbImageData = NULL;
279
280 if(ppbRowPointers)
281 free (ppbRowPointers);
282
283 fclose(pfFile);
284
285 return FALSE;
286 }
287
288 fclose (pfFile);
289
290 return TRUE;
291}
292
293
294BOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData,
295 int iWidth, int iHeight, png_color bkgColor)
296{
297 const int ciBitDepth = 8;
298 const int ciChannels = 3;
299
300 static FILE *pfFile;
301 png_uint_32 ulRowBytes;
302 static png_byte **ppbRowPointers = NULL;
303 int i;
304
305 /* open the PNG output file */
306
307 if (!pstrFileName)
308 return FALSE;
309
310 if (!(pfFile = fopen(pstrFileName, "wb")))
311 return FALSE;
312
313 /* prepare the standard PNG structures */
314
315 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
316 (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
317 if (!png_ptr)
318 {
319 fclose(pfFile);
320 return FALSE;
321 }
322
323 info_ptr = png_create_info_struct(png_ptr);
324 if (!info_ptr) {
325 fclose(pfFile);
326 png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
327 return FALSE;
328 }
329
330 Try
331 {
332 /* initialize the png structure */
333
334#ifdef PNG_STDIO_SUPPORTED
335 png_init_io(png_ptr, pfFile);
336#else
337 png_set_write_fn(png_ptr, (png_voidp)pfFile, png_write_data, png_flush);
338#endif
339
340 /* we're going to write a very simple 3x8-bit RGB image */
341
342 png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth,
343 PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
344 PNG_FILTER_TYPE_BASE);
345
346 /* write the file header information */
347
348 png_write_info(png_ptr, info_ptr);
349
350 /* swap the BGR pixels in the DiData structure to RGB */
351
352 png_set_bgr(png_ptr);
353
354 /* row_bytes is the width x number of channels */
355
356 ulRowBytes = iWidth * ciChannels;
357
358 /* we can allocate memory for an array of row-pointers */
359
360 if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL)
361 Throw "Visualpng: Out of memory";
362
363 /* set the individual row-pointers to point at the correct offsets */
364
365 for (i = 0; i < iHeight; i++)
366 ppbRowPointers[i] = pDiData + i * (((ulRowBytes + 3) >> 2) << 2);
367
368 /* write out the entire image data in one call */
369
370 png_write_image (png_ptr, ppbRowPointers);
371
372 /* write the additional chunks to the PNG file (not really needed) */
373
374 png_write_end(png_ptr, info_ptr);
375
376 /* and we're done */
377
378 free (ppbRowPointers);
379 ppbRowPointers = NULL;
380
381 /* clean up after the write, and free any memory allocated */
382
383 png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
384
385 /* yepp, done */
386 }
387
388 Catch (msg)
389 {
390 png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
391
392 if(ppbRowPointers)
393 free (ppbRowPointers);
394
395 fclose(pfFile);
396
397 return FALSE;
398 }
399
400 fclose (pfFile);
401
402 return TRUE;
403}
404
405#ifndef PNG_STDIO_SUPPORTED
406
407static void
408png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
409{
410 png_size_t check;
411
412 /* fread() returns 0 on error, so it is OK to store this in a png_size_t
413 * instead of an int, which is what fread() actually returns.
414 */
415 check = (png_size_t)fread(data, (png_size_t)1, length,
416 (FILE *)png_ptr->io_ptr);
417
418 if (check != length)
419 {
420 png_error(png_ptr, "Read Error");
421 }
422}
423
424static void
425png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
426{
427 png_uint_32 check;
428
429 check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
430 if (check != length)
431 {
432 png_error(png_ptr, "Write Error");
433 }
434}
435
436static void
437png_flush(png_structp png_ptr)
438{
439 FILE *io_ptr;
440 io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr));
441 if (io_ptr != NULL)
442 fflush(io_ptr);
443}
444
445#endif
446
447/*-----------------
448 * end of source
449 *-----------------
450 */
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/PngFile.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/PngFile.h
new file mode 100644
index 0000000..66f8472
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/PngFile.h
@@ -0,0 +1,30 @@
1/*------------------------------------------*/
2/* PNGFILE.H -- Header File for pngfile.c*/
3/*------------------------------------------*/
4
5/* Copyright 2000, Willem van Schaik.*/
6
7/* This code is released under the libpng license.*/
8/* For conditions of distribution and use, see the disclaimer*/
9/* and license in png.h*/
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <windows.h>
15
16void PngFileInitialize (HWND hwnd) ;
17BOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) ;
18BOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) ;
19
20BOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData,
21 int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor);
22BOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData,
23 int iWidth, int iHeight, png_color BkgColor);
24
25#ifndef PNG_STDIO_SUPPORTED
26static void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length);
27static void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length);
28static void png_flush(png_structp png_ptr);
29#endif
30
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/README.txt b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/README.txt
new file mode 100644
index 0000000..7291bb2
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/README.txt
@@ -0,0 +1,61 @@
1Microsoft Developer Studio Build File, Format Version 6.00 for VisualPng
2------------------------------------------------------------------------
3
4Copyright 2000, Willem van Schaik.
5
6This code is released under the libpng license.
7For conditions of distribution and use, see the disclaimer
8and license in png.h
9
10As a PNG .dll demo VisualPng is finished. More features would only hinder
11the program's objective. However, further extensions (like support for other
12graphics formats) are in development. To get these, or for pre-compiled
13binaries, go to "http://www.schaik.com/png/visualpng.html".
14
15------------------------------------------------------------------------
16
17Assumes that
18
19 libpng DLLs and LIBs are in ..\..\projects\msvc\win32\libpng
20 zlib DLLs and LIBs are in ..\..\projects\msvc\win32\zlib
21 libpng header files are in ..\..\..\libpng
22 zlib header files are in ..\..\..\zlib
23 the pngsuite images are in ..\pngsuite
24
25To build:
26
271) On the main menu Select "Build|Set Active configuration".
28 Choose the configuration that corresponds to the library you want to test.
29 This library must have been built using the libpng MS project located in
30 the "..\..\mscv" subdirectory.
31
322) Select "Build|Clean"
33
343) Select "Build|Rebuild All"
35
364) After compiling and linking VisualPng will be started to view an image
37 from the PngSuite directory. Press Ctrl-N (and Ctrl-V) for other images.
38
39
40To install:
41
42When distributing VisualPng (or a further development) the following options
43are available:
44
451) Build the program with the configuration "Win32 LIB" and you only need to
46 include the executable from the ./lib directory in your distribution.
47
482) Build the program with the configuration "Win32 DLL" and you need to put
49 in your distribution the executable from the ./dll directory and the dll's
50 libpng1.dll, zlib.dll and msvcrt.dll. These need to be in the user's PATH.
51
52
53Willem van Schaik
54Calgary, June 6th 2000
55
56P.S. VisualPng was written based on preliminary work of:
57
58 - Simon-Pierre Cadieux
59 - Glenn Randers-Pehrson
60 - Greg Roelofs
61
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.c
new file mode 100644
index 0000000..e672ce0
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.c
@@ -0,0 +1,969 @@
1/*------------------------------------
2 * VisualPng.C -- Shows a PNG image
3 *------------------------------------
4 *
5 * Copyright 2000, Willem van Schaik.
6 *
7 * This code is released under the libpng license.
8 * For conditions of distribution and use, see the disclaimer
9 * and license in png.h
10 */
11
12/* switches */
13
14/* defines */
15
16#define PROGNAME "VisualPng"
17#define LONGNAME "Win32 Viewer for PNG-files"
18#define VERSION "1.0 of 2000 June 07"
19
20/* constants */
21
22#define MARGIN 8
23
24/* standard includes */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <windows.h>
30
31/* application includes */
32
33#include "png.h"
34#include "pngfile.h"
35#include "resource.h"
36
37/* macros */
38
39/* function prototypes */
40
41LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
42BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
43
44BOOL CenterAbout (HWND hwndChild, HWND hwndParent);
45
46BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
47 int *pFileIndex);
48
49BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex,
50 PTSTR pstrPrevName, PTSTR pstrNextName);
51
52BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName,
53 png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels,
54 png_color *pBkgColor);
55
56BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
57 BYTE **ppDiData, int cxWinSize, int cyWinSize,
58 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
59 BOOL bStretched);
60
61BOOL InitBitmap (
62 BYTE *pDiData, int cxWinSize, int cyWinSize);
63
64BOOL FillBitmap (
65 BYTE *pDiData, int cxWinSize, int cyWinSize,
66 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
67 BOOL bStretched);
68
69/* a few global variables */
70
71static char *szProgName = PROGNAME;
72static char *szAppName = LONGNAME;
73static char *szIconName = PROGNAME;
74static char szCmdFileName [MAX_PATH];
75
76/* MAIN routine */
77
78int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
79 PSTR szCmdLine, int iCmdShow)
80{
81 HACCEL hAccel;
82 HWND hwnd;
83 MSG msg;
84 WNDCLASS wndclass;
85 int ixBorders, iyBorders;
86
87 wndclass.style = CS_HREDRAW | CS_VREDRAW;
88 wndclass.lpfnWndProc = WndProc;
89 wndclass.cbClsExtra = 0;
90 wndclass.cbWndExtra = 0;
91 wndclass.hInstance = hInstance;
92 wndclass.hIcon = LoadIcon (hInstance, szIconName) ;
93 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
94 wndclass.hbrBackground = NULL; /* (HBRUSH) GetStockObject (GRAY_BRUSH); */
95 wndclass.lpszMenuName = szProgName;
96 wndclass.lpszClassName = szProgName;
97
98 if (!RegisterClass (&wndclass))
99 {
100 MessageBox (NULL, TEXT ("Error: this program requires Windows NT!"),
101 szProgName, MB_ICONERROR);
102 return 0;
103 }
104
105 /* if filename given on commandline, store it */
106 if ((szCmdLine != NULL) && (*szCmdLine != '\0'))
107 if (szCmdLine[0] == '"')
108 strncpy (szCmdFileName, szCmdLine + 1, strlen(szCmdLine) - 2);
109 else
110 strcpy (szCmdFileName, szCmdLine);
111 else
112 strcpy (szCmdFileName, "");
113
114 /* calculate size of window-borders */
115 ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) +
116 GetSystemMetrics (SM_CXDLGFRAME));
117 iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) +
118 GetSystemMetrics (SM_CYDLGFRAME)) +
119 GetSystemMetrics (SM_CYCAPTION) +
120 GetSystemMetrics (SM_CYMENUSIZE) +
121 1; /* WvS: don't ask me why? */
122
123 hwnd = CreateWindow (szProgName, szAppName,
124 WS_OVERLAPPEDWINDOW,
125 CW_USEDEFAULT, CW_USEDEFAULT,
126 512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders,
127/* CW_USEDEFAULT, CW_USEDEFAULT, */
128 NULL, NULL, hInstance, NULL);
129
130 ShowWindow (hwnd, iCmdShow);
131 UpdateWindow (hwnd);
132
133 hAccel = LoadAccelerators (hInstance, szProgName);
134
135 while (GetMessage (&msg, NULL, 0, 0))
136 {
137 if (!TranslateAccelerator (hwnd, hAccel, &msg))
138 {
139 TranslateMessage (&msg);
140 DispatchMessage (&msg);
141 }
142 }
143 return msg.wParam;
144}
145
146LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
147 LPARAM lParam)
148{
149 static HINSTANCE hInstance ;
150 static HDC hdc;
151 static PAINTSTRUCT ps;
152 static HMENU hMenu;
153
154 static BITMAPFILEHEADER *pbmfh;
155 static BITMAPINFOHEADER *pbmih;
156 static BYTE *pbImage;
157 static int cxWinSize, cyWinSize;
158 static int cxImgSize, cyImgSize;
159 static int cImgChannels;
160 static png_color bkgColor = {127, 127, 127};
161
162 static BOOL bStretched = TRUE;
163
164 static BYTE *pDib = NULL;
165 static BYTE *pDiData = NULL;
166
167 static TCHAR szImgPathName [MAX_PATH];
168 static TCHAR szTitleName [MAX_PATH];
169
170 static TCHAR *pPngFileList = NULL;
171 static int iPngFileCount;
172 static int iPngFileIndex;
173
174 BOOL bOk;
175
176 switch (message)
177 {
178 case WM_CREATE:
179 hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
180 PngFileInitialize (hwnd);
181
182 strcpy (szImgPathName, "");
183
184 /* in case we process file given on command-line */
185
186 if (szCmdFileName[0] != '\0')
187 {
188 strcpy (szImgPathName, szCmdFileName);
189
190 /* read the other png-files in the directory for later */
191 /* next/previous commands */
192
193 BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
194 &iPngFileIndex);
195
196 /* load the image from file */
197
198 if (!LoadImageFile (hwnd, szImgPathName,
199 &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
200 return 0;
201
202 /* invalidate the client area for later update */
203
204 InvalidateRect (hwnd, NULL, TRUE);
205
206 /* display the PNG into the DIBitmap */
207
208 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
209 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
210 }
211
212 return 0;
213
214 case WM_SIZE:
215 cxWinSize = LOWORD (lParam);
216 cyWinSize = HIWORD (lParam);
217
218 /* invalidate the client area for later update */
219
220 InvalidateRect (hwnd, NULL, TRUE);
221
222 /* display the PNG into the DIBitmap */
223
224 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
225 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
226
227 return 0;
228
229 case WM_INITMENUPOPUP:
230 hMenu = GetMenu (hwnd);
231
232 if (pbImage)
233 EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_ENABLED);
234 else
235 EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_GRAYED);
236
237 return 0;
238
239 case WM_COMMAND:
240 hMenu = GetMenu (hwnd);
241
242 switch (LOWORD (wParam))
243 {
244 case IDM_FILE_OPEN:
245
246 /* show the File Open dialog box */
247
248 if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName))
249 return 0;
250
251 /* read the other png-files in the directory for later */
252 /* next/previous commands */
253
254 BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
255 &iPngFileIndex);
256
257 /* load the image from file */
258
259 if (!LoadImageFile (hwnd, szImgPathName,
260 &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
261 return 0;
262
263 /* invalidate the client area for later update */
264
265 InvalidateRect (hwnd, NULL, TRUE);
266
267 /* display the PNG into the DIBitmap */
268
269 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
270 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
271
272 return 0;
273
274 case IDM_FILE_SAVE:
275
276 /* show the File Save dialog box */
277
278 if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName))
279 return 0;
280
281 /* save the PNG to a disk file */
282
283 SetCursor (LoadCursor (NULL, IDC_WAIT));
284 ShowCursor (TRUE);
285
286 bOk = PngSaveImage (szImgPathName, pDiData, cxWinSize, cyWinSize,
287 bkgColor);
288
289 ShowCursor (FALSE);
290 SetCursor (LoadCursor (NULL, IDC_ARROW));
291
292 if (!bOk)
293 MessageBox (hwnd, TEXT ("Error in saving the PNG image"),
294 szProgName, MB_ICONEXCLAMATION | MB_OK);
295 return 0;
296
297 case IDM_FILE_NEXT:
298
299 /* read next entry in the directory */
300
301 if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
302 NULL, szImgPathName))
303 {
304 if (strcmp (szImgPathName, "") == 0)
305 return 0;
306
307 /* load the image from file */
308
309 if (!LoadImageFile (hwnd, szImgPathName, &pbImage,
310 &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
311 return 0;
312
313 /* invalidate the client area for later update */
314
315 InvalidateRect (hwnd, NULL, TRUE);
316
317 /* display the PNG into the DIBitmap */
318
319 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
320 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
321 }
322
323 return 0;
324
325 case IDM_FILE_PREVIOUS:
326
327 /* read previous entry in the directory */
328
329 if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
330 szImgPathName, NULL))
331 {
332
333 if (strcmp (szImgPathName, "") == 0)
334 return 0;
335
336 /* load the image from file */
337
338 if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize,
339 &cyImgSize, &cImgChannels, &bkgColor))
340 return 0;
341
342 /* invalidate the client area for later update */
343
344 InvalidateRect (hwnd, NULL, TRUE);
345
346 /* display the PNG into the DIBitmap */
347
348 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
349 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
350 }
351
352 return 0;
353
354 case IDM_FILE_EXIT:
355
356 /* more cleanup needed... */
357
358 /* free image buffer */
359
360 if (pDib != NULL)
361 {
362 free (pDib);
363 pDib = NULL;
364 }
365
366 /* free file-list */
367
368 if (pPngFileList != NULL)
369 {
370 free (pPngFileList);
371 pPngFileList = NULL;
372 }
373
374 /* let's go ... */
375
376 exit (0);
377
378 return 0;
379
380 case IDM_OPTIONS_STRETCH:
381 bStretched = !bStretched;
382 if (bStretched)
383 CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_CHECKED);
384 else
385 CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED);
386
387 /* invalidate the client area for later update */
388
389 InvalidateRect (hwnd, NULL, TRUE);
390
391 /* display the PNG into the DIBitmap */
392
393 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
394 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
395
396 return 0;
397
398 case IDM_HELP_ABOUT:
399 DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ;
400 return 0;
401
402 } /* end switch */
403
404 break;
405
406 case WM_PAINT:
407 hdc = BeginPaint (hwnd, &ps);
408
409 if (pDib)
410 SetDIBitsToDevice (hdc, 0, 0, cxWinSize, cyWinSize, 0, 0,
411 0, cyWinSize, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS);
412
413 EndPaint (hwnd, &ps);
414 return 0;
415
416 case WM_DESTROY:
417 if (pbmfh)
418 {
419 free (pbmfh);
420 pbmfh = NULL;
421 }
422
423 PostQuitMessage (0);
424 return 0;
425 }
426
427 return DefWindowProc (hwnd, message, wParam, lParam);
428}
429
430BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,
431 WPARAM wParam, LPARAM lParam)
432{
433 switch (message)
434 {
435 case WM_INITDIALOG :
436 ShowWindow (hDlg, SW_HIDE);
437 CenterAbout (hDlg, GetWindow (hDlg, GW_OWNER));
438 ShowWindow (hDlg, SW_SHOW);
439 return TRUE ;
440
441 case WM_COMMAND :
442 switch (LOWORD (wParam))
443 {
444 case IDOK :
445 case IDCANCEL :
446 EndDialog (hDlg, 0) ;
447 return TRUE ;
448 }
449 break ;
450 }
451 return FALSE ;
452}
453
454/*---------------
455 * CenterAbout
456 *---------------
457 */
458BOOL CenterAbout (HWND hwndChild, HWND hwndParent)
459{
460 RECT rChild, rParent, rWorkArea;
461 int wChild, hChild, wParent, hParent;
462 int xNew, yNew;
463 BOOL bResult;
464
465 /* Get the Height and Width of the child window */
466 GetWindowRect (hwndChild, &rChild);
467 wChild = rChild.right - rChild.left;
468 hChild = rChild.bottom - rChild.top;
469
470 /* Get the Height and Width of the parent window */
471 GetWindowRect (hwndParent, &rParent);
472 wParent = rParent.right - rParent.left;
473 hParent = rParent.bottom - rParent.top;
474
475 /* Get the limits of the 'workarea' */
476 bResult = SystemParametersInfo(
477 SPI_GETWORKAREA, /* system parameter to query or set */
478 sizeof(RECT),
479 &rWorkArea,
480 0);
481 if (!bResult) {
482 rWorkArea.left = rWorkArea.top = 0;
483 rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
484 rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
485 }
486
487 /* Calculate new X position, then adjust for workarea */
488 xNew = rParent.left + ((wParent - wChild) /2);
489 if (xNew < rWorkArea.left) {
490 xNew = rWorkArea.left;
491 } else if ((xNew+wChild) > rWorkArea.right) {
492 xNew = rWorkArea.right - wChild;
493 }
494
495 /* Calculate new Y position, then adjust for workarea */
496 yNew = rParent.top + ((hParent - hChild) /2);
497 if (yNew < rWorkArea.top) {
498 yNew = rWorkArea.top;
499 } else if ((yNew+hChild) > rWorkArea.bottom) {
500 yNew = rWorkArea.bottom - hChild;
501 }
502
503 /* Set it, and return */
504 return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE |
505 SWP_NOZORDER);
506}
507
508/*----------------
509 * BuildPngList
510 *----------------
511 */
512BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
513 int *pFileIndex)
514{
515 static TCHAR szImgPathName [MAX_PATH];
516 static TCHAR szImgFileName [MAX_PATH];
517 static TCHAR szImgFindName [MAX_PATH];
518
519 WIN32_FIND_DATA finddata;
520 HANDLE hFind;
521
522 static TCHAR szTmp [MAX_PATH];
523 BOOL bOk;
524 int i, ii;
525 int j, jj;
526
527 /* free previous file-list */
528
529 if (*ppFileList != NULL)
530 {
531 free (*ppFileList);
532 *ppFileList = NULL;
533 }
534
535 /* extract foldername, filename and search-name */
536
537 strcpy (szImgPathName, pstrPathName);
538 strcpy (szImgFileName, strrchr (pstrPathName, '\\') + 1);
539
540 strcpy (szImgFindName, szImgPathName);
541 *(strrchr (szImgFindName, '\\') + 1) = '\0';
542 strcat (szImgFindName, "*.png");
543
544 /* first cycle: count number of files in directory for memory allocation */
545
546 *pFileCount = 0;
547
548 hFind = FindFirstFile(szImgFindName, &finddata);
549 bOk = (hFind != (HANDLE) -1);
550
551 while (bOk)
552 {
553 *pFileCount += 1;
554 bOk = FindNextFile(hFind, &finddata);
555 }
556 FindClose(hFind);
557
558 /* allocation memory for file-list */
559
560 *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH);
561
562 /* second cycle: read directory and store filenames in file-list */
563
564 hFind = FindFirstFile(szImgFindName, &finddata);
565 bOk = (hFind != (HANDLE) -1);
566
567 i = 0;
568 ii = 0;
569 while (bOk)
570 {
571 strcpy (*ppFileList + ii, szImgPathName);
572 strcpy (strrchr(*ppFileList + ii, '\\') + 1, finddata.cFileName);
573
574 if (strcmp(pstrPathName, *ppFileList + ii) == 0)
575 *pFileIndex = i;
576
577 ii += MAX_PATH;
578 i++;
579
580 bOk = FindNextFile(hFind, &finddata);
581 }
582 FindClose(hFind);
583
584 /* finally we must sort the file-list */
585
586 for (i = 0; i < *pFileCount - 1; i++)
587 {
588 ii = i * MAX_PATH;
589 for (j = i+1; j < *pFileCount; j++)
590 {
591 jj = j * MAX_PATH;
592 if (strcmp (*ppFileList + ii, *ppFileList + jj) > 0)
593 {
594 strcpy (szTmp, *ppFileList + jj);
595 strcpy (*ppFileList + jj, *ppFileList + ii);
596 strcpy (*ppFileList + ii, szTmp);
597
598 /* check if this was the current image that we moved */
599
600 if (*pFileIndex == i)
601 *pFileIndex = j;
602 else
603 if (*pFileIndex == j)
604 *pFileIndex = i;
605 }
606 }
607 }
608
609 return TRUE;
610}
611
612/*----------------
613 * SearchPngList
614 *----------------
615 */
616
617BOOL SearchPngList (
618 TCHAR *pFileList, int FileCount, int *pFileIndex,
619 PTSTR pstrPrevName, PTSTR pstrNextName)
620{
621 if (FileCount > 0)
622 {
623 /* get previous entry */
624
625 if (pstrPrevName != NULL)
626 {
627 if (*pFileIndex > 0)
628 *pFileIndex -= 1;
629 else
630 *pFileIndex = FileCount - 1;
631
632 strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH));
633 }
634
635 /* get next entry */
636
637 if (pstrNextName != NULL)
638 {
639 if (*pFileIndex < FileCount - 1)
640 *pFileIndex += 1;
641 else
642 *pFileIndex = 0;
643
644 strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH));
645 }
646
647 return TRUE;
648 }
649 else
650 {
651 return FALSE;
652 }
653}
654
655/*-----------------
656 * LoadImageFile
657 *-----------------
658 */
659
660BOOL LoadImageFile (HWND hwnd, PTSTR pstrPathName,
661 png_byte **ppbImage, int *pxImgSize, int *pyImgSize,
662 int *piChannels, png_color *pBkgColor)
663{
664 static TCHAR szTmp [MAX_PATH];
665
666 /* if there's an existing PNG, free the memory */
667
668 if (*ppbImage)
669 {
670 free (*ppbImage);
671 *ppbImage = NULL;
672 }
673
674 /* Load the entire PNG into memory */
675
676 SetCursor (LoadCursor (NULL, IDC_WAIT));
677 ShowCursor (TRUE);
678
679 PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels,
680 pBkgColor);
681
682 ShowCursor (FALSE);
683 SetCursor (LoadCursor (NULL, IDC_ARROW));
684
685 if (*ppbImage != NULL)
686 {
687 sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1);
688 SetWindowText (hwnd, szTmp);
689 }
690 else
691 {
692 MessageBox (hwnd, TEXT ("Error in loading the PNG image"),
693 szProgName, MB_ICONEXCLAMATION | MB_OK);
694 return FALSE;
695 }
696
697 return TRUE;
698}
699
700/*----------------
701 * DisplayImage
702 *----------------
703 */
704BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
705 BYTE **ppDiData, int cxWinSize, int cyWinSize,
706 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
707 BOOL bStretched)
708{
709 BYTE *pDib = *ppDib;
710 BYTE *pDiData = *ppDiData;
711 /* BITMAPFILEHEADER *pbmfh; */
712 BITMAPINFOHEADER *pbmih;
713 WORD wDIRowBytes;
714 png_color bkgBlack = {0, 0, 0};
715 png_color bkgGray = {127, 127, 127};
716 png_color bkgWhite = {255, 255, 255};
717
718 /* allocate memory for the Device Independant bitmap */
719
720 wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2;
721
722 if (pDib)
723 {
724 free (pDib);
725 pDib = NULL;
726 }
727
728 if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) +
729 wDIRowBytes * cyWinSize)))
730 {
731 MessageBox (hwnd, TEXT ("Error in displaying the PNG image"),
732 szProgName, MB_ICONEXCLAMATION | MB_OK);
733 *ppDib = pDib = NULL;
734 return FALSE;
735 }
736 *ppDib = pDib;
737 memset (pDib, 0, sizeof(BITMAPINFOHEADER));
738
739 /* initialize the dib-structure */
740
741 pbmih = (BITMAPINFOHEADER *) pDib;
742 pbmih->biSize = sizeof(BITMAPINFOHEADER);
743 pbmih->biWidth = cxWinSize;
744 pbmih->biHeight = -((long) cyWinSize);
745 pbmih->biPlanes = 1;
746 pbmih->biBitCount = 24;
747 pbmih->biCompression = 0;
748 pDiData = pDib + sizeof(BITMAPINFOHEADER);
749 *ppDiData = pDiData;
750
751 /* first fill bitmap with gray and image border */
752
753 InitBitmap (pDiData, cxWinSize, cyWinSize);
754
755 /* then fill bitmap with image */
756
757 if (pbImage)
758 {
759 FillBitmap (
760 pDiData, cxWinSize, cyWinSize,
761 pbImage, cxImgSize, cyImgSize, cImgChannels,
762 bStretched);
763 }
764
765 return TRUE;
766}
767
768/*--------------
769 * InitBitmap
770 *--------------
771 */
772BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize)
773{
774 BYTE *dst;
775 int x, y, col;
776
777 /* initialize the background with gray */
778
779 dst = pDiData;
780 for (y = 0; y < cyWinSize; y++)
781 {
782 col = 0;
783 for (x = 0; x < cxWinSize; x++)
784 {
785 /* fill with GRAY */
786 *dst++ = 127;
787 *dst++ = 127;
788 *dst++ = 127;
789 col += 3;
790 }
791 /* rows start on 4 byte boundaries */
792 while ((col % 4) != 0)
793 {
794 dst++;
795 col++;
796 }
797 }
798
799 return TRUE;
800}
801
802/*--------------
803 * FillBitmap
804 *--------------
805 */
806BOOL FillBitmap (
807 BYTE *pDiData, int cxWinSize, int cyWinSize,
808 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
809 BOOL bStretched)
810{
811 BYTE *pStretchedImage;
812 BYTE *pImg;
813 BYTE *src, *dst;
814 BYTE r, g, b, a;
815 const int cDIChannels = 3;
816 WORD wImgRowBytes;
817 WORD wDIRowBytes;
818 int cxNewSize, cyNewSize;
819 int cxImgPos, cyImgPos;
820 int xImg, yImg;
821 int xWin, yWin;
822 int xOld, yOld;
823 int xNew, yNew;
824
825 if (bStretched)
826 {
827 cxNewSize = cxWinSize - 2 * MARGIN;
828 cyNewSize = cyWinSize - 2 * MARGIN;
829
830 /* stretch the image to it's window determined size */
831
832 /* the following two are mathematically the same, but the first
833 * has side-effects because of rounding
834 */
835/* if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize)) */
836 if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize))
837 {
838 cyNewSize = cxNewSize * cyImgSize / cxImgSize;
839 cxImgPos = MARGIN;
840 cyImgPos = (cyWinSize - cyNewSize) / 2;
841 }
842 else
843 {
844 cxNewSize = cyNewSize * cxImgSize / cyImgSize;
845 cyImgPos = MARGIN;
846 cxImgPos = (cxWinSize - cxNewSize) / 2;
847 }
848
849 pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize);
850 pImg = pStretchedImage;
851
852 for (yNew = 0; yNew < cyNewSize; yNew++)
853 {
854 yOld = yNew * cyImgSize / cyNewSize;
855 for (xNew = 0; xNew < cxNewSize; xNew++)
856 {
857 xOld = xNew * cxImgSize / cxNewSize;
858
859 r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0);
860 g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1);
861 b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2);
862 *pImg++ = r;
863 *pImg++ = g;
864 *pImg++ = b;
865 if (cImgChannels == 4)
866 {
867 a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld)
868 + 3);
869 *pImg++ = a;
870 }
871 }
872 }
873
874 /* calculate row-bytes */
875
876 wImgRowBytes = cImgChannels * cxNewSize;
877 wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
878
879 /* copy image to screen */
880
881 for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++)
882 {
883 if (yWin >= cyWinSize - cyImgPos)
884 break;
885 src = pStretchedImage + yImg * wImgRowBytes;
886 dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
887
888 for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++)
889 {
890 if (xWin >= cxWinSize - cxImgPos)
891 break;
892 r = *src++;
893 g = *src++;
894 b = *src++;
895 *dst++ = b; /* note the reverse order */
896 *dst++ = g;
897 *dst++ = r;
898 if (cImgChannels == 4)
899 {
900 a = *src++;
901 }
902 }
903 }
904
905 /* free memory */
906
907 if (pStretchedImage != NULL)
908 {
909 free (pStretchedImage);
910 pStretchedImage = NULL;
911 }
912
913 }
914
915 /* process the image not-stretched */
916
917 else
918 {
919 /* calculate the central position */
920
921 cxImgPos = (cxWinSize - cxImgSize) / 2;
922 cyImgPos = (cyWinSize - cyImgSize) / 2;
923
924 /* check for image larger than window */
925
926 if (cxImgPos < MARGIN)
927 cxImgPos = MARGIN;
928 if (cyImgPos < MARGIN)
929 cyImgPos = MARGIN;
930
931 /* calculate both row-bytes */
932
933 wImgRowBytes = cImgChannels * cxImgSize;
934 wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
935
936 /* copy image to screen */
937
938 for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++)
939 {
940 if (yWin >= cyWinSize - MARGIN)
941 break;
942 src = pbImage + yImg * wImgRowBytes;
943 dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
944
945 for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++)
946 {
947 if (xWin >= cxWinSize - MARGIN)
948 break;
949 r = *src++;
950 g = *src++;
951 b = *src++;
952 *dst++ = b; /* note the reverse order */
953 *dst++ = g;
954 *dst++ = r;
955 if (cImgChannels == 4)
956 {
957 a = *src++;
958 }
959 }
960 }
961 }
962
963 return TRUE;
964}
965
966/*-----------------
967 * end of source
968 *-----------------
969 */
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.ico b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.ico
new file mode 100644
index 0000000..68aa371
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.ico
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.png b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.png
new file mode 100644
index 0000000..c6aa80a
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.png
Binary files differ
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.rc b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.rc
new file mode 100644
index 0000000..6e0623a
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/VisualPng.rc
@@ -0,0 +1,152 @@
1//Microsoft Developer Studio generated resource script.
2//
3#include "resource.h"
4
5#define APSTUDIO_READONLY_SYMBOLS
6/////////////////////////////////////////////////////////////////////////////
7//
8// Generated from the TEXTINCLUDE 2 resource.
9//
10#include "afxres.h"
11
12/////////////////////////////////////////////////////////////////////////////
13#undef APSTUDIO_READONLY_SYMBOLS
14
15/////////////////////////////////////////////////////////////////////////////
16// English (U.S.) resources
17
18#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19#ifdef _WIN32
20LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21#pragma code_page(1252)
22#endif //_WIN32
23
24#ifdef APSTUDIO_INVOKED
25/////////////////////////////////////////////////////////////////////////////
26//
27// TEXTINCLUDE
28//
29
301 TEXTINCLUDE DISCARDABLE
31BEGIN
32 "resource.h\0"
33END
34
352 TEXTINCLUDE DISCARDABLE
36BEGIN
37 "#include ""afxres.h""\r\n"
38 "\0"
39END
40
413 TEXTINCLUDE DISCARDABLE
42BEGIN
43 "\r\n"
44 "\0"
45END
46
47#endif // APSTUDIO_INVOKED
48
49
50/////////////////////////////////////////////////////////////////////////////
51//
52// Menu
53//
54
55VISUALPNG MENU DISCARDABLE
56BEGIN
57 POPUP "&File"
58 BEGIN
59 MENUITEM "&Open Image...\tCtrl+O", IDM_FILE_OPEN
60 MENUITEM "Save &As...", IDM_FILE_SAVE
61 MENUITEM SEPARATOR
62 MENUITEM "&Next Image\tCtrl+N", IDM_FILE_NEXT
63 MENUITEM "Pre&vious Image\tCtrl+V", IDM_FILE_PREVIOUS
64 MENUITEM SEPARATOR
65 MENUITEM "E&xit\tAlt+X", IDM_FILE_EXIT
66 END
67 POPUP "&Options"
68 BEGIN
69 MENUITEM "&Stretch", IDM_OPTIONS_STRETCH, CHECKED
70 END
71 POPUP "&Help"
72 BEGIN
73 MENUITEM "&About", IDM_HELP_ABOUT
74 END
75END
76
77
78/////////////////////////////////////////////////////////////////////////////
79//
80// Accelerator
81//
82
83VISUALPNG ACCELERATORS DISCARDABLE
84BEGIN
85 "N", IDM_FILE_NEXT, VIRTKEY, CONTROL, NOINVERT
86 "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
87 "P", IDM_FILE_PREVIOUS, VIRTKEY, CONTROL, NOINVERT
88 "V", IDM_FILE_PREVIOUS, VIRTKEY, CONTROL, NOINVERT
89 "X", IDM_FILE_EXIT, VIRTKEY, ALT, NOINVERT
90END
91
92
93/////////////////////////////////////////////////////////////////////////////
94//
95// Icon
96//
97
98// Icon with lowest ID value placed first to ensure application icon
99// remains consistent on all systems.
100VISUALPNG ICON DISCARDABLE "VisualPng.ico"
101
102/////////////////////////////////////////////////////////////////////////////
103//
104// Dialog
105//
106
107ABOUTBOX DIALOG DISCARDABLE 0, 0, 186, 94
108STYLE DS_MODALFRAME | WS_POPUP
109FONT 8, "MS Sans Serif"
110BEGIN
111 DEFPUSHBUTTON "OK",IDOK,68,67,50,14
112 CTEXT "VisualPng 1.0 - June 2000",IDC_STATIC,49,14,88,8
113 LTEXT "a PNG image viewer",IDC_STATIC,60,30,66,8
114 LTEXT "(c) Willem van Schaik, 2000",IDC_STATIC,48,52,90,8
115 LTEXT "to demonstrate the use of libpng in Visual C",
116 IDC_STATIC,25,38,136,8
117END
118
119
120/////////////////////////////////////////////////////////////////////////////
121//
122// DESIGNINFO
123//
124
125#ifdef APSTUDIO_INVOKED
126GUIDELINES DESIGNINFO DISCARDABLE
127BEGIN
128 "ABOUTBOX", DIALOG
129 BEGIN
130 LEFTMARGIN, 7
131 RIGHTMARGIN, 179
132 TOPMARGIN, 7
133 BOTTOMMARGIN, 87
134 END
135END
136#endif // APSTUDIO_INVOKED
137
138#endif // English (U.S.) resources
139/////////////////////////////////////////////////////////////////////////////
140
141
142
143#ifndef APSTUDIO_INVOKED
144/////////////////////////////////////////////////////////////////////////////
145//
146// Generated from the TEXTINCLUDE 3 resource.
147//
148
149
150/////////////////////////////////////////////////////////////////////////////
151#endif // not APSTUDIO_INVOKED
152
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/cexcept.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/cexcept.h
new file mode 100644
index 0000000..83c8bfe
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/cexcept.h
@@ -0,0 +1,248 @@
1/*===
2cexcept.h 2.0.1 (2008-Jul-19-Sat)
3http://www.nicemice.net/cexcept/
4Adam M. Costello
5http://www.nicemice.net/amc/
6
7An interface for exception-handling in ANSI C (C89 and subsequent ISO
8standards), developed jointly with Cosmin Truta.
9
10 Copyright (c) 2000-2008 Adam M. Costello and Cosmin Truta.
11 This software may be modified only if its author and version
12 information is updated accurately, and may be redistributed
13 only if accompanied by this unaltered notice. Subject to those
14 restrictions, permission is granted to anyone to do anything
15 with this software. The copyright holders make no guarantees
16 regarding this software, and are not responsible for any damage
17 resulting from its use.
18
19The cexcept interface is not compatible with and cannot interact
20with system exceptions (like division by zero or memory segmentation
21violation), compiler-generated exceptions (like C++ exceptions), or
22other exception-handling interfaces.
23
24When using this interface across multiple .c files, do not include
25this header file directly. Instead, create a wrapper header file that
26includes this header file and then invokes the define_exception_type
27macro (see below). The .c files should then include that header file.
28
29The interface consists of one type, one well-known name, and six macros.
30
31
32define_exception_type(type_name);
33
34 This macro is used like an external declaration. It specifies
35 the type of object that gets copied from the exception thrower to
36 the exception catcher. The type_name can be any type that can be
37 assigned to, that is, a non-constant arithmetic type, struct, union,
38 or pointer. Examples:
39
40 define_exception_type(int);
41
42 enum exception { out_of_memory, bad_arguments, disk_full };
43 define_exception_type(enum exception);
44
45 struct exception { int code; const char *msg; };
46 define_exception_type(struct exception);
47
48 Because throwing an exception causes the object to be copied (not
49 just once, but twice), programmers may wish to consider size when
50 choosing the exception type.
51
52
53struct exception_context;
54
55 This type may be used after the define_exception_type() macro has
56 been invoked. A struct exception_context must be known to both
57 the thrower and the catcher. It is expected that there be one
58 context for each thread that uses exceptions. It would certainly
59 be dangerous for multiple threads to access the same context.
60 One thread can use multiple contexts, but that is likely to be
61 confusing and not typically useful. The application can allocate
62 this structure in any way it pleases--automatic, static, or dynamic.
63 The application programmer should pretend not to know the structure
64 members, which are subject to change.
65
66
67struct exception_context *the_exception_context;
68
69 The Try/Catch and Throw statements (described below) implicitly
70 refer to a context, using the name the_exception_context. It is
71 the application's responsibility to make sure that this name yields
72 the address of a mutable (non-constant) struct exception_context
73 wherever those statements are used. Subject to that constraint, the
74 application may declare a variable of this name anywhere it likes
75 (inside a function, in a parameter list, or externally), and may
76 use whatever storage class specifiers (static, extern, etc) or type
77 qualifiers (const, volatile, etc) it likes. Examples:
78
79 static struct exception_context
80 * const the_exception_context = &foo;
81
82 { struct exception_context *the_exception_context = bar; ... }
83
84 int blah(struct exception_context *the_exception_context, ...);
85
86 extern struct exception_context the_exception_context[1];
87
88 The last example illustrates a trick that avoids creating a pointer
89 object separate from the structure object.
90
91 The name could even be a macro, for example:
92
93 struct exception_context ec_array[numthreads];
94 #define the_exception_context (ec_array + thread_id)
95
96 Be aware that the_exception_context is used several times by the
97 Try/Catch/Throw macros, so it shouldn't be expensive or have side
98 effects. The expansion must be a drop-in replacement for an
99 identifier, so it's safest to put parentheses around it.
100
101
102void init_exception_context(struct exception_context *ec);
103
104 For context structures allocated statically (by an external
105 definition or using the "static" keyword), the implicit
106 initialization to all zeros is sufficient, but contexts allocated
107 by other means must be initialized using this macro before they
108 are used by a Try/Catch statement. It does no harm to initialize
109 a context more than once (by using this macro on a statically
110 allocated context, or using this macro twice on the same context),
111 but a context must not be re-initialized after it has been used by a
112 Try/Catch statement.
113
114
115Try statement
116Catch (expression) statement
117
118 The Try/Catch/Throw macros are capitalized in order to avoid
119 confusion with the C++ keywords, which have subtly different
120 semantics.
121
122 A Try/Catch statement has a syntax similar to an if/else statement,
123 except that the parenthesized expression goes after the second
124 keyword rather than the first. As with if/else, there are two
125 clauses, each of which may be a simple statement ending with a
126 semicolon or a brace-enclosed compound statement. But whereas
127 the else clause is optional, the Catch clause is required. The
128 expression must be a modifiable lvalue (something capable of being
129 assigned to) of the same type (disregarding type qualifiers) that
130 was passed to define_exception_type().
131
132 If a Throw that uses the same exception context as the Try/Catch is
133 executed within the Try clause (typically within a function called
134 by the Try clause), and the exception is not caught by a nested
135 Try/Catch statement, then a copy of the exception will be assigned
136 to the expression, and control will jump to the Catch clause. If no
137 such Throw is executed, then the assignment is not performed, and
138 the Catch clause is not executed.
139
140 The expression is not evaluated unless and until the exception is
141 caught, which is significant if it has side effects, for example:
142
143 Try foo();
144 Catch (p[++i].e) { ... }
145
146 IMPORTANT: Jumping into or out of a Try clause (for example via
147 return, break, continue, goto, longjmp) is forbidden--the compiler
148 will not complain, but bad things will happen at run-time. Jumping
149 into or out of a Catch clause is okay, and so is jumping around
150 inside a Try clause. In many cases where one is tempted to return
151 from a Try clause, it will suffice to use Throw, and then return
152 from the Catch clause. Another option is to set a flag variable and
153 use goto to jump to the end of the Try clause, then check the flag
154 after the Try/Catch statement.
155
156 IMPORTANT: The values of any non-volatile automatic variables
157 changed within the Try clause are undefined after an exception is
158 caught. Therefore, variables modified inside the Try block whose
159 values are needed later outside the Try block must either use static
160 storage or be declared with the "volatile" type qualifier.
161
162
163Throw expression;
164
165 A Throw statement is very much like a return statement, except that
166 the expression is required. Whereas return jumps back to the place
167 where the current function was called, Throw jumps back to the Catch
168 clause of the innermost enclosing Try clause. The expression must
169 be compatible with the type passed to define_exception_type(). The
170 exception must be caught, otherwise the program may crash.
171
172 Slight limitation: If the expression is a comma-expression, it must
173 be enclosed in parentheses.
174
175
176Try statement
177Catch_anonymous statement
178
179 When the value of the exception is not needed, a Try/Catch statement
180 can use Catch_anonymous instead of Catch (expression).
181
182
183Everything below this point is for the benefit of the compiler. The
184application programmer should pretend not to know any of it, because it
185is subject to change.
186
187===*/
188
189
190#ifndef CEXCEPT_H
191#define CEXCEPT_H
192
193
194#include <setjmp.h>
195
196#define define_exception_type(etype) \
197struct exception_context { \
198 jmp_buf *penv; \
199 int caught; \
200 volatile struct { etype etmp; } v; \
201}
202
203/* etmp must be volatile because the application might use automatic */
204/* storage for the_exception_context, and etmp is modified between */
205/* the calls to setjmp() and longjmp(). A wrapper struct is used to */
206/* avoid warnings about a duplicate volatile qualifier in case etype */
207/* already includes it. */
208
209#define init_exception_context(ec) ((void)((ec)->penv = 0))
210
211#define Try \
212 { \
213 jmp_buf *exception__prev, exception__env; \
214 exception__prev = the_exception_context->penv; \
215 the_exception_context->penv = &exception__env; \
216 if (setjmp(exception__env) == 0) { \
217 do
218
219#define exception__catch(action) \
220 while (the_exception_context->caught = 0, \
221 the_exception_context->caught); \
222 } \
223 else { \
224 the_exception_context->caught = 1; \
225 } \
226 the_exception_context->penv = exception__prev; \
227 } \
228 if (!the_exception_context->caught || action) { } \
229 else
230
231#define Catch(e) exception__catch(((e) = the_exception_context->v.etmp, 0))
232#define Catch_anonymous exception__catch(0)
233
234/* Try ends with do, and Catch begins with while(0) and ends with */
235/* else, to ensure that Try/Catch syntax is similar to if/else */
236/* syntax. */
237/* */
238/* The 0 in while(0) is expressed as x=0,x in order to appease */
239/* compilers that warn about constant expressions inside while(). */
240/* Most compilers should still recognize that the condition is always */
241/* false and avoid generating code for it. */
242
243#define Throw \
244 for (;; longjmp(*the_exception_context->penv, 1)) \
245 the_exception_context->v.etmp =
246
247
248#endif /* CEXCEPT_H */
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/resource.h b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/resource.h
new file mode 100644
index 0000000..a06050a
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/visupng/resource.h
@@ -0,0 +1,23 @@
1//{{NO_DEPENDENCIES}}
2// Microsoft Developer Studio generated include file.
3// Used by VisualPng.rc
4//
5#define IDM_FILE_OPEN 40001
6#define IDM_FILE_SAVE 40002
7#define IDM_FILE_NEXT 40003
8#define IDM_FILE_PREVIOUS 40004
9#define IDM_FILE_EXIT 40005
10#define IDM_OPTIONS_BACKGROUND 40006
11#define IDM_OPTIONS_STRETCH 40007
12#define IDM_HELP_ABOUT 40008
13
14// Next default values for new objects
15//
16#ifdef APSTUDIO_INVOKED
17#ifndef APSTUDIO_READONLY_SYMBOLS
18#define _APS_NEXT_RESOURCE_VALUE 113
19#define _APS_NEXT_COMMAND_VALUE 40009
20#define _APS_NEXT_CONTROL_VALUE 1001
21#define _APS_NEXT_SYMED_VALUE 101
22#endif
23#endif