1 /*
2 LodePNG Unit Test
3 
4 Copyright (c) 2005-2020 Lode Vandevenne
5 
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9 
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
13 
14     1. The origin of this software must not be misrepresented; you must not
15     claim that you wrote the original software. If you use this software
16     in a product, an acknowledgment in the product documentation would be
17     appreciated but is not required.
18 
19     2. Altered source versions must be plainly marked as such, and must not be
20     misrepresented as being the original software.
21 
22     3. This notice may not be removed or altered from any source
23     distribution.
24 */
25 
26 //g++ lodepng.cpp lodepng_util.cpp lodepng_unittest.cpp -Wall -Wextra -Wsign-conversion -pedantic -ansi -O3
27 
28 /*
29 Testing instructions:
30 
31 *) Ensure no tests commented out below or early return in doMain
32 
33 *) Compile with g++ with all warnings and run the unit test
34 g++ lodepng.cpp lodepng_util.cpp lodepng_unittest.cpp -Werror -Wall -Wextra -Wsign-conversion -Wshadow -pedantic -ansi -O3 && ./a.out
35 
36 *) Compile with clang, which may sometimes give different warnings
37 clang++ lodepng.cpp lodepng_util.cpp lodepng_unittest.cpp -Werror -Wall -Wextra -Wsign-conversion -Wshadow -pedantic -ansi -O3
38 
39 *) Compile with pure ISO C90 and all warnings:
40 mv lodepng.cpp lodepng.c ; gcc -I ./ lodepng.c examples/example_decode.c -ansi -pedantic -Werror -Wall -Wextra -O3 ; mv lodepng.c lodepng.cpp
41 
42 mv lodepng.cpp lodepng.c ; clang -I ./ lodepng.c examples/example_decode.c -ansi -pedantic -Werror -Wall -Wextra -O3 ; mv lodepng.c lodepng.cpp
43 
44 *) Compile with C with -pedantic but not -ansi flag so it warns about // style comments in C++-only ifdefs
45 mv lodepng.cpp lodepng.c ; gcc -I ./ lodepng.c examples/example_decode.c -pedantic -Werror -Wall -Wextra -O3 ; mv lodepng.c lodepng.cpp
46 
47 *) try lodepng_benchmark.cpp
48 g++ lodepng.cpp lodepng_benchmark.cpp -Werror -Wall -Wextra -pedantic -ansi -lSDL -O3 && ./a.out testdata/corpus/''*
49 
50 *) try the fuzzer
51 clang++ -fsanitize=fuzzer -DLODEPNG_MAX_ALLOC=100000000 lodepng.cpp lodepng_fuzzer.cpp -O3 -o fuzzer && ./fuzzer
52 
53 clang++ -fsanitize=fuzzer,address,undefined -DLODEPNG_MAX_ALLOC=100000000 lodepng.cpp lodepng_fuzzer.cpp -O3 -o fuzzer && ./fuzzer
54 
55 *) Check if all C++ examples compile without warnings:
56 g++ -I ./ lodepng.cpp examples/''*.cpp -Werror -W -Wall -ansi -pedantic -O3 -c
57 
58 *) Check if all C examples compile without warnings:
59 mv lodepng.cpp lodepng.c ; gcc -I ./ lodepng.c examples/''*.c -Werror -W -Wall -ansi -pedantic -O3 -c ; mv lodepng.c lodepng.cpp
60 
61 *) Check pngdetail.cpp:
62 g++ lodepng.cpp lodepng_util.cpp pngdetail.cpp -Werror -W -Wall -ansi -pedantic -O3 -o pngdetail
63 ./pngdetail testdata/PngSuite/basi0g01.png
64 
65 *) Test compiling with some code sections with #defines disabled, for unused static function warnings etc...
66 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_ZLIB
67 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_PNG
68 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_DECODER
69 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_ENCODER
70 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_DISK
71 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
72 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_ERROR_TEXT
73 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_CPP
74 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_ZLIB -DLODEPNG_NO_COMPILE_DECODER
75 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_ZLIB -DLODEPNG_NO_COMPILE_ENCODER
76 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_PNG -DLODEPNG_NO_COMPILE_DECODER
77 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_PNG -DLODEPNG_NO_COMPILE_ENCODER
78 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_DECODER -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS -DLODEPNG_NO_COMPILE_ERROR_TEXT -DLODEPNG_NO_COMPILE_DISK
79 g++ lodepng.cpp -W -Wall -ansi -pedantic -O3 -c -DLODEPNG_NO_COMPILE_ENCODER -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS -DLODEPNG_NO_COMPILE_ERROR_TEXT -DLODEPNG_NO_COMPILE_DISK
80 rm *.o
81 
82 *) analyze with clang:
83 clang++ lodepng.cpp --analyze
84 
85 More verbose:
86 clang++ --analyze -Xanalyzer -analyzer-output=text lodepng.cpp
87 
88 Or html, look under lodepng.plist dir afterwards and find the numbered locations in the pages:
89 clang++ --analyze -Xanalyzer -analyzer-output=html lodepng.cpp
90 
91 *) check for memory leaks and vulnerabilities with valgrind
92 (DISABLE_SLOW disables a few tests that are very slow with valgrind)
93 g++ -DDISABLE_SLOW lodepng.cpp lodepng_util.cpp lodepng_unittest.cpp -Wall -Wextra -pedantic -ansi -O3 -DLODEPNG_MAX_ALLOC=100000000 && valgrind --leak-check=full --track-origins=yes ./a.out
94 
95 *) Try with clang++ and address sanitizer (to get line numbers, make sure 'llvm' is also installed to get 'llvm-symbolizer'
96 clang++ -O3 -fsanitize=address,undefined lodepng.cpp lodepng_util.cpp lodepng_unittest.cpp -Werror -Wall -Wextra -Wshadow -pedantic -ansi && ASAN_OPTIONS=allocator_may_return_null=1 ./a.out
97 
98 clang++ -g3 -fsanitize=address,undefined lodepng.cpp lodepng_util.cpp lodepng_unittest.cpp -Werror -Wall -Wextra -Wshadow -pedantic -ansi && ASAN_OPTIONS=allocator_may_return_null=1 ./a.out
99 
100 *) remove "#include <iostream>" from lodepng.cpp if it's still in there (some are legit)
101 cat lodepng.cpp lodepng_util.cpp | grep iostream
102 cat lodepng.cpp lodepng_util.cpp | grep stdio
103 cat lodepng.cpp lodepng_util.cpp | grep "#include"
104 
105 *) try the Makefile
106 make clean && make -j
107 
108 *) check that no plain "free", "malloc", "realloc", "strlen", "memcpy", ... used, but the lodepng_* versions instead
109 
110 *) check version dates in copyright message and LODEPNG_VERSION_STRING
111 
112 *) check year in copyright message at top of all files as well as at bottom of lodepng.h
113 
114 *) check examples/sdl.cpp with the png test suite images (the "x" ones are expected to show error)
115 g++ -I ./ lodepng.cpp examples/example_sdl.cpp -Werror -Wall -Wextra -pedantic -ansi -O3 -lSDL -o showpng && ./showpng testdata/PngSuite/''*.png
116 
117 *) strip trailing spaces and ensure consistent newlines
118 
119 *) check diff of lodepng.cpp and lodepng.h before submitting
120 git difftool -y
121 
122 */
123 
124 #include "lodepng.h"
125 #include "lodepng_util.h"
126 
127 #include <cmath>
128 #include <map>
129 #include <iomanip>
130 #include <iostream>
131 #include <sstream>
132 #include <string>
133 #include <vector>
134 
135 #include <stdio.h>
136 #include <stdlib.h>
137 
138 ////////////////////////////////////////////////////////////////////////////////
139 
fail()140 void fail() {
141   throw 1; //that's how to let a unittest fail
142 }
143 
144 //Utility for debug messages
145 template<typename T>
valtostr(const T & val)146 std::string valtostr(const T& val) {
147   std::ostringstream sstream;
148   sstream << val;
149   return sstream.str();
150 }
151 
152 //Print char as a numeric value rather than a character
153 template<>
valtostr(const unsigned char & val)154 std::string valtostr(const unsigned char& val) {
155   std::ostringstream sstream;
156   sstream << (int)val;
157   return sstream.str();
158 }
159 
160 //Print char pointer as pointer, not as string
161 template<typename T>
valtostr(const T * val)162 std::string valtostr(const T* val) {
163   std::ostringstream sstream;
164   sstream << (const void*)val;
165   return sstream.str();
166 }
167 
168 template<typename T>
valtostr(const std::vector<T> & val)169 std::string valtostr(const std::vector<T>& val) {
170   std::ostringstream sstream;
171   sstream << "[vector with size " << val.size() << "]";
172   return sstream.str();
173 }
174 
175 // TODO: remove, use only ASSERT_EQUALS (it prints line number). Requires adding extra message ability to ASSERT_EQUALS
176 template<typename T, typename U>
assertEquals(const T & expected,const U & actual,const std::string & message="")177 void assertEquals(const T& expected, const U& actual, const std::string& message = "") {
178   if(expected != (T)actual) {
179     std::cout << "Error: Not equal! Expected " << valtostr(expected)
180               << " got " << valtostr((T)actual) << ". "
181               << "Message: " << message << std::endl;
182     fail();
183   }
184 }
185 
186 // TODO: turn into ASSERT_TRUE with line number printed
assertTrue(bool value,const std::string & message="")187 void assertTrue(bool value, const std::string& message = "") {
188   if(!value) {
189     std::cout << "Error: expected true. " << "Message: " << message << std::endl;
190     fail();
191   }
192 }
193 
194 //assert that no error
assertNoPNGError(unsigned error,const std::string & message="")195 void assertNoPNGError(unsigned error, const std::string& message = "") {
196   if(error) {
197     std::string msg = (message == "") ? lodepng_error_text(error)
198                                       : message + std::string(": ") + lodepng_error_text(error);
199     assertEquals(0, error, msg);
200   }
201 }
202 
assertNoError(unsigned error)203 void assertNoError(unsigned error) {
204   if(error) {
205     assertEquals(0, error, "Expected no error");
206   }
207 }
208 
209 #define STR_EXPAND(s) #s
210 #define STR(s) STR_EXPAND(s)
211 #define ASSERT_EQUALS(e, v) {\
212   if((e) != (v)) {\
213     std::cout << std::string("line ") + STR(__LINE__) + ": " + STR(v) + " ASSERT_EQUALS failed: ";\
214     std::cout << "Expected " << valtostr(e) << " but got " << valtostr(v) << ". " << std::endl;\
215     fail();\
216   }\
217 }
218 #define ASSERT_NOT_EQUALS(e, v) {\
219   if((e) == (v)) {\
220     std::cout << std::string("line ") + STR(__LINE__) + ": " + STR(v) + " ASSERT_NOT_EQUALS failed: ";\
221     std::cout << "Expected not " << valtostr(e) << " but got " << valtostr(v) << ". " << std::endl;\
222     fail();\
223   }\
224 }
225 
226 template<typename T, typename U, typename V>
isNear(T e,U v,V maxdist)227 bool isNear(T e, U v, V maxdist) {
228   T dist = e > (T)v ? e - (T)v : (T)v - e;
229   return dist <= (T)maxdist;
230 }
231 
232 template<typename T, typename U>
233 T diff(T e, U v) {
234   return v > e ? v - e : e - v;
235 }
236 
237 #define ASSERT_NEAR(e, v, maxdist) {\
238   if(!isNear(e, v, maxdist)) {\
239     std::cout << std::string("line ") + STR(__LINE__) + ": " + STR(v) + " ASSERT_NEAR failed: ";\
240     std::cout << "dist too great! Expected near " << valtostr(e) << " but got " << valtostr(v) << ", with max dist " << valtostr(maxdist)\
241               << " but got dist " << valtostr(diff(e, v)) << ". " << std::endl;\
242     fail();\
243   }\
244 }
245 
246 #define ASSERT_STRING_EQUALS(e, v) ASSERT_EQUALS(std::string(e), std::string(v))
247 #define ASSERT_NO_PNG_ERROR_MSG(error, message) assertNoPNGError(error, std::string("line ") + STR(__LINE__) + (std::string(message).empty() ? std::string("") : (": " + std::string(message))))
248 #define ASSERT_NO_PNG_ERROR(error) ASSERT_NO_PNG_ERROR_MSG(error, std::string(""))
249 
250 static const std::string BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
251 
252 
253 
254 //T and U can be std::string or std::vector<unsigned char>
255 template<typename T, typename U>
toBase64(T & out,const U & in)256 void toBase64(T& out, const U& in) {
257   for(size_t i = 0; i < in.size(); i += 3) {
258     int v = 65536 * in[i];
259     if(i + 1 < in.size()) v += 256 * in[i + 1];
260     if(i + 2 < in.size()) v += in[i + 2];
261     out.push_back(BASE64[(v >> 18) & 0x3f]);
262     out.push_back(BASE64[(v >> 12) & 0x3f]);
263     if(i + 1 < in.size()) out.push_back(BASE64[(v >> 6) & 0x3f]);
264     else out.push_back('=');
265     if(i + 2 < in.size()) out.push_back(BASE64[(v >> 0) & 0x3f]);
266     else out.push_back('=');
267   }
268 }
269 
fromBase64(int v)270 int fromBase64(int v) {
271   if(v >= 'A' && v <= 'Z') return (v - 'A');
272   if(v >= 'a' && v <= 'z') return (v - 'a' + 26);
273   if(v >= '0' && v <= '9') return (v - '0' + 52);
274   if(v == '+') return 62;
275   if(v == '/') return 63;
276   return 0; //v == '='
277 }
278 
279 //T and U can be std::string or std::vector<unsigned char>
280 template<typename T, typename U>
fromBase64(T & out,const U & in)281 void fromBase64(T& out, const U& in) {
282   for(size_t i = 0; i + 3 < in.size(); i += 4) {
283     int v = 262144 * fromBase64(in[i]) + 4096 * fromBase64(in[i + 1]) + 64 * fromBase64(in[i + 2]) + fromBase64(in[i + 3]);
284     out.push_back((v >> 16) & 0xff);
285     if(in[i + 2] != '=') out.push_back((v >> 8) & 0xff);
286     if(in[i + 3] != '=') out.push_back((v >> 0) & 0xff);
287   }
288 }
289 
getRandom()290 unsigned getRandom() {
291   static unsigned s = 1000000000;
292   // xorshift32, good enough for testing
293   s ^= (s << 13);
294   s ^= (s >> 17);
295   s ^= (s << 5);
296   return s;
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 
301 
leftrotate(unsigned x,unsigned c)302 unsigned leftrotate(unsigned x, unsigned c) {
303   return (x << c) | (x >> (32u - c));
304 }
305 
306 // the 128-bit result is output in 4 32-bit integers a0..d0 (to make 16-byte digest: append a0|b0|c0|d0 in little endian)
md5sum(const unsigned char * in,size_t size,unsigned * a0,unsigned * b0,unsigned * c0,unsigned * d0)307 void md5sum(const unsigned char* in, size_t size, unsigned* a0, unsigned* b0, unsigned* c0, unsigned* d0) {
308   ASSERT_EQUALS(4, sizeof(unsigned));
309   // per-round shift amounts
310   static const unsigned s[64] = {
311     7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
312     4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
313   };
314   // precomputed table from sines
315   static const unsigned k[64] = {
316     0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
317     0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
318     0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
319     0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
320     0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
321     0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
322     0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
323     0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
324   };
325 
326   *a0 = 0x67452301;
327   *b0 = 0xefcdab89;
328   *c0 = 0x98badcfe;
329   *d0 = 0x10325476;
330 
331   // append bit, padding and size to input
332   std::vector<unsigned char> data(in, in + size);
333   data.resize(((size + 1 + 8 + 63) / 64) * 64, 0);
334   data[size] = 128; // append 1 bit (msb)
335   size_t bitsize = size * 8; // append the size (shifts > 31 are avoided)
336   data[data.size() - 1] = ((bitsize >> 28u) >> 28u) & 255u;
337   data[data.size() - 2] = ((bitsize >> 24u) >> 24u) & 255u;
338   data[data.size() - 3] = ((bitsize >> 20u) >> 20u) & 255u;
339   data[data.size() - 4] = ((bitsize >> 16u) >> 16u) & 255u;
340   data[data.size() - 5] = (bitsize >> 24u) & 255u;
341   data[data.size() - 6] = (bitsize >> 16u) & 255u;
342   data[data.size() - 7] = (bitsize >> 8u) & 255u;
343   data[data.size() - 8] = bitsize & 255u;
344 
345   // per chunk
346   for(size_t i = 0; i < data.size(); i += 64) {
347     unsigned a = *a0;
348     unsigned b = *b0;
349     unsigned c = *c0;
350     unsigned d = *d0;
351 
352     for(size_t j = 0; j < 64; j++) {
353       unsigned f, g;
354       if(j <= 15u) {
355         f = (b & c) | (~b & d);
356         g = j;
357       } else if(j <= 31u) {
358         f = (d & b) | (~d & c);
359         g = (5u * j + 1u) & 15u;
360       } else if(j <= 47u) {
361         f = b ^ c ^ d;
362         g = (3u * j + 5u) & 15u;
363       } else {
364         f = c ^ (b | ~d);
365         g = (7u * j) & 15u;
366       }
367       unsigned m = (unsigned)(data[i + g * 4 + 3] << 24u) | (unsigned)(data[i + g * 4 + 2] << 16u)
368                  | (unsigned)(data[i + g * 4 + 1] << 8u) | (unsigned)data[i + g * 4];
369       f += a + k[j] + m;
370       a = d;
371       d = c;
372       c = b;
373       b += leftrotate(f, s[j]);
374     }
375     *a0 += a;
376     *b0 += b;
377     *c0 += c;
378     *d0 += d;
379   }
380 }
381 
md5sum(const std::vector<unsigned char> & in)382 std::string md5sum(const std::vector<unsigned char>& in) {
383   unsigned a0, b0, c0, d0;
384   md5sum(in.data(), in.size(), &a0, &b0, &c0, &d0);
385   char result[33];
386   //sprintf(result, "%8.8x%8.8x%8.8x%8.8x", a0, b0, c0, d0);
387   sprintf(result, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
388           a0 & 255, (a0 >> 8) & 255, (a0 >> 16) & 255, (a0 >> 24) & 255,
389           b0 & 255, (b0 >> 8) & 255, (b0 >> 16) & 255, (b0 >> 24) & 255,
390           c0 & 255, (c0 >> 8) & 255, (c0 >> 16) & 255, (c0 >> 24) & 255,
391           d0 & 255, (d0 >> 8) & 255, (d0 >> 16) & 255, (d0 >> 24) & 255);
392   return std::string(result);
393 }
394 
395 ////////////////////////////////////////////////////////////////////////////////
396 
397 //Test image data
398 struct Image {
399   std::vector<unsigned char> data;
400   unsigned width;
401   unsigned height;
402   LodePNGColorType colorType;
403   unsigned bitDepth;
404 };
405 
406 //Get number of color channels for a given PNG color type
getNumColorChannels(unsigned colorType)407 unsigned getNumColorChannels(unsigned colorType) {
408   switch(colorType) {
409     case 0: return 1; /*gray*/
410     case 2: return 3; /*RGB*/
411     case 3: return 1; /*palette*/
412     case 4: return 2; /*gray + alpha*/
413     case 6: return 4; /*RGBA*/
414   }
415   return 0; /*unexisting color type*/
416 }
417 
418 //Generate a test image with some data in it, the contents of the data is unspecified,
419 //except the content is not just one plain color, and not true random either to be compressible.
generateTestImage(Image & image,unsigned width,unsigned height,LodePNGColorType colorType=LCT_RGBA,unsigned bitDepth=8)420 void generateTestImage(Image& image, unsigned width, unsigned height, LodePNGColorType colorType = LCT_RGBA, unsigned bitDepth = 8) {
421   image.width = width;
422   image.height = height;
423   image.colorType = colorType;
424   image.bitDepth = bitDepth;
425 
426   size_t bits = bitDepth * getNumColorChannels(colorType); //bits per pixel
427   size_t size = (width * height * bits + 7) / 8; //total image size in bytes
428   image.data.resize(size);
429   unsigned char value = 128;
430   for(size_t i = 0; i < size; i++) {
431     image.data[i] = value++;
432   }
433 }
434 
435 //Generate a 16-bit test image with minimal size that requires at minimum the given color type (bit depth, grayscaleness, ...)
436 //If key is true, makes it such that exactly one color is transparent, so it can use a key. If false, adds a translucent color depending on
437 //whether it's an alpha color type or not.
generateTestImageRequiringColorType16(Image & image,LodePNGColorType colorType,unsigned bitDepth,bool key)438 void generateTestImageRequiringColorType16(Image& image, LodePNGColorType colorType, unsigned bitDepth, bool key) {
439   image.colorType = colorType;
440   image.bitDepth = bitDepth;
441   unsigned w = 1;
442   unsigned h = 1;
443 
444   bool gray = colorType == LCT_GREY || colorType == LCT_GREY_ALPHA;
445   bool alpha = colorType == LCT_RGBA || colorType == LCT_GREY_ALPHA;
446 
447   if(colorType == LCT_PALETTE) {
448     w = 1u << bitDepth;
449     h = 256; // ensure it'll really choose palette, not omit it due to small image size
450     image.data.resize(w * h * 8);
451     for(size_t y = 0; y < h; y++) {
452       for(size_t x = 0; x < w; x++) {
453         size_t i = y * w * 8 + x * 8;
454         image.data[i + 0] = image.data[i + 1] = y;
455         image.data[i + 2] = image.data[i + 3] = 255;
456         image.data[i + 4] = image.data[i + 5] = 0;
457         image.data[i + 6] = image.data[i + 7] = (key && y == 0) ? 0 : 255;
458       }
459     }
460   } else if(bitDepth == 16) {
461     // one color suffices for this model. But add one more to support key.
462     w = 2;
463     image.data.resize(w * h * 8);
464     image.data[0] = 10; image.data[1] = 20;
465     image.data[2] = 10; image.data[3] = 20;
466     image.data[4] = gray ? 10 : 110; image.data[5] = gray ? 20 : 120;
467     image.data[6] = alpha ? 128 : 255; image.data[7] = alpha ? 20 : 255;
468 
469     image.data[8] = 40; image.data[9] = 50;
470     image.data[10] = 40; image.data[11] = 50;
471     image.data[12] = gray ? 40 : 140; image.data[13] = gray ? 50 : 150;
472     image.data[14] = key ? 0 : 255; image.data[15] = key ? 0 : 255;
473   } else if(gray) {
474     w = 2;
475     unsigned v = 255u / ((1u << bitDepth) - 1u); // value that forces at least this bitdepth
476     image.data.resize(w * h * 8);
477     image.data[0] = v; image.data[1] = v;
478     image.data[2] = v; image.data[3] = v;
479     image.data[4] = v; image.data[5] = v;
480     image.data[6] = alpha ? v : 255; image.data[7] = alpha ? v : 255;
481 
482     image.data[8] = image.data[9] = 0;
483     image.data[10] = image.data[11] = 0;
484     image.data[12] = image.data[13] = 0;
485     image.data[14] = image.data[15] = key ? 0 : 255;
486   } else {
487     // now it's RGB or RGBA with bitdepth 8
488     w = 257; // must have at least more than 256 colors so it won't use palette
489     image.data.resize(w * h * 8);
490     for(size_t y = 0; y < h; y++) {
491       for(size_t x = 0; x < w; x++) {
492         size_t i = y * w * 8 + x * 8;
493         image.data[i + 0] = image.data[i + 1] = i / 2;
494         image.data[i + 2] = image.data[i + 3] = i / 3;
495         image.data[i + 4] = image.data[i + 5] = i / 5;
496         image.data[i + 6] = image.data[i + 7] = (key && y == 0) ? 0 : (alpha ? i : 255);
497       }
498     }
499   }
500 
501   image.width = w;
502   image.height = h;
503 }
504 
505 //Generate a 8-bit test image with minimal size that requires at minimum the given color type (bit depth, grayscaleness, ...). bitDepth max 8 here.
506 //If key is true, makes it such that exactly one color is transparent, so it can use a key. If false, adds a translucent color depending on
507 //whether it's an alpha color type or not.
generateTestImageRequiringColorType8(Image & image,LodePNGColorType colorType,unsigned bitDepth,bool key)508 void generateTestImageRequiringColorType8(Image& image, LodePNGColorType colorType, unsigned bitDepth, bool key) {
509   image.colorType = colorType;
510   image.bitDepth = bitDepth;
511   unsigned w = 1;
512   unsigned h = 1;
513 
514   bool gray = colorType == LCT_GREY || colorType == LCT_GREY_ALPHA;
515   bool alpha = colorType == LCT_RGBA || colorType == LCT_GREY_ALPHA;
516 
517   if(colorType == LCT_PALETTE) {
518     w = 1u << bitDepth;
519     h = 256; // ensure it'll really choose palette, not omit it due to small image size
520     image.data.resize(w * h * 4);
521     for(size_t y = 0; y < h; y++) {
522       for(size_t x = 0; x < w; x++) {
523         size_t i = y * w * 4 + x * 4;
524         image.data[i + 0] = x;
525         image.data[i + 1] = 255;
526         image.data[i + 2] = 0;
527         image.data[i + 3] = (key && x == 0) ? 0 : 255;
528       }
529     }
530   } else if(gray) {
531     w = 2;
532     unsigned v = 255u / ((1u << bitDepth) - 1u); // value that forces at least this bitdepth
533     image.data.resize(w * h * 4);
534     image.data[0] = v;
535     image.data[1] = v;
536     image.data[2] = v;
537     image.data[3] = alpha ? v : 255;
538 
539     image.data[4] = 0;
540     image.data[5] = 0;
541     image.data[6] = 0;
542     image.data[7] = key ? 0 : 255;
543   } else {
544     // now it's RGB or RGBA with bitdepth 8
545     w = 257; // must have at least more than 256 colors so it won't use palette
546     image.data.resize(w * h * 4);
547     for(size_t y = 0; y < h; y++) {
548       for(size_t x = 0; x < w; x++) {
549         size_t i = y * w * 4 + x * 4;
550         image.data[i + 0] = i / 2;
551         image.data[i + 1] = i / 3;
552         image.data[i + 2] = i / 5;
553         image.data[i + 3] = (key && x == 0) ? 0 : (alpha ? i : 255);
554       }
555     }
556   }
557 
558   image.width = w;
559   image.height = h;
560 }
561 
562 //Check that the decoded PNG pixels are the same as the pixels in the image
assertPixels(Image & image,const unsigned char * decoded,const std::string & message)563 void assertPixels(Image& image, const unsigned char* decoded, const std::string& message) {
564   for(size_t i = 0; i < image.data.size(); i++) {
565     int byte_expected = image.data[i];
566     int byte_actual = decoded[i];
567 
568     //last byte is special due to possible random padding bits which need not to be equal
569     if(i == image.data.size() - 1) {
570       size_t numbits = getNumColorChannels(image.colorType) * image.bitDepth * image.width * image.height;
571       size_t padding = 8u - (numbits - 8u * (numbits / 8u));
572       if(padding != 8u) {
573         //set all padding bits of both to 0
574         for(size_t j = 0; j < padding; j++) {
575           byte_expected = (byte_expected & (~(1 << j))) % 256;
576           byte_actual = (byte_actual & (~(1 << j))) % 256;
577         }
578       }
579     }
580 
581     assertEquals(byte_expected, byte_actual, message + " " + valtostr(i));
582   }
583 }
584 
585 //Test LodePNG encoding and decoding the encoded result, using the C interface
doCodecTestC(Image & image)586 void doCodecTestC(Image& image) {
587   unsigned char* encoded = 0;
588   size_t encoded_size = 0;
589   unsigned char* decoded = 0;
590   unsigned decoded_w;
591   unsigned decoded_h;
592 
593   struct OnExitScope {
594     unsigned char** a;
595     unsigned char** b;
596     OnExitScope(unsigned char** ca, unsigned char** cb) : a(ca), b(cb) {}
597     ~OnExitScope() { free(*a); free(*b); }
598   } onExitScope(&encoded, &decoded);
599 
600   unsigned error_enc = lodepng_encode_memory(&encoded, &encoded_size, &image.data[0],
601                                              image.width, image.height, image.colorType, image.bitDepth);
602 
603   if(error_enc != 0) std::cout << "Error: " << lodepng_error_text(error_enc) << std::endl;
604   ASSERT_NO_PNG_ERROR_MSG(error_enc, "encoder error C");
605 
606   //if the image is large enough, compressing it should result in smaller size
607   if(image.data.size() > 512) assertTrue(encoded_size < image.data.size(), "compressed size");
608 
609   unsigned error_dec = lodepng_decode_memory(&decoded, &decoded_w, &decoded_h,
610                                              encoded, encoded_size, image.colorType, image.bitDepth);
611 
612   if(error_dec != 0) std::cout << "Error: " << lodepng_error_text(error_dec) << std::endl;
613   ASSERT_NO_PNG_ERROR_MSG(error_dec, "decoder error C");
614 
615   ASSERT_EQUALS(image.width, decoded_w);
616   ASSERT_EQUALS(image.height, decoded_h);
617   assertPixels(image, decoded, "Pixels C");
618 }
619 
620 //Test LodePNG encoding and decoding the encoded result, using the C++ interface
doCodecTestCPP(Image & image)621 void doCodecTestCPP(Image& image) {
622   std::vector<unsigned char> encoded;
623   std::vector<unsigned char> decoded;
624   unsigned decoded_w;
625   unsigned decoded_h;
626 
627   unsigned error_enc = lodepng::encode(encoded, image.data, image.width, image.height,
628                                        image.colorType, image.bitDepth);
629 
630   ASSERT_NO_PNG_ERROR_MSG(error_enc, "encoder error C++");
631 
632   //if the image is large enough, compressing it should result in smaller size
633   if(image.data.size() > 512) assertTrue(encoded.size() < image.data.size(), "compressed size");
634 
635   unsigned error_dec = lodepng::decode(decoded, decoded_w, decoded_h, encoded, image.colorType, image.bitDepth);
636 
637   ASSERT_NO_PNG_ERROR_MSG(error_dec, "decoder error C++");
638 
639   ASSERT_EQUALS(image.width, decoded_w);
640   ASSERT_EQUALS(image.height, decoded_h);
641   ASSERT_EQUALS(image.data.size(), decoded.size());
642   assertPixels(image, &decoded[0], "Pixels C++");
643 }
644 
645 
doCodecTestWithEncState(Image & image,lodepng::State & state)646 void doCodecTestWithEncState(Image& image, lodepng::State& state) {
647   std::vector<unsigned char> encoded;
648   std::vector<unsigned char> decoded;
649   unsigned decoded_w;
650   unsigned decoded_h;
651   state.info_raw.colortype = image.colorType;
652   state.info_raw.bitdepth = image.bitDepth;
653 
654 
655   unsigned error_enc = lodepng::encode(encoded, image.data, image.width, image.height, state);
656   ASSERT_NO_PNG_ERROR_MSG(error_enc, "encoder error uncompressed");
657 
658   unsigned error_dec = lodepng::decode(decoded, decoded_w, decoded_h, encoded, image.colorType, image.bitDepth);
659 
660   ASSERT_NO_PNG_ERROR_MSG(error_dec, "decoder error uncompressed");
661 
662   ASSERT_EQUALS(image.width, decoded_w);
663   ASSERT_EQUALS(image.height, decoded_h);
664   ASSERT_EQUALS(image.data.size(), decoded.size());
665   assertPixels(image, &decoded[0], "Pixels uncompressed");
666 }
667 
668 
669 //Test LodePNG encoding and decoding the encoded result, using the C++ interface
doCodecTestUncompressed(Image & image)670 void doCodecTestUncompressed(Image& image) {
671   lodepng::State state;
672   state.encoder.zlibsettings.btype = 0;
673   doCodecTestWithEncState(image, state);
674 }
675 
doCodecTestNoLZ77(Image & image)676 void doCodecTestNoLZ77(Image& image) {
677   lodepng::State state;
678   state.encoder.zlibsettings.use_lz77 = 0;
679   doCodecTestWithEncState(image, state);
680 }
681 
testGetFilterTypes()682 void testGetFilterTypes() {
683   std::cout << "testGetFilterTypes" << std::endl;
684   // Test that getFilterTypes works on the special case of 1-pixel wide interlaced image
685   std::string png64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAHCAIAAAExKYBVAAAAHUlEQVR4ASXHAQoAAAjCwPX/R9tK4ZBN4EHKcPcLXCgGAQa0TV8AAAAASUVORK5CYII=";
686   std::vector<unsigned char> png;
687   fromBase64(png, png64);
688   std::vector<unsigned char> types;
689   lodepng::getFilterTypes(types, png);
690   ASSERT_EQUALS(7, types.size());
691   ASSERT_EQUALS(1, types[0]);
692   ASSERT_EQUALS(1, types[1]);
693   ASSERT_EQUALS(1, types[2]);
694   ASSERT_EQUALS(0, types[3]);
695   ASSERT_EQUALS(1, types[4]);
696   ASSERT_EQUALS(1, types[5]);
697   ASSERT_EQUALS(1, types[6]);
698 }
699 
700 //Test LodePNG encoding and decoding the encoded result, using the C++ interface, with interlace
doCodecTestInterlaced(Image & image)701 void doCodecTestInterlaced(Image& image) {
702   std::vector<unsigned char> encoded;
703   std::vector<unsigned char> decoded;
704   unsigned decoded_w;
705   unsigned decoded_h;
706 
707   lodepng::State state;
708   state.info_png.interlace_method = 1;
709   state.info_raw.colortype = image.colorType;
710   state.info_raw.bitdepth = image.bitDepth;
711 
712   unsigned error_enc = lodepng::encode(encoded, image.data, image.width, image.height, state);
713 
714   ASSERT_NO_PNG_ERROR_MSG(error_enc, "encoder error interlaced");
715 
716   //if the image is large enough, compressing it should result in smaller size
717   if(image.data.size() > 512) assertTrue(encoded.size() < image.data.size(), "compressed size");
718 
719   state.info_raw.colortype = image.colorType;
720   state.info_raw.bitdepth = image.bitDepth;
721   unsigned error_dec = lodepng::decode(decoded, decoded_w, decoded_h, state, encoded);
722 
723   ASSERT_NO_PNG_ERROR_MSG(error_dec, "decoder error interlaced");
724 
725   ASSERT_EQUALS(image.width, decoded_w);
726   ASSERT_EQUALS(image.height, decoded_h);
727   ASSERT_EQUALS(image.data.size(), decoded.size());
728   assertPixels(image, &decoded[0], "Pixels interlaced");
729 }
730 
731 //Test LodePNG encoding and decoding the encoded result
doCodecTest(Image & image)732 void doCodecTest(Image& image) {
733   doCodecTestC(image);
734   doCodecTestCPP(image);
735   doCodecTestInterlaced(image);
736   doCodecTestUncompressed(image);
737   doCodecTestNoLZ77(image);
738 }
739 
740 
741 //Test LodePNG encoding and decoding using some image generated with the given parameters
codecTest(unsigned width,unsigned height,LodePNGColorType colorType=LCT_RGBA,unsigned bitDepth=8)742 void codecTest(unsigned width, unsigned height, LodePNGColorType colorType = LCT_RGBA, unsigned bitDepth = 8) {
743   std::cout << "codec test " << width << " " << height << std::endl;
744   Image image;
745   generateTestImage(image, width, height, colorType, bitDepth);
746   doCodecTest(image);
747 }
748 
removeSpaces(const std::string & s)749 std::string removeSpaces(const std::string& s) {
750   std::string result;
751   for(size_t i = 0; i < s.size(); i++) if(s[i] != ' ') result += s[i];
752   return result;
753 }
754 
bitStringToBytes(std::vector<unsigned char> & bytes,const std::string & bits_)755 void bitStringToBytes(std::vector<unsigned char>& bytes, const std::string& bits_) {
756   std::string bits = removeSpaces(bits_);
757   bytes.resize((bits.size()) + 7 / 8);
758   for(size_t i = 0; i < bits.size(); i++) {
759     size_t j = i / 8;
760     size_t k = i % 8;
761     char c = bits[i];
762     if(k == 0) bytes[j] = 0;
763     if(c == '1') bytes[j] |= (1 << (7 - k));
764   }
765 }
766 
767 /*
768 test color convert on a single pixel. Testing palette and testing color keys is
769 not supported by this function. Pixel values given using bits in an std::string
770 of 0's and 1's.
771 */
colorConvertTest(const std::string & bits_in,LodePNGColorType colorType_in,unsigned bitDepth_in,const std::string & bits_out,LodePNGColorType colorType_out,unsigned bitDepth_out)772 void colorConvertTest(const std::string& bits_in, LodePNGColorType colorType_in, unsigned bitDepth_in,
773                       const std::string& bits_out, LodePNGColorType colorType_out, unsigned bitDepth_out) {
774   std::cout << "color convert test " << bits_in << " - " << bits_out << std::endl;
775 
776   std::vector<unsigned char> expected, actual, image;
777   bitStringToBytes(expected, bits_out);
778   actual.resize(expected.size());
779   bitStringToBytes(image, bits_in);
780   LodePNGColorMode mode_in, mode_out;
781   lodepng_color_mode_init(&mode_in);
782   lodepng_color_mode_init(&mode_out);
783   mode_in.colortype = colorType_in;
784   mode_in.bitdepth = bitDepth_in;
785   mode_out.colortype = colorType_out;
786   mode_out.bitdepth = bitDepth_out;
787   unsigned error = lodepng_convert(&actual[0], &image[0], &mode_out, &mode_in, 1, 1);
788 
789   ASSERT_NO_PNG_ERROR_MSG(error, "convert error");
790 
791   for(size_t i = 0; i < expected.size(); i++) {
792     assertEquals((int)expected[i], (int)actual[i], "byte " + valtostr(i));
793   }
794 
795   lodepng_color_mode_cleanup(&mode_in);
796   lodepng_color_mode_cleanup(&mode_out);
797 }
798 
testOtherPattern1()799 void testOtherPattern1() {
800   std::cout << "codec other pattern 1" << std::endl;
801 
802   Image image1;
803   size_t w = 192;
804   size_t h = 192;
805   image1.width = w;
806   image1.height = h;
807   image1.colorType = LCT_RGBA;
808   image1.bitDepth = 8;
809   image1.data.resize(w * h * 4u);
810   for(size_t y = 0; y < h; y++)
811   for(size_t x = 0; x < w; x++) {
812     //pattern 1
813     image1.data[4u * w * y + 4u * x + 0u] = (unsigned char)(127 * (1 + std::sin((                    x * x +                     y * y) / (w * h / 8.0))));
814     image1.data[4u * w * y + 4u * x + 1u] = (unsigned char)(127 * (1 + std::sin(((w - x - 1) * (w - x - 1) +                     y * y) / (w * h / 8.0))));
815     image1.data[4u * w * y + 4u * x + 2u] = (unsigned char)(127 * (1 + std::sin((                    x * x + (h - y - 1) * (h - y - 1)) / (w * h / 8.0))));
816     image1.data[4u * w * y + 4u * x + 3u] = (unsigned char)(127 * (1 + std::sin(((w - x - 1) * (w - x - 1) + (h - y - 1) * (h - y - 1)) / (w * h / 8.0))));
817   }
818 
819   doCodecTest(image1);
820 }
821 
testOtherPattern2()822 void testOtherPattern2() {
823   std::cout << "codec other pattern 2" << std::endl;
824 
825   Image image1;
826   size_t w = 192;
827   size_t h = 192;
828   image1.width = w;
829   image1.height = h;
830   image1.colorType = LCT_RGBA;
831   image1.bitDepth = 8;
832   image1.data.resize(w * h * 4u);
833   for(size_t y = 0; y < h; y++)
834   for(size_t x = 0; x < w; x++) {
835     image1.data[4u * w * y + 4u * x + 0u] = 255 * !(x & y);
836     image1.data[4u * w * y + 4u * x + 1u] = x ^ y;
837     image1.data[4u * w * y + 4u * x + 2u] = x | y;
838     image1.data[4u * w * y + 4u * x + 3u] = 255;
839   }
840 
841   doCodecTest(image1);
842 }
843 
testSinglePixel(int r,int g,int b,int a)844 void testSinglePixel(int r, int g, int b, int a) {
845   std::cout << "codec single pixel " << r << " " << g << " " << b << " " << a << std::endl;
846   Image pixel;
847   pixel.width = 1;
848   pixel.height = 1;
849   pixel.colorType = LCT_RGBA;
850   pixel.bitDepth = 8;
851   pixel.data.resize(4);
852   pixel.data[0] = r;
853   pixel.data[1] = g;
854   pixel.data[2] = b;
855   pixel.data[3] = a;
856 
857   doCodecTest(pixel);
858 }
859 
testColor(int r,int g,int b,int a)860 void testColor(int r, int g, int b, int a) {
861   std::cout << "codec test color " << r << " " << g << " " << b << " " << a << std::endl;
862   Image image;
863   image.width = 20;
864   image.height = 20;
865   image.colorType = LCT_RGBA;
866   image.bitDepth = 8;
867   image.data.resize(20 * 20 * 4);
868   for(size_t y = 0; y < 20; y++)
869   for(size_t x = 0; x < 20; x++) {
870     image.data[20 * 4 * y + 4 * x + 0] = r;
871     image.data[20 * 4 * y + 4 * x + 0] = g;
872     image.data[20 * 4 * y + 4 * x + 0] = b;
873     image.data[20 * 4 * y + 4 * x + 0] = a;
874   }
875 
876   doCodecTest(image);
877 
878   Image image2 = image;
879   image2.data[3] = 0; //one fully transparent pixel
880   doCodecTest(image2);
881   image2.data[3] = 128; //one semi transparent pixel
882   doCodecTest(image2);
883 
884   Image image3 = image;
885   // add 255 different colors
886   for(size_t i = 0; i < 255; i++) {
887     image.data[i * 4 + 0] = i;
888     image.data[i * 4 + 1] = i;
889     image.data[i * 4 + 2] = i;
890     image.data[i * 4 + 3] = 255;
891   }
892   doCodecTest(image3);
893   // a 256th color
894   image.data[255 * 4 + 0] = 255;
895   image.data[255 * 4 + 1] = 255;
896   image.data[255 * 4 + 2] = 255;
897   image.data[255 * 4 + 3] = 255;
898   doCodecTest(image3);
899 
900   testSinglePixel(r, g, b, a);
901 }
902 
903 // Tests combinations of various colors in different orders
testFewColors()904 void testFewColors() {
905   std::cout << "codec test few colors " << std::endl;
906   Image image;
907   image.width = 4;
908   image.height = 4;
909   image.colorType = LCT_RGBA;
910   image.bitDepth = 8;
911   image.data.resize(image.width * image.height * 4);
912   std::vector<unsigned char> colors;
913   colors.push_back(0); colors.push_back(0); colors.push_back(0); colors.push_back(255); // black
914   colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(255); // white
915   colors.push_back(128); colors.push_back(128); colors.push_back(128); colors.push_back(255); // gray
916   colors.push_back(0); colors.push_back(0); colors.push_back(255); colors.push_back(255); // blue
917   colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(0); // transparent white
918   colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(1); // translucent white
919   for(size_t i = 0; i < colors.size(); i += 4)
920   for(size_t j = 0; j < colors.size(); j += 4)
921   for(size_t k = 0; k < colors.size(); k += 4)
922   for(size_t l = 0; l < colors.size(); l += 4) {
923     for(unsigned y = 0; y < image.height; y++)
924     for(unsigned x = 0; x < image.width; x++) {
925       size_t a = (y * image.width + x) & 3;
926       size_t b = (a == 0) ? i : ((a == 1) ? j : ((a == 2) ? k : l));
927       for(size_t c = 0; c < 4; c++) {
928         image.data[y * image.width * 4 + x * 4 + c] = colors[b + c];
929       }
930     }
931     doCodecTest(image);
932   }
933   image.width = 20;
934   image.height = 20;
935   image.data.resize(image.width * image.height * 4);
936   for(size_t i = 0; i < colors.size(); i += 4)
937   for(size_t j = 0; j < colors.size(); j += 4)
938   for(size_t k = 0; k < colors.size(); k += 4) {
939     for(unsigned y = 0; y < image.height; y++)
940     for(unsigned x = 0; x < image.width; x++) {
941       size_t a = (y * image.width + x) % 3;
942       size_t b = (a == 0) ? i : ((a == 1) ? j : k);
943       for(size_t c = 0; c < 4; c++) {
944         image.data[y * image.width * 4 + x * 4 + c] = colors[b + c];
945       }
946     }
947     doCodecTest(image);
948   }
949 }
950 
testSize(unsigned w,unsigned h)951 void testSize(unsigned w, unsigned h) {
952   std::cout << "codec test size " << w << " " << h << std::endl;
953   Image image;
954   image.width = w;
955   image.height = h;
956   image.colorType = LCT_RGBA;
957   image.bitDepth = 8;
958   image.data.resize(w * h * 4);
959   for(size_t y = 0; y < h; y++)
960   for(size_t x = 0; x < w; x++) {
961     image.data[w * 4 * y + 4 * x + 0] = x % 256;
962     image.data[w * 4 * y + 4 * x + 0] = y % 256;
963     image.data[w * 4 * y + 4 * x + 0] = 255;
964     image.data[w * 4 * y + 4 * x + 0] = 255;
965   }
966 
967   doCodecTest(image);
968 }
969 
testPNGCodec()970 void testPNGCodec() {
971   codecTest(1, 1);
972   codecTest(2, 2);
973   codecTest(1, 1, LCT_GREY, 1);
974   codecTest(7, 7, LCT_GREY, 1);
975 #ifndef DISABLE_SLOW
976   codecTest(127, 127);
977   codecTest(127, 127, LCT_GREY, 1);
978   codecTest(320, 320);
979   codecTest(1, 10000);
980   codecTest(10000, 1);
981 
982   testOtherPattern1();
983   testOtherPattern2();
984 #endif // DISABLE_SLOW
985 
986   testColor(255, 255, 255, 255);
987   testColor(0, 0, 0, 255);
988   testColor(1, 2, 3, 255);
989   testColor(255, 0, 0, 255);
990   testColor(0, 255, 0, 255);
991   testColor(0, 0, 255, 255);
992   testColor(0, 0, 0, 255);
993   testColor(1, 1, 1, 255);
994   testColor(1, 1, 1, 1);
995   testColor(0, 0, 0, 128);
996   testColor(255, 0, 0, 128);
997   testColor(127, 127, 127, 255);
998   testColor(128, 128, 128, 255);
999   testColor(127, 127, 127, 128);
1000   testColor(128, 128, 128, 128);
1001   //transparent single pixels
1002   testColor(0, 0, 0, 0);
1003   testColor(255, 0, 0, 0);
1004   testColor(1, 2, 3, 0);
1005   testColor(255, 255, 255, 0);
1006   testColor(254, 254, 254, 0);
1007 
1008   // This is mainly to test the Adam7 interlacing
1009   for(unsigned h = 1; h < 12; h++)
1010   for(unsigned w = 1; w < 12; w++) {
1011     testSize(w, h);
1012   }
1013 }
1014 
1015 //Tests some specific color conversions with specific color bit combinations
testColorConvert()1016 void testColorConvert() {
1017   //test color conversions to RGBA8
1018   colorConvertTest("1", LCT_GREY, 1, "11111111 11111111 11111111 11111111", LCT_RGBA, 8);
1019   colorConvertTest("10", LCT_GREY, 2, "10101010 10101010 10101010 11111111", LCT_RGBA, 8);
1020   colorConvertTest("1001", LCT_GREY, 4, "10011001 10011001 10011001 11111111", LCT_RGBA, 8);
1021   colorConvertTest("10010101", LCT_GREY, 8, "10010101 10010101 10010101 11111111", LCT_RGBA, 8);
1022   colorConvertTest("10010101 11111110", LCT_GREY_ALPHA, 8, "10010101 10010101 10010101 11111110", LCT_RGBA, 8);
1023   colorConvertTest("10010101 00000001 11111110 00000001", LCT_GREY_ALPHA, 16, "10010101 10010101 10010101 11111110", LCT_RGBA, 8);
1024   colorConvertTest("01010101 00000000 00110011", LCT_RGB, 8, "01010101 00000000 00110011 11111111", LCT_RGBA, 8);
1025   colorConvertTest("01010101 00000000 00110011 10101010", LCT_RGBA, 8, "01010101 00000000 00110011 10101010", LCT_RGBA, 8);
1026   colorConvertTest("10101010 01010101 11111111 00000000 11001100 00110011", LCT_RGB, 16, "10101010 11111111 11001100 11111111", LCT_RGBA, 8);
1027   colorConvertTest("10101010 01010101 11111111 00000000 11001100 00110011 11100111 00011000", LCT_RGBA, 16, "10101010 11111111 11001100 11100111", LCT_RGBA, 8);
1028 
1029   //test color conversions to RGB8
1030   colorConvertTest("1", LCT_GREY, 1, "11111111 11111111 11111111", LCT_RGB, 8);
1031   colorConvertTest("10", LCT_GREY, 2, "10101010 10101010 10101010", LCT_RGB, 8);
1032   colorConvertTest("1001", LCT_GREY, 4, "10011001 10011001 10011001", LCT_RGB, 8);
1033   colorConvertTest("10010101", LCT_GREY, 8, "10010101 10010101 10010101", LCT_RGB, 8);
1034   colorConvertTest("10010101 11111110", LCT_GREY_ALPHA, 8, "10010101 10010101 10010101", LCT_RGB, 8);
1035   colorConvertTest("10010101 00000001 11111110 00000001", LCT_GREY_ALPHA, 16, "10010101 10010101 10010101", LCT_RGB, 8);
1036   colorConvertTest("01010101 00000000 00110011", LCT_RGB, 8, "01010101 00000000 00110011", LCT_RGB, 8);
1037   colorConvertTest("01010101 00000000 00110011 10101010", LCT_RGBA, 8, "01010101 00000000 00110011", LCT_RGB, 8);
1038   colorConvertTest("10101010 01010101 11111111 00000000 11001100 00110011", LCT_RGB, 16, "10101010 11111111 11001100", LCT_RGB, 8);
1039   colorConvertTest("10101010 01010101 11111111 00000000 11001100 00110011 11100111 00011000", LCT_RGBA, 16, "10101010 11111111 11001100", LCT_RGB, 8);
1040 
1041   //test color conversions to RGBA16
1042   colorConvertTest("1", LCT_GREY, 1, "11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111", LCT_RGBA, 16);
1043   colorConvertTest("10", LCT_GREY, 2, "10101010 10101010 10101010 10101010 10101010 10101010 11111111 11111111", LCT_RGBA, 16);
1044 
1045   //test grayscale color conversions
1046   colorConvertTest("1", LCT_GREY, 1, "11111111", LCT_GREY, 8);
1047   colorConvertTest("1", LCT_GREY, 1, "1111111111111111", LCT_GREY, 16);
1048   colorConvertTest("0", LCT_GREY, 1, "00000000", LCT_GREY, 8);
1049   colorConvertTest("0", LCT_GREY, 1, "0000000000000000", LCT_GREY, 16);
1050   colorConvertTest("11", LCT_GREY, 2, "11111111", LCT_GREY, 8);
1051   colorConvertTest("11", LCT_GREY, 2, "1111111111111111", LCT_GREY, 16);
1052   colorConvertTest("10", LCT_GREY, 2, "10101010", LCT_GREY, 8);
1053   colorConvertTest("10", LCT_GREY, 2, "1010101010101010", LCT_GREY, 16);
1054   colorConvertTest("1000", LCT_GREY, 4, "10001000", LCT_GREY, 8);
1055   colorConvertTest("1000", LCT_GREY, 4, "1000100010001000", LCT_GREY, 16);
1056   colorConvertTest("10110101", LCT_GREY, 8, "1011010110110101", LCT_GREY, 16);
1057   colorConvertTest("1011010110110101", LCT_GREY, 16, "10110101", LCT_GREY, 8);
1058 
1059   //others
1060   colorConvertTest("11111111 11111111 11111111 00000000 00000000 00000000", LCT_RGB, 8, "10", LCT_GREY, 1);
1061   colorConvertTest("11111111 11111111 11111111 11111111 11111111 11111111 00000000 00000000 00000000 00000000 00000000 00000000", LCT_RGB, 16, "10", LCT_GREY, 1);
1062 }
1063 
1064 //This tests color conversions from any color model to any color model, with any bit depth
1065 //But it tests only with colors black and white, because that are the only colors every single model supports
testColorConvert2()1066 void testColorConvert2() {
1067   std::cout << "testColorConvert2" << std::endl;
1068   struct Combo {
1069     LodePNGColorType colortype;
1070     unsigned bitdepth;
1071   };
1072 
1073   Combo combos[15] = { { LCT_GREY, 1}, { LCT_GREY, 2}, { LCT_GREY, 4}, { LCT_GREY, 8}, { LCT_GREY, 16}, { LCT_RGB, 8}, { LCT_RGB, 16}, { LCT_PALETTE, 1}, { LCT_PALETTE, 2}, { LCT_PALETTE, 4}, { LCT_PALETTE, 8}, { LCT_GREY_ALPHA, 8}, { LCT_GREY_ALPHA, 16}, { LCT_RGBA, 8}, { LCT_RGBA, 16},
1074   };
1075 
1076   lodepng::State state;
1077   LodePNGColorMode& mode_in = state.info_png.color;
1078   LodePNGColorMode& mode_out = state.info_raw;
1079   LodePNGColorMode mode_8;
1080   lodepng_color_mode_init(&mode_8);
1081 
1082   for(size_t i = 0; i < 256; i++) {
1083     size_t j = i == 1 ? 255 : i;
1084     lodepng_palette_add(&mode_in, j, j, j, 255);
1085     lodepng_palette_add(&mode_out, j, j, j, 255);
1086   }
1087 
1088   for(size_t i = 0; i < 15; i++) {
1089     mode_in.colortype = combos[i].colortype;
1090     mode_in.bitdepth = combos[i].bitdepth;
1091 
1092     for(size_t j = 0; j < 15; j++) {
1093       mode_out.colortype = combos[i].colortype;
1094       mode_out.bitdepth = combos[i].bitdepth;
1095 
1096       unsigned char eight[36] = {
1097           0,0,0,255, 255,255,255,255,
1098           0,0,0,255, 255,255,255,255,
1099           255,255,255,255, 0,0,0,255,
1100           255,255,255,255, 255,255,255,255,
1101           0,0,0,255 }; //input in RGBA8
1102       unsigned char in[72]; //custom input color type
1103       unsigned char out[72]; //custom output color type
1104       unsigned char eight2[36]; //back in RGBA8 after all conversions to check correctness
1105       unsigned error = 0;
1106 
1107       error |= lodepng_convert(in, eight, &mode_in, &mode_8, 3, 3);
1108       if(!error) error |= lodepng_convert(out, in, &mode_out, &mode_in, 3, 3); //Test input to output type
1109       if(!error) error |= lodepng_convert(eight2, out, &mode_8, &mode_out, 3, 3);
1110 
1111       if(!error) {
1112         for(size_t k = 0; k < 36; k++) {
1113           if(eight[k] != eight2[k]) {
1114             error = 99999;
1115             break;
1116           }
1117         }
1118       }
1119 
1120       if(error) {
1121         std::cout << "Error " << error << " i: " << i << " j: " << j
1122           << " colortype i: " << combos[i].colortype
1123           << " bitdepth i: " << combos[i].bitdepth
1124           << " colortype j: " << combos[j].colortype
1125           << " bitdepth j: " << combos[j].bitdepth
1126           << std::endl;
1127         if(error != 99999) ASSERT_NO_PNG_ERROR(error);
1128         else fail();
1129       }
1130     }
1131   }
1132 }
1133 
1134 //if compressible is true, the test will also assert that the compressed string is smaller
testCompressStringZlib(const std::string & text,bool compressible)1135 void testCompressStringZlib(const std::string& text, bool compressible) {
1136   if(text.size() < 500) std::cout << "compress test with text: " << text << std::endl;
1137   else std::cout << "compress test with text length: " << text.size() << std::endl;
1138 
1139   std::vector<unsigned char> in(text.size());
1140   for(size_t i = 0; i < text.size(); i++) in[i] = (unsigned char)text[i];
1141   unsigned char* out = 0;
1142   size_t outsize = 0;
1143   unsigned error = 0;
1144 
1145   error = lodepng_zlib_compress(&out, &outsize, in.empty() ? 0 : &in[0], in.size(), &lodepng_default_compress_settings);
1146   ASSERT_NO_PNG_ERROR(error);
1147   if(compressible) assertTrue(outsize < in.size());
1148 
1149   unsigned char* out2 = 0;
1150   size_t outsize2 = 0;
1151 
1152   error = lodepng_zlib_decompress(&out2, &outsize2, out, outsize, &lodepng_default_decompress_settings);
1153   ASSERT_NO_PNG_ERROR(error);
1154   ASSERT_EQUALS(outsize2, in.size());
1155   for(size_t i = 0; i < in.size(); i++) ASSERT_EQUALS(in[i], out2[i]);
1156 
1157   free(out);
1158   free(out2);
1159 }
1160 
testCompressZlib()1161 void testCompressZlib() {
1162   testCompressStringZlib("", false);
1163   testCompressStringZlib("a", false);
1164   testCompressStringZlib("aa", false);
1165   testCompressStringZlib("ababababababababababababababababababababababababababababababababababababababababababab", true);
1166   testCompressStringZlib("abaaaabaabbbaabbabbababbbbabababbbaabbbaaaabbbbabbbabbbaababbbbbaaabaabbabaaaabbbbbbab", true);
1167   testCompressStringZlib("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", true);
1168   testCompressStringZlib("omnomnomnomnomnomnomnomnomnomnom", true);
1169   testCompressStringZlib("the quick brown fox jumps over the lazy dog. the quick brown fox jumps over the lazy dog.", true);
1170   testCompressStringZlib("abracadabra", false);
1171   testCompressStringZlib("hello hello hello hello hello hello hello hello hello hello hello?", true);
1172   testCompressStringZlib("WPgZX2D*um0H::,4/KU\"kt\"Ne\"#Qa.&#<aF9{jag]|{hv,IXez\
1173 \\DKn5zYdV{XxBi=n|1J-TwakWvp[b8|-kOcZ@QkAxJSMeZ0l&<*w0BP/CXM(LFH'", false);
1174   testCompressStringZlib("asdfhlkhfafsduyfbasiuytfgbiasuidygiausygdifaubsydfsdf", false);
1175   testCompressStringZlib("418541499849814614617987416457317375467441841687487", true);
1176   testCompressStringZlib("3.141592653589793238462643383279502884197169399375105820974944592307816406286", true);
1177   testCompressStringZlib("lodepng_zlib_decompress(&out2, &outsize2, out, outsize, &lodepng_default_decompress_settings);", true);
1178 }
1179 
testDiskCompressZlib(const std::string & filename)1180 void testDiskCompressZlib(const std::string& filename) {
1181   std::cout << "testDiskCompressZlib: File " << filename << std::endl;
1182 
1183   std::vector<unsigned char> buffer;
1184   lodepng::load_file(buffer, filename);
1185   std::string f;
1186   for(size_t i = 0; i < buffer.size(); i++) f += (char)buffer[i];
1187   testCompressStringZlib(f, false);
1188 }
1189 
testDiskPNG(const std::string & filename)1190 void testDiskPNG(const std::string& filename) {
1191   std::cout << "testDiskPNG: File " << filename << std::endl;
1192 
1193   Image image;
1194   image.colorType = LCT_RGB;
1195   image.bitDepth = 8;
1196   unsigned error = lodepng::decode(image.data, image.width, image.height, filename, image.colorType, image.bitDepth);
1197   ASSERT_NO_PNG_ERROR(error);
1198 
1199   doCodecTest(image);
1200 }
1201 
strtovector(const std::string & numbers)1202 std::vector<unsigned> strtovector(const std::string& numbers) {
1203   std::vector<unsigned> result;
1204   std::stringstream ss(numbers);
1205   unsigned i;
1206   while(ss >> i) result.push_back(i);
1207   return result;
1208 }
1209 
doTestHuffmanCodeLengths(const std::string & expectedstr,const std::string & counts,size_t bitlength)1210 void doTestHuffmanCodeLengths(const std::string& expectedstr, const std::string& counts, size_t bitlength) {
1211   std::vector<unsigned> expected = strtovector(expectedstr);
1212   std::vector<unsigned> count = strtovector(counts);
1213   std::cout << "doTestHuffmanCodeLengths: " << counts << std::endl;
1214   std::vector<unsigned> result(count.size());
1215   unsigned error = lodepng_huffman_code_lengths(&result[0], &count[0], count.size(), bitlength);
1216   ASSERT_NO_PNG_ERROR_MSG(error, "errorcode");
1217   std::stringstream ss1, ss2;
1218   for(size_t i = 0; i < count.size(); i++) {
1219     ss1 << expected[i] << " ";
1220     ss2 << result[i] << " ";
1221   }
1222   assertEquals(ss1.str(), ss2.str(), "value");
1223 }
1224 
testHuffmanCodeLengths()1225 void testHuffmanCodeLengths() {
1226   bool atleasttwo = true; //LodePNG generates at least two, instead of at least one, symbol
1227   if(atleasttwo) {
1228     doTestHuffmanCodeLengths("1 1", "0 0", 16);
1229     doTestHuffmanCodeLengths("1 1 0", "0 0 0", 16);
1230     doTestHuffmanCodeLengths("1 1", "1 0", 16);
1231     doTestHuffmanCodeLengths("1 1 0 0 0 0 0 0 0", "0 0 0 0 0 0 0 0 0", 16);
1232     doTestHuffmanCodeLengths("1 1 0 0 0 0 0 0 0", "1 0 0 0 0 0 0 0 0", 16);
1233     doTestHuffmanCodeLengths("1 1 0 0 0 0 0 0 0", "0 1 0 0 0 0 0 0 0", 16);
1234     doTestHuffmanCodeLengths("1 0 0 0 0 0 0 0 1", "0 0 0 0 0 0 0 0 1", 16);
1235     doTestHuffmanCodeLengths("0 0 0 0 0 0 0 1 1", "0 0 0 0 0 0 0 1 1", 16);
1236   } else {
1237     doTestHuffmanCodeLengths("1 0", "0 0", 16);
1238     doTestHuffmanCodeLengths("1 0 0", "0 0 0", 16);
1239     doTestHuffmanCodeLengths("1 0", "1 0", 16);
1240     doTestHuffmanCodeLengths("1", "1", 16);
1241     doTestHuffmanCodeLengths("1", "0", 16);
1242   }
1243   doTestHuffmanCodeLengths("1 1", "1 1", 16);
1244   doTestHuffmanCodeLengths("1 1", "1 100", 16);
1245   doTestHuffmanCodeLengths("2 2 1", "1 2 3", 16);
1246   doTestHuffmanCodeLengths("2 1 2", "2 3 1", 16);
1247   doTestHuffmanCodeLengths("1 2 2", "3 1 2", 16);
1248   doTestHuffmanCodeLengths("3 3 2 1", "1 30 31 32", 16);
1249   doTestHuffmanCodeLengths("2 2 2 2", "1 30 31 32", 2);
1250   doTestHuffmanCodeLengths("5 5 4 4 4 3 3 1", "1 2 3 4 5 6 7 500", 16);
1251 }
1252 
1253 /*
1254 Create a PNG image with all known chunks (except only one of tEXt or zTXt) plus
1255 unknown chunks, and a palette.
1256 */
createComplexPNG(std::vector<unsigned char> & png)1257 void createComplexPNG(std::vector<unsigned char>& png) {
1258   unsigned w = 16, h = 17;
1259   std::vector<unsigned char> image(w * h);
1260   for(size_t i = 0; i < w * h; i++) {
1261     image[i] = i % 256;
1262   }
1263 
1264   lodepng::State state;
1265   LodePNGInfo& info = state.info_png;
1266   info.color.colortype = LCT_PALETTE;
1267   info.color.bitdepth = 8;
1268   state.info_raw.colortype = LCT_PALETTE;
1269   state.info_raw.bitdepth = 8;
1270   state.encoder.auto_convert = false;
1271   state.encoder.text_compression = 1;
1272   state.encoder.add_id = 1;
1273   for(size_t i = 0; i < 256; i++) {
1274     lodepng_palette_add(&info.color, i, i, i, i);
1275     lodepng_palette_add(&state.info_raw, i, i, i, i);
1276   }
1277 
1278   info.background_defined = 1;
1279   info.background_r = 127;
1280 
1281   lodepng_add_text(&info, "key0", "string0");
1282   lodepng_add_text(&info, "key1", "string1");
1283 
1284   lodepng_add_itext(&info, "ikey0", "ilangtag0", "itranskey0", "istring0");
1285   lodepng_add_itext(&info, "ikey1", "ilangtag1", "itranskey1", "istring1");
1286 
1287   info.time_defined = 1;
1288   info.time.year = 2012;
1289   info.time.month = 1;
1290   info.time.day = 2;
1291   info.time.hour = 3;
1292   info.time.minute = 4;
1293   info.time.second = 5;
1294 
1295   info.phys_defined = 1;
1296   info.phys_x = 1;
1297   info.phys_y = 2;
1298   info.phys_unit = 1;
1299 
1300   lodepng_chunk_create(&info.unknown_chunks_data[0], &info.unknown_chunks_size[0], 3, "uNKa", (unsigned char*)"a00");
1301   lodepng_chunk_create(&info.unknown_chunks_data[0], &info.unknown_chunks_size[0], 3, "uNKa", (unsigned char*)"a01");
1302   lodepng_chunk_create(&info.unknown_chunks_data[1], &info.unknown_chunks_size[1], 3, "uNKb", (unsigned char*)"b00");
1303   lodepng_chunk_create(&info.unknown_chunks_data[2], &info.unknown_chunks_size[2], 3, "uNKc", (unsigned char*)"c00");
1304 
1305   unsigned error = lodepng::encode(png, &image[0], w, h, state);
1306   ASSERT_NO_PNG_ERROR(error);
1307 }
1308 
extractChunkNames(const std::vector<unsigned char> & png)1309 std::string extractChunkNames(const std::vector<unsigned char>& png) {
1310   const unsigned char* chunk = &png[8];
1311   const unsigned char* end = &png.back() + 1;
1312   char name[5];
1313   std::string result = "";
1314   for(;;) {
1315     lodepng_chunk_type(name, chunk);
1316     result += (std::string(" ") + name);
1317     if(std::string(name) == "IEND") break;
1318     chunk = lodepng_chunk_next_const(chunk, end);
1319     assertTrue(chunk < &png.back(), "jumped out of chunks");
1320   }
1321   return result;
1322 }
1323 
testComplexPNG()1324 void testComplexPNG() {
1325   std::cout << "testComplexPNG" << std::endl;
1326 
1327   std::vector<unsigned char> png;
1328   createComplexPNG(png);
1329  {
1330     lodepng::State state;
1331     LodePNGInfo& info = state.info_png;
1332     unsigned w, h;
1333     std::vector<unsigned char> image;
1334     unsigned error = lodepng::decode(image, w, h, state, &png[0], png.size());
1335     ASSERT_NO_PNG_ERROR(error);
1336 
1337     ASSERT_EQUALS(16, w);
1338     ASSERT_EQUALS(17, h);
1339     ASSERT_EQUALS(1, info.background_defined);
1340     ASSERT_EQUALS(127, info.background_r);
1341     ASSERT_EQUALS(1, info.time_defined);
1342     ASSERT_EQUALS(2012, info.time.year);
1343     ASSERT_EQUALS(1, info.time.month);
1344     ASSERT_EQUALS(2, info.time.day);
1345     ASSERT_EQUALS(3, info.time.hour);
1346     ASSERT_EQUALS(4, info.time.minute);
1347     ASSERT_EQUALS(5, info.time.second);
1348     ASSERT_EQUALS(1, info.phys_defined);
1349     ASSERT_EQUALS(1, info.phys_x);
1350     ASSERT_EQUALS(2, info.phys_y);
1351     ASSERT_EQUALS(1, info.phys_unit);
1352 
1353     std::string chunknames = extractChunkNames(png);
1354     //std::string expectednames = " IHDR uNKa uNKa PLTE tRNS bKGD pHYs uNKb IDAT tIME tEXt tEXt tEXt iTXt iTXt uNKc IEND";
1355     std::string expectednames = " IHDR uNKa uNKa PLTE tRNS bKGD pHYs uNKb IDAT tIME zTXt zTXt tEXt iTXt iTXt uNKc IEND";
1356     ASSERT_EQUALS(expectednames, chunknames);
1357 
1358     ASSERT_EQUALS(3, info.text_num);
1359     ASSERT_STRING_EQUALS("key0", info.text_keys[0]);
1360     ASSERT_STRING_EQUALS("string0", info.text_strings[0]);
1361     ASSERT_STRING_EQUALS("key1", info.text_keys[1]);
1362     ASSERT_STRING_EQUALS("string1", info.text_strings[1]);
1363     ASSERT_STRING_EQUALS("LodePNG", info.text_keys[2]);
1364     ASSERT_STRING_EQUALS(LODEPNG_VERSION_STRING, info.text_strings[2]);
1365 
1366     ASSERT_EQUALS(2, info.itext_num);
1367     ASSERT_STRING_EQUALS("ikey0", info.itext_keys[0]);
1368     ASSERT_STRING_EQUALS("ilangtag0", info.itext_langtags[0]);
1369     ASSERT_STRING_EQUALS("itranskey0", info.itext_transkeys[0]);
1370     ASSERT_STRING_EQUALS("istring0", info.itext_strings[0]);
1371     ASSERT_STRING_EQUALS("ikey1", info.itext_keys[1]);
1372     ASSERT_STRING_EQUALS("ilangtag1", info.itext_langtags[1]);
1373     ASSERT_STRING_EQUALS("itranskey1", info.itext_transkeys[1]);
1374     ASSERT_STRING_EQUALS("istring1", info.itext_strings[1]);
1375 
1376     // TODO: test if unknown chunks listed too
1377   }
1378 
1379 
1380   // Test that if read_text_chunks is disabled, we do not get the texts
1381   {
1382     lodepng::State state;
1383     state.decoder.read_text_chunks = 0;
1384     unsigned w, h;
1385     std::vector<unsigned char> image;
1386     unsigned error = lodepng::decode(image, w, h, state, &png[0], png.size());
1387     ASSERT_NO_PNG_ERROR(error);
1388 
1389     ASSERT_EQUALS(0, state.info_png.text_num);
1390     ASSERT_EQUALS(0, state.info_png.itext_num);
1391 
1392     // But we should still get other values.
1393     ASSERT_EQUALS(2012, state.info_png.time.year);
1394   }
1395 }
1396 
1397 // Tests lodepng_inspect_chunk, and also lodepng_chunk_find to find the chunk to inspect
testInspectChunk()1398 void testInspectChunk() {
1399   std::cout << "testInspectChunk" << std::endl;
1400 
1401   std::vector<unsigned char> png;
1402   createComplexPNG(png);
1403 
1404   const unsigned char* chunk;
1405   lodepng::State state;
1406   LodePNGInfo& info = state.info_png;
1407   state.decoder.read_text_chunks = 0;
1408   lodepng_inspect(0, 0, &state, png.data(), png.size());
1409   chunk = lodepng_chunk_find(png.data(), png.data() + png.size(), "tIME");
1410   ASSERT_NOT_EQUALS((const unsigned char*)0, chunk); // should be non-null, since it should find it
1411   ASSERT_EQUALS(0, info.time_defined);
1412   lodepng_inspect_chunk(&state, (size_t)(chunk - png.data()), png.data(), png.size());
1413   ASSERT_EQUALS(1, info.time_defined);
1414   ASSERT_EQUALS(2012, state.info_png.time.year);
1415   ASSERT_EQUALS(1, info.time.month);
1416   ASSERT_EQUALS(2, info.time.day);
1417   ASSERT_EQUALS(3, info.time.hour);
1418   ASSERT_EQUALS(4, info.time.minute);
1419   ASSERT_EQUALS(5, info.time.second);
1420 
1421   ASSERT_EQUALS(0, info.text_num);
1422   chunk = lodepng_chunk_find_const(png.data(), png.data() + png.size(), "zTXt");
1423   lodepng_inspect_chunk(&state, (size_t)(chunk - png.data()), png.data(), png.size());
1424   ASSERT_EQUALS(1, info.text_num);
1425   chunk = lodepng_chunk_find_const(chunk, png.data() + png.size(), "zTXt");
1426   lodepng_inspect_chunk(&state, (size_t)(chunk - png.data()), png.data(), png.size());
1427   ASSERT_EQUALS(2, info.text_num);
1428 }
1429 
1430 //test that, by default, it chooses filter type zero for all scanlines if the image has a palette
testPaletteFilterTypesZero()1431 void testPaletteFilterTypesZero() {
1432   std::cout << "testPaletteFilterTypesZero" << std::endl;
1433 
1434   std::vector<unsigned char> png;
1435   createComplexPNG(png);
1436 
1437   std::vector<unsigned char> filterTypes;
1438   lodepng::getFilterTypes(filterTypes, png);
1439 
1440   ASSERT_EQUALS(17, filterTypes.size());
1441   for(size_t i = 0; i < 17; i++) ASSERT_EQUALS(0, filterTypes[i]);
1442 }
1443 
1444 //tests that there are no crashes with auto color chooser in case of palettes with translucency etc...
testPaletteToPaletteConvert()1445 void testPaletteToPaletteConvert() {
1446   std::cout << "testPaletteToPaletteConvert" << std::endl;
1447   unsigned error;
1448   unsigned w = 16, h = 16;
1449   std::vector<unsigned char> image(w * h);
1450   for(size_t i = 0; i < w * h; i++) image[i] = i % 256;
1451   lodepng::State state;
1452   LodePNGInfo& info = state.info_png;
1453   info.color.colortype = state.info_raw.colortype = LCT_PALETTE;
1454   info.color.bitdepth = state.info_raw.bitdepth = 8;
1455   ASSERT_EQUALS(true, state.encoder.auto_convert);
1456   for(size_t i = 0; i < 256; i++) {
1457     lodepng_palette_add(&info.color, i, i, i, i);
1458   }
1459   std::vector<unsigned char> png;
1460   for(size_t i = 0; i < 256; i++) {
1461     lodepng_palette_add(&state.info_raw, i, i, i, i);
1462   }
1463   error = lodepng::encode(png, &image[0], w, h, state);
1464   ASSERT_NO_PNG_ERROR(error);
1465 }
1466 
1467 //for this test, you have to choose palette colors that cause LodePNG to actually use a palette,
1468 //so don't use all grayscale colors for example
doRGBAToPaletteTest(unsigned char * palette,size_t size,LodePNGColorType expectedType=LCT_PALETTE)1469 void doRGBAToPaletteTest(unsigned char* palette, size_t size, LodePNGColorType expectedType = LCT_PALETTE) {
1470   std::cout << "testRGBToPaletteConvert " << size << std::endl;
1471   unsigned error;
1472   unsigned w = size, h = 257 /*LodePNG encodes no palette if image is too small*/;
1473   std::vector<unsigned char> image(w * h * 4);
1474   for(size_t i = 0; i < image.size(); i++) image[i] = palette[i % (size * 4)];
1475   std::vector<unsigned char> png;
1476   error = lodepng::encode(png, &image[0], w, h);
1477   ASSERT_NO_PNG_ERROR(error);
1478   lodepng::State state;
1479   std::vector<unsigned char> image2;
1480   error = lodepng::decode(image2, w, h, state, png);
1481   ASSERT_NO_PNG_ERROR(error);
1482   ASSERT_EQUALS(image.size(), image2.size());
1483   for(size_t i = 0; i < image.size(); i++) ASSERT_EQUALS(image[i], image2[i]);
1484 
1485   ASSERT_EQUALS(expectedType, state.info_png.color.colortype);
1486   if(expectedType == LCT_PALETTE) {
1487 
1488     ASSERT_EQUALS(size, state.info_png.color.palettesize);
1489     for(size_t i = 0; i < size * 4; i++) ASSERT_EQUALS(state.info_png.color.palette[i], image[i]);
1490   }
1491 }
1492 
testRGBToPaletteConvert()1493 void testRGBToPaletteConvert() {
1494   unsigned char palette1[4] = {1,2,3,4};
1495   doRGBAToPaletteTest(palette1, 1);
1496   unsigned char palette2[8] = {1,2,3,4, 5,6,7,8};
1497   doRGBAToPaletteTest(palette2, 2);
1498   unsigned char palette3[12] = {1,1,1,255, 20,20,20,255, 20,20,21,255};
1499   doRGBAToPaletteTest(palette3, 3);
1500 
1501   std::vector<unsigned char> palette;
1502   for(int i = 0; i < 256; i++) {
1503     palette.push_back(i);
1504     palette.push_back(5);
1505     palette.push_back(6);
1506     palette.push_back(128);
1507   }
1508   doRGBAToPaletteTest(&palette[0], 256);
1509   palette.push_back(5);
1510   palette.push_back(6);
1511   palette.push_back(7);
1512   palette.push_back(8);
1513   doRGBAToPaletteTest(&palette[0], 257, LCT_RGBA);
1514 }
1515 
testColorKeyConvert()1516 void testColorKeyConvert() {
1517   std::cout << "testColorKeyConvert" << std::endl;
1518   unsigned error;
1519   unsigned w = 32, h = 32;
1520   std::vector<unsigned char> image(w * h * 4);
1521   for(size_t i = 0; i < w * h; i++) {
1522     image[i * 4 + 0] = i % 256;
1523     image[i * 4 + 1] = i / 256;
1524     image[i * 4 + 2] = 0;
1525     image[i * 4 + 3] = i == 23 ? 0 : 255;
1526   }
1527   std::vector<unsigned char> png;
1528   error = lodepng::encode(png, &image[0], w, h);
1529   ASSERT_NO_PNG_ERROR(error);
1530 
1531   lodepng::State state;
1532   std::vector<unsigned char> image2;
1533   error = lodepng::decode(image2, w, h, state, png);
1534   ASSERT_NO_PNG_ERROR(error);
1535   ASSERT_EQUALS(32, w);
1536   ASSERT_EQUALS(32, h);
1537   ASSERT_EQUALS(1, state.info_png.color.key_defined);
1538   ASSERT_EQUALS(23, state.info_png.color.key_r);
1539   ASSERT_EQUALS(0, state.info_png.color.key_g);
1540   ASSERT_EQUALS(0, state.info_png.color.key_b);
1541   ASSERT_EQUALS(image.size(), image2.size());
1542   for(size_t i = 0; i < image.size(); i++) {
1543     ASSERT_EQUALS(image[i], image2[i]);
1544   }
1545 }
1546 
testNoAutoConvert()1547 void testNoAutoConvert() {
1548   std::cout << "testNoAutoConvert" << std::endl;
1549   unsigned error;
1550   unsigned w = 32, h = 32;
1551   std::vector<unsigned char> image(w * h * 4);
1552   for(size_t i = 0; i < w * h; i++) {
1553     image[i * 4 + 0] = (i % 2) ? 255 : 0;
1554     image[i * 4 + 1] = (i % 2) ? 255 : 0;
1555     image[i * 4 + 2] = (i % 2) ? 255 : 0;
1556     image[i * 4 + 3] = 0;
1557   }
1558   std::vector<unsigned char> png;
1559   lodepng::State state;
1560   state.info_png.color.colortype = LCT_RGBA;
1561   state.info_png.color.bitdepth = 8;
1562   state.encoder.auto_convert = false;
1563   error = lodepng::encode(png, &image[0], w, h, state);
1564   ASSERT_NO_PNG_ERROR(error);
1565 
1566   lodepng::State state2;
1567   std::vector<unsigned char> image2;
1568   error = lodepng::decode(image2, w, h, state2, png);
1569   ASSERT_NO_PNG_ERROR(error);
1570   ASSERT_EQUALS(32, w);
1571   ASSERT_EQUALS(32, h);
1572   ASSERT_EQUALS(LCT_RGBA, state2.info_png.color.colortype);
1573   ASSERT_EQUALS(8, state2.info_png.color.bitdepth);
1574   ASSERT_EQUALS(image.size(), image2.size());
1575   for(size_t i = 0; i < image.size(); i++) {
1576     ASSERT_EQUALS(image[i], image2[i]);
1577   }
1578 }
1579 
flipBit(unsigned char c,int bitpos)1580 unsigned char flipBit(unsigned char c, int bitpos) {
1581   return c ^ (1 << bitpos);
1582 }
1583 
1584 //Test various broken inputs. Returned errors are not checked, what is tested is
1585 //that is doesn't crash, and, when run with valgrind, no memory warnings are
1586 //given.
testFuzzing()1587 void testFuzzing() {
1588   std::cout << "testFuzzing" << std::endl;
1589   std::vector<unsigned char> png;
1590   createComplexPNG(png);
1591   std::vector<unsigned char> broken = png;
1592   std::vector<unsigned char> result;
1593   std::map<unsigned, unsigned> errors;
1594   unsigned w, h;
1595   lodepng::State state;
1596   state.decoder.ignore_crc = 1;
1597   state.decoder.zlibsettings.ignore_adler32 = 1;
1598   for(size_t i = 0; i < png.size(); i++) {
1599     result.clear();
1600     broken[i] = ~png[i];
1601     errors[lodepng::decode(result, w, h, state, broken)]++;
1602     broken[i] = 0;
1603     errors[lodepng::decode(result, w, h, state, broken)]++;
1604     for(int j = 0; j < 8; j++) {
1605       broken[i] = flipBit(png[i], j);
1606       errors[lodepng::decode(result, w, h, state, broken)]++;
1607     }
1608     broken[i] = 255;
1609     errors[lodepng::decode(result, w, h, state, broken)]++;
1610     broken[i] = png[i]; //fix it again for the next test
1611   }
1612   std::cout << "testFuzzing shrinking" << std::endl;
1613   broken = png;
1614   while(broken.size() > 0) {
1615     broken.resize(broken.size() - 1);
1616     errors[lodepng::decode(result, w, h, state, broken)]++;
1617   }
1618 
1619   //For fun, print the number of each error
1620   std::cout << "Fuzzing error code counts: ";
1621   for(std::map<unsigned, unsigned>::iterator it = errors.begin(); it != errors.end(); ++it) {
1622     std::cout << it->first << ":" << it->second << ", ";
1623   }
1624   std::cout << std::endl;
1625 }
1626 
testCustomZlibCompress()1627 void testCustomZlibCompress() {
1628   std::cout << "testCustomZlibCompress" << std::endl;
1629   Image image;
1630   generateTestImage(image, 5, 5, LCT_RGBA, 8);
1631 
1632   std::vector<unsigned char> encoded;
1633   int customcontext = 5;
1634 
1635   struct TestFun {
1636     static unsigned custom_zlib(unsigned char**, size_t*,
1637                           const unsigned char*, size_t,
1638                           const LodePNGCompressSettings* settings) {
1639       ASSERT_EQUALS(5, *(int*)(settings->custom_context));
1640       return 5555; //return a custom error code to prove this function was called
1641     }
1642   };
1643 
1644   lodepng::State state;
1645   state.encoder.zlibsettings.custom_zlib = TestFun::custom_zlib;
1646   state.encoder.zlibsettings.custom_context = &customcontext;
1647 
1648   unsigned error = lodepng::encode(encoded, image.data, image.width, image.height,
1649                                    state);
1650 
1651   ASSERT_EQUALS(5555, error);
1652 }
1653 
testCustomZlibCompress2()1654 void testCustomZlibCompress2() {
1655   std::cout << "testCustomZlibCompress2" << std::endl;
1656   Image image;
1657   generateTestImage(image, 5, 5, LCT_RGBA, 8);
1658 
1659   std::vector<unsigned char> encoded;
1660 
1661   lodepng::State state;
1662   state.encoder.zlibsettings.custom_zlib = lodepng_zlib_compress;
1663 
1664   unsigned error = lodepng::encode(encoded, image.data, image.width, image.height,
1665                                    state);
1666   ASSERT_NO_PNG_ERROR(error);
1667 
1668   std::vector<unsigned char> decoded;
1669   unsigned w, h;
1670   state.decoder.zlibsettings.ignore_adler32 = 0;
1671   state.decoder.ignore_crc = 0;
1672   error = lodepng::decode(decoded, w, h, state, encoded);
1673   ASSERT_NO_PNG_ERROR(error);
1674   ASSERT_EQUALS(5, w);
1675   ASSERT_EQUALS(5, h);
1676 }
1677 
testCustomDeflate()1678 void testCustomDeflate() {
1679   std::cout << "testCustomDeflate" << std::endl;
1680   Image image;
1681   generateTestImage(image, 5, 5, LCT_RGBA, 8);
1682 
1683   std::vector<unsigned char> encoded;
1684   int customcontext = 5;
1685 
1686   struct TestFun {
1687     static unsigned custom_deflate(unsigned char**, size_t*,
1688                                    const unsigned char*, size_t,
1689                                    const LodePNGCompressSettings* settings) {
1690       ASSERT_EQUALS(5, *(int*)(settings->custom_context));
1691       return 5555; //return a custom error code to prove this function was called
1692     }
1693   };
1694 
1695   lodepng::State state;
1696   state.encoder.zlibsettings.custom_deflate = TestFun::custom_deflate;
1697   state.encoder.zlibsettings.custom_context = &customcontext;
1698 
1699   unsigned error = lodepng::encode(encoded, image.data, image.width, image.height,
1700                                    state);
1701 
1702   ASSERT_EQUALS(5555, error);
1703 }
1704 
testCustomZlibDecompress()1705 void testCustomZlibDecompress() {
1706   std::cout << "testCustomZlibDecompress" << std::endl;
1707   Image image;
1708   generateTestImage(image, 5, 5, LCT_RGBA, 8);
1709 
1710   std::vector<unsigned char> encoded;
1711 
1712   unsigned error_enc = lodepng::encode(encoded, image.data, image.width, image.height,
1713                                    image.colorType, image.bitDepth);
1714   ASSERT_NO_PNG_ERROR_MSG(error_enc, "encoder error not expected");
1715 
1716 
1717   std::vector<unsigned char> decoded;
1718   unsigned w, h;
1719   int customcontext = 5;
1720 
1721   struct TestFun {
1722     static unsigned custom_zlib(unsigned char**, size_t*,
1723                           const unsigned char*, size_t,
1724                           const LodePNGDecompressSettings* settings) {
1725       ASSERT_EQUALS(5, *(int*)(settings->custom_context));
1726       return 5555; //return a custom error code to prove this function was called
1727     }
1728   };
1729 
1730   lodepng::State state;
1731   state.decoder.zlibsettings.custom_zlib = TestFun::custom_zlib;
1732   state.decoder.zlibsettings.custom_context = &customcontext;
1733   state.decoder.zlibsettings.ignore_adler32 = 0;
1734   state.decoder.ignore_crc = 0;
1735   unsigned error = lodepng::decode(decoded, w, h, state, encoded);
1736 
1737   ASSERT_EQUALS(5555, error);
1738 }
1739 
testCustomInflate()1740 void testCustomInflate() {
1741   std::cout << "testCustomInflate" << std::endl;
1742   Image image;
1743   generateTestImage(image, 5, 5, LCT_RGBA, 8);
1744 
1745   std::vector<unsigned char> encoded;
1746 
1747   unsigned error_enc = lodepng::encode(encoded, image.data, image.width, image.height,
1748                                    image.colorType, image.bitDepth);
1749   ASSERT_NO_PNG_ERROR_MSG(error_enc, "encoder error not expected");
1750 
1751 
1752   std::vector<unsigned char> decoded;
1753   unsigned w, h;
1754   int customcontext = 5;
1755 
1756   struct TestFun {
1757     static unsigned custom_inflate(unsigned char**, size_t*,
1758                                    const unsigned char*, size_t,
1759                                    const LodePNGDecompressSettings* settings) {
1760       ASSERT_EQUALS(5, *(int*)(settings->custom_context));
1761       return 5555; //return a custom error code to prove this function was called
1762     }
1763   };
1764 
1765   lodepng::State state;
1766   state.decoder.zlibsettings.custom_inflate = TestFun::custom_inflate;
1767   state.decoder.zlibsettings.custom_context = &customcontext;
1768   state.decoder.zlibsettings.ignore_adler32 = 0;
1769   state.decoder.ignore_crc = 0;
1770   unsigned error = lodepng::decode(decoded, w, h, state, encoded);
1771 
1772   ASSERT_EQUALS(5555, error);
1773 }
1774 
1775 
testChunkUtil()1776 void testChunkUtil() {
1777   std::cout << "testChunkUtil" << std::endl;
1778   std::vector<unsigned char> png;
1779   createComplexPNG(png);
1780 
1781   std::vector<std::string> names[3];
1782   std::vector<std::vector<unsigned char> > chunks[3];
1783 
1784   assertNoError(lodepng::getChunks(names, chunks, png));
1785 
1786   std::vector<std::vector<unsigned char> > chunks2[3];
1787   chunks2[0].push_back(chunks[2][2]); //zTXt
1788   chunks2[1].push_back(chunks[2][3]); //tEXt
1789   chunks2[2].push_back(chunks[2][4]); //iTXt
1790 
1791   assertNoError(lodepng::insertChunks(png, chunks2));
1792 
1793   std::string chunknames = extractChunkNames(png);
1794   //                                        chunks2[0]                    chunks2[1]                                   chunks2[2]
1795   //                                             v                             v                                            v
1796   std::string expectednames = " IHDR uNKa uNKa zTXt PLTE tRNS bKGD pHYs uNKb tEXt IDAT tIME zTXt zTXt tEXt iTXt iTXt uNKc iTXt IEND";
1797   ASSERT_EQUALS(expectednames, chunknames);
1798 
1799   std::vector<unsigned char> image;
1800   unsigned w, h;
1801   ASSERT_NO_PNG_ERROR(lodepng::decode(image, w, h, png));
1802 }
1803 
1804 //Test that when decoding to 16-bit per channel, it always uses big endian consistently.
1805 //It should always output big endian, the convention used inside of PNG, even though x86 CPU's are little endian.
test16bitColorEndianness()1806 void test16bitColorEndianness() {
1807   std::cout << "test16bitColorEndianness" << std::endl;
1808 
1809   //basn0g16.png from the PNG test suite
1810   std::string base64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAYagMeiWXwAAAF5JREFU"
1811                        "eJzV0jEKwDAMQ1E5W+9/xtygk8AoezLVKgSj2Y8/OICnuFcTE2OgOoJgHQiZAN2C9kDKBOgW3AZC"
1812                        "JkC3oD2QMgG6BbeBkAnQLWgPpExgP28H7E/0GTjPfwAW2EvYX64rn9cAAAAASUVORK5CYII=";
1813   std::vector<unsigned char> png;
1814   fromBase64(png, base64);
1815   unsigned w, h;
1816   std::vector<unsigned char> image;
1817   lodepng::State state;
1818 
1819   // Decode from 16-bit gray image to 16-bit per channel RGBA
1820   state.info_raw.bitdepth = 16;
1821   ASSERT_NO_PNG_ERROR(lodepng::decode(image, w, h, state, png));
1822   ASSERT_EQUALS(0x09, image[8]);
1823   ASSERT_EQUALS(0x00, image[9]);
1824 
1825   // Decode from 16-bit gray image to 16-bit gray raw image (no conversion)
1826   image.clear();
1827   state = lodepng::State();
1828   state.decoder.color_convert = false;
1829   ASSERT_NO_PNG_ERROR(lodepng::decode(image, w, h, state, png));
1830   ASSERT_EQUALS(0x09, image[2]);
1831   ASSERT_EQUALS(0x00, image[3]);
1832 
1833   // Decode from 16-bit per channel RGB image to 16-bit per channel RGBA
1834   base64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAAAANzQklU"
1835            "DQ0N0DeNwQAAAH5JREFUeJztl8ENxEAIAwcJ6cpI+q8qKeNepAgelq2dCjz4AdQM1jRcf3WIDQ13"
1836            "qUNsiBBQZ1gR0cARUFIz3pug3586wo5+rOcfIaBOsCSggSOgpcB8D4D3R9DgfUyECIhDbAhp4Ajo"
1837            "KPD+CBq8P4IG72MiQkCdYUVEA0dAyQcwUyZpXH92ZwAAAABJRU5ErkJggg=="; //cs3n2c16.png
1838   png.clear();
1839   fromBase64(png, base64);
1840   image.clear();
1841   state = lodepng::State();
1842   state.info_raw.bitdepth = 16;
1843   ASSERT_NO_PNG_ERROR(lodepng::decode(image, w, h, state, png));
1844   ASSERT_EQUALS(0x1f, image[258]);
1845   ASSERT_EQUALS(0xf9, image[259]);
1846 
1847   // Decode from 16-bit per channel RGB image to 16-bit per channel RGBA raw image (no conversion)
1848   image.clear();
1849   state = lodepng::State();
1850   state.decoder.color_convert = false;
1851   ASSERT_NO_PNG_ERROR(lodepng::decode(image, w, h, state, png));
1852 
1853   ASSERT_EQUALS(0x1f, image[194]);
1854   ASSERT_EQUALS(0xf9, image[195]);
1855 
1856   image.clear();
1857   state = lodepng::State();
1858 
1859   // Decode from palette image to 16-bit per channel RGBA
1860   base64 = "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHAgMAAAC5PL9AAAAABGdBTUEAAYagMeiWXwAAAANzQklU"
1861            "BAQEd/i1owAAAAxQTFRF/wB3AP93//8AAAD/G0OznAAAABpJREFUeJxj+P+H4WoMw605DDfmgEgg"
1862            "+/8fAHF5CrkeXW0HAAAAAElFTkSuQmCC"; //s07n3p02.png
1863   png.clear();
1864   fromBase64(png, base64);
1865   image.clear();
1866   state = lodepng::State();
1867   state.info_raw.bitdepth = 16;
1868   ASSERT_NO_PNG_ERROR(lodepng::decode(image, w, h, state, png));
1869   ASSERT_EQUALS(0x77, image[84]);
1870   ASSERT_EQUALS(0x77, image[85]);
1871 }
1872 
testPredefinedFilters()1873 void testPredefinedFilters() {
1874   size_t w = 32, h = 32;
1875   std::cout << "testPredefinedFilters" << std::endl;
1876   Image image;
1877   generateTestImage(image, w, h, LCT_RGBA, 8);
1878 
1879   // everything to filter type '3'
1880   std::vector<unsigned char> predefined(h, 3);
1881   lodepng::State state;
1882   state.encoder.filter_strategy = LFS_PREDEFINED;
1883   state.encoder.filter_palette_zero = 0;
1884   state.encoder.predefined_filters = &predefined[0];
1885 
1886   std::vector<unsigned char> png;
1887   unsigned error = lodepng::encode(png, &image.data[0], w, h, state);
1888   assertNoError(error);
1889 
1890   std::vector<unsigned char> outfilters;
1891   error = lodepng::getFilterTypes(outfilters, png);
1892   assertNoError(error);
1893 
1894   ASSERT_EQUALS(outfilters.size(), h);
1895   for(size_t i = 0; i < h; i++) ASSERT_EQUALS(3, outfilters[i]);
1896 }
1897 
testEncoderErrors()1898 void testEncoderErrors() {
1899   std::cout << "testEncoderErrors" << std::endl;
1900 
1901   std::vector<unsigned char> png;
1902   unsigned w = 32, h = 32;
1903   Image image;
1904   generateTestImage(image, w, h);
1905 
1906   lodepng::State def;
1907 
1908   lodepng::State state;
1909 
1910   ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
1911 
1912   // test window sizes
1913   state.encoder.zlibsettings.windowsize = 0;
1914   ASSERT_EQUALS(60, lodepng::encode(png, &image.data[0], w, h, state));
1915   state.encoder.zlibsettings.windowsize = 65536;
1916   ASSERT_EQUALS(60, lodepng::encode(png, &image.data[0], w, h, state));
1917   state.encoder.zlibsettings.windowsize = 1000; // not power of two
1918   ASSERT_EQUALS(90, lodepng::encode(png, &image.data[0], w, h, state));
1919   state.encoder.zlibsettings.windowsize = 256;
1920   ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
1921 
1922   state = def;
1923   state.info_png.color.bitdepth = 3;
1924   ASSERT_EQUALS(37, lodepng::encode(png, &image.data[0], w, h, state));
1925 
1926   state = def;
1927   state.info_png.color.colortype = (LodePNGColorType)5;
1928   ASSERT_EQUALS(31, lodepng::encode(png, &image.data[0], w, h, state));
1929 
1930   state = def;
1931   state.info_png.color.colortype = LCT_PALETTE;
1932   ASSERT_EQUALS(68, lodepng::encode(png, &image.data[0], w, h, state));
1933 
1934   state = def;
1935   state.info_png.interlace_method = 0;
1936   ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
1937   state.info_png.interlace_method = 1;
1938   ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
1939   state.info_png.interlace_method = 2;
1940   ASSERT_EQUALS(71, lodepng::encode(png, &image.data[0], w, h, state));
1941 
1942   state = def;
1943   state.encoder.zlibsettings.btype = 0;
1944   ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
1945   state.encoder.zlibsettings.btype = 1;
1946   ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
1947   state.encoder.zlibsettings.btype = 2;
1948   ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
1949   state.encoder.zlibsettings.btype = 3;
1950   ASSERT_EQUALS(61, lodepng::encode(png, &image.data[0], w, h, state));
1951 }
1952 
addColor(std::vector<unsigned char> & colors,unsigned char r,unsigned char g,unsigned char b,unsigned char a)1953 void addColor(std::vector<unsigned char>& colors, unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
1954   colors.push_back(r);
1955   colors.push_back(g);
1956   colors.push_back(b);
1957   colors.push_back(a);
1958 }
1959 
addColor16(std::vector<unsigned char> & colors,unsigned short r,unsigned short g,unsigned short b,unsigned short a)1960 void addColor16(std::vector<unsigned char>& colors, unsigned short r, unsigned short g, unsigned short b, unsigned short a) {
1961   colors.push_back(r & 255);
1962   colors.push_back((r >> 8) & 255);
1963   colors.push_back(g & 255);
1964   colors.push_back((g >> 8) & 255);
1965   colors.push_back(b & 255);
1966   colors.push_back((b >> 8) & 255);
1967   colors.push_back(a & 255);
1968   colors.push_back((a >> 8) & 255);
1969 }
1970 
1971 // Tests auto_convert
1972 // colors is in RGBA, inbitdepth must be 8 or 16, the amount of bits per channel.
1973 // colortype and bitdepth are the expected values. insize is amount of pixels. So the amount of bytes is insize * 4 * (inbitdepth / 8)
testAutoColorModel(const std::vector<unsigned char> & colors,unsigned inbitdepth,LodePNGColorType colortype,unsigned bitdepth,bool key)1974 void testAutoColorModel(const std::vector<unsigned char>& colors, unsigned inbitdepth, LodePNGColorType colortype, unsigned bitdepth, bool key) {
1975   std::cout << "testAutoColorModel " << inbitdepth << " " << colortype << " " << bitdepth << " " << key << std::endl;
1976   size_t innum = colors.size() / 4 * inbitdepth / 8;
1977   size_t num = innum < 65536 ? 65536 : innum; // Make image bigger so the convert doesn't avoid palette due to small image.
1978   std::vector<unsigned char> colors2(num * 4 * (inbitdepth / 8));
1979   for(size_t i = 0; i < colors2.size(); i++) colors2[i] = colors[i % colors.size()];
1980 
1981   std::vector<unsigned char> png;
1982   lodepng::encode(png, colors2, num, 1, LCT_RGBA, inbitdepth);
1983 
1984   // now extract the color type it chose
1985   unsigned w, h;
1986   lodepng::State state;
1987   std::vector<unsigned char> decoded;
1988   lodepng::decode(decoded, w, h, state, png);
1989   ASSERT_EQUALS(num, w);
1990   ASSERT_EQUALS(1, h);
1991   ASSERT_EQUALS(colortype, state.info_png.color.colortype);
1992   ASSERT_EQUALS(bitdepth, state.info_png.color.bitdepth);
1993   ASSERT_EQUALS(key, state.info_png.color.key_defined);
1994   // also check that the PNG decoded correctly and has same colors as input
1995   if(inbitdepth == 8) { for(size_t i = 0; i < colors.size(); i++) ASSERT_EQUALS(colors[i], decoded[i]); }
1996   else { for(size_t i = 0; i < colors.size() / 2; i++) ASSERT_EQUALS(colors[i * 2], decoded[i]); }
1997 }
1998 
testAutoColorModels()1999 void testAutoColorModels() {
2000   // 1-bit gray
2001   std::vector<unsigned char> gray1;
2002   for(size_t i = 0; i < 2; i++) addColor(gray1, i * 255, i * 255, i * 255, 255);
2003   testAutoColorModel(gray1, 8, LCT_GREY, 1, false);
2004 
2005   // 2-bit gray
2006   std::vector<unsigned char> gray2;
2007   for(size_t i = 0; i < 4; i++) addColor(gray2, i * 85, i * 85, i * 85, 255);
2008   testAutoColorModel(gray2, 8, LCT_GREY, 2, false);
2009 
2010   // 4-bit gray
2011   std::vector<unsigned char> gray4;
2012   for(size_t i = 0; i < 16; i++) addColor(gray4, i * 17, i * 17, i * 17, 255);
2013   testAutoColorModel(gray4, 8, LCT_GREY, 4, false);
2014 
2015   // 8-bit gray
2016   std::vector<unsigned char> gray8;
2017   for(size_t i = 0; i < 256; i++) addColor(gray8, i, i, i, 255);
2018   testAutoColorModel(gray8, 8, LCT_GREY, 8, false);
2019 
2020   // 16-bit gray
2021   std::vector<unsigned char> gray16;
2022   for(size_t i = 0; i < 257; i++) addColor16(gray16, i, i, i, 65535);
2023   testAutoColorModel(gray16, 16, LCT_GREY, 16, false);
2024 
2025   // 8-bit gray+alpha
2026   std::vector<unsigned char> gray8a;
2027   for(size_t i = 0; i < 17; i++) addColor(gray8a, i, i, i, i);
2028   testAutoColorModel(gray8a, 8, LCT_PALETTE, 8, false);
2029   // palette not possible, becomes gray alpha
2030   for(size_t i = 0; i < 256; i++) addColor(gray8a, i, i, i, i ^ 1);
2031   testAutoColorModel(gray8a, 8, LCT_GREY_ALPHA, 8, false);
2032 
2033   // 16-bit gray+alpha
2034   std::vector<unsigned char> gray16a;
2035   for(size_t i = 0; i < 257; i++) addColor16(gray16a, i, i, i, i);
2036   testAutoColorModel(gray16a, 16, LCT_GREY_ALPHA, 16, false);
2037 
2038 
2039   // various palette tests
2040   std::vector<unsigned char> palette;
2041   addColor(palette, 0, 0, 1, 255);
2042   testAutoColorModel(palette, 8, LCT_PALETTE, 1, false);
2043   addColor(palette, 0, 0, 2, 255);
2044   testAutoColorModel(palette, 8, LCT_PALETTE, 1, false);
2045   for(int i = 3; i <= 4; i++) addColor(palette, 0, 0, i, 255);
2046   testAutoColorModel(palette, 8, LCT_PALETTE, 2, false);
2047   for(int i = 5; i <= 7; i++) addColor(palette, 0, 0, i, 255);
2048   testAutoColorModel(palette, 8, LCT_PALETTE, 4, false);
2049   for(int i = 8; i <= 17; i++) addColor(palette, 0, 0, i, 255);
2050   testAutoColorModel(palette, 8, LCT_PALETTE, 8, false);
2051   addColor(palette, 0, 0, 18, 0); // transparent
2052   testAutoColorModel(palette, 8, LCT_PALETTE, 8, false);
2053   addColor(palette, 0, 0, 18, 1); // translucent
2054   testAutoColorModel(palette, 8, LCT_PALETTE, 8, false);
2055 
2056   // 1-bit gray + alpha not possible, becomes palette
2057   std::vector<unsigned char> gray1a;
2058   for(size_t i = 0; i < 2; i++) addColor(gray1a, i, i, i, 128);
2059   testAutoColorModel(gray1a, 8, LCT_PALETTE, 1, false);
2060 
2061   // 2-bit gray + alpha not possible, becomes palette
2062   std::vector<unsigned char> gray2a;
2063   for(size_t i = 0; i < 4; i++) addColor(gray2a, i, i, i, 128);
2064   testAutoColorModel(gray2a, 8, LCT_PALETTE, 2, false);
2065 
2066   // 4-bit gray + alpha not possible, becomes palette
2067   std::vector<unsigned char> gray4a;
2068   for(size_t i = 0; i < 16; i++) addColor(gray4a, i, i, i, 128);
2069   testAutoColorModel(gray4a, 8, LCT_PALETTE, 4, false);
2070 
2071   // 8-bit rgb
2072   std::vector<unsigned char> rgb = gray8;
2073   addColor(rgb, 255, 0, 0, 255);
2074   testAutoColorModel(rgb, 8, LCT_RGB, 8, false);
2075 
2076   // 8-bit rgb + key
2077   std::vector<unsigned char> rgb_key = rgb;
2078   addColor(rgb_key, 128, 0, 0, 0);
2079   testAutoColorModel(rgb_key, 8, LCT_RGB, 8, true);
2080 
2081   // 8-bit rgb, not key due to edge case: single key color, but opaque color has same RGB value
2082   std::vector<unsigned char> rgb_key2 = rgb_key;
2083   addColor(rgb_key2, 128, 0, 0, 255); // same color but opaque ==> no more key
2084   testAutoColorModel(rgb_key2, 8, LCT_RGBA, 8, false);
2085 
2086   // 8-bit rgb, not key due to semi translucent
2087   std::vector<unsigned char> rgb_key3 = rgb_key;
2088   addColor(rgb_key3, 128, 0, 0, 255); // semi-translucent ==> no more key
2089   testAutoColorModel(rgb_key3, 8, LCT_RGBA, 8, false);
2090 
2091   // 8-bit rgb, not key due to multiple transparent colors
2092   std::vector<unsigned char> rgb_key4 = rgb_key;
2093   addColor(rgb_key4, 128, 0, 0, 255);
2094   addColor(rgb_key4, 129, 0, 0, 255); // two different transparent colors ==> no more key
2095   testAutoColorModel(rgb_key4, 8, LCT_RGBA, 8, false);
2096 
2097   // 1-bit gray with key
2098   std::vector<unsigned char> gray1_key = gray1;
2099   gray1_key[7] = 0;
2100   testAutoColorModel(gray1_key, 8, LCT_GREY, 1, true);
2101 
2102   // 2-bit gray with key
2103   std::vector<unsigned char> gray2_key = gray2;
2104   gray2_key[7] = 0;
2105   testAutoColorModel(gray2_key, 8, LCT_GREY, 2, true);
2106 
2107   // 4-bit gray with key
2108   std::vector<unsigned char> gray4_key = gray4;
2109   gray4_key[7] = 0;
2110   testAutoColorModel(gray4_key, 8, LCT_GREY, 4, true);
2111 
2112   // 8-bit gray with key
2113   std::vector<unsigned char> gray8_key = gray8;
2114   gray8_key[7] = 0;
2115   testAutoColorModel(gray8_key, 8, LCT_GREY, 8, true);
2116 
2117   // 16-bit gray with key
2118   std::vector<unsigned char> gray16_key = gray16;
2119   gray16_key[14] = gray16_key[15] = 0;
2120   testAutoColorModel(gray16_key, 16, LCT_GREY, 16, true);
2121 
2122   // a single 16-bit color, can't become palette due to being 16-bit
2123   std::vector<unsigned char> small16;
2124   addColor16(small16, 1, 0, 0, 65535);
2125   testAutoColorModel(small16, 16, LCT_RGB, 16, false);
2126 
2127   std::vector<unsigned char> small16a;
2128   addColor16(small16a, 1, 0, 0, 1);
2129   testAutoColorModel(small16a, 16, LCT_RGBA, 16, false);
2130 
2131   // what we provide as 16-bit is actually representable as 8-bit, so 8-bit palette expected for single color
2132   std::vector<unsigned char> not16;
2133   addColor16(not16, 257, 257, 257, 0);
2134   testAutoColorModel(not16, 16, LCT_PALETTE, 1, false);
2135 
2136   // the rgb color is representable as 8-bit, but the alpha channel only as 16-bit, so ensure it uses 16-bit and not palette for this single color
2137   std::vector<unsigned char> alpha16;
2138   addColor16(alpha16, 257, 0, 0, 10000);
2139   testAutoColorModel(alpha16, 16, LCT_RGBA, 16, false);
2140 
2141   // 1-bit gray, with attempt to get color key but can't do it due to opaque color with same value
2142   std::vector<unsigned char> gray1k;
2143   addColor(gray1k, 0, 0, 0, 255);
2144   addColor(gray1k, 255, 255, 255, 255);
2145   addColor(gray1k, 255, 255, 255, 0);
2146   testAutoColorModel(gray1k, 8, LCT_PALETTE, 2, false);
2147 }
2148 
testPaletteToPaletteDecode()2149 void testPaletteToPaletteDecode() {
2150   std::cout << "testPaletteToPaletteDecode" << std::endl;
2151   // It's a bit big for a 2x2 image... but this tests needs one with 256 palette entries in it.
2152   std::string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAMAAABFaP0WAAAAA3NCSVQICAjb4U/gAAADAFBMVEUA"
2153                        "AAAAADMAAGYAAJkAAMwAAP8AMwAAMzMAM2YAM5kAM8wAM/8AZgAAZjMAZmYAZpkAZswAZv8AmQAA"
2154                        "mTMAmWYAmZkAmcwAmf8AzAAAzDMAzGYAzJkAzMwAzP8A/wAA/zMA/2YA/5kA/8wA//8zAAAzADMz"
2155                        "AGYzAJkzAMwzAP8zMwAzMzMzM2YzM5kzM8wzM/8zZgAzZjMzZmYzZpkzZswzZv8zmQAzmTMzmWYz"
2156                        "mZkzmcwzmf8zzAAzzDMzzGYzzJkzzMwzzP8z/wAz/zMz/2Yz/5kz/8wz//9mAABmADNmAGZmAJlm"
2157                        "AMxmAP9mMwBmMzNmM2ZmM5lmM8xmM/9mZgBmZjNmZmZmZplmZsxmZv9mmQBmmTNmmWZmmZlmmcxm"
2158                        "mf9mzABmzDNmzGZmzJlmzMxmzP9m/wBm/zNm/2Zm/5lm/8xm//+ZAACZADOZAGaZAJmZAMyZAP+Z"
2159                        "MwCZMzOZM2aZM5mZM8yZM/+ZZgCZZjOZZmaZZpmZZsyZZv+ZmQCZmTOZmWaZmZmZmcyZmf+ZzACZ"
2160                        "zDOZzGaZzJmZzMyZzP+Z/wCZ/zOZ/2aZ/5mZ/8yZ///MAADMADPMAGbMAJnMAMzMAP/MMwDMMzPM"
2161                        "M2bMM5nMM8zMM//MZgDMZjPMZmbMZpnMZszMZv/MmQDMmTPMmWbMmZnMmczMmf/MzADMzDPMzGbM"
2162                        "zJnMzMzMzP/M/wDM/zPM/2bM/5nM/8zM////AAD/ADP/AGb/AJn/AMz/AP//MwD/MzP/M2b/M5n/"
2163                        "M8z/M///ZgD/ZjP/Zmb/Zpn/Zsz/Zv//mQD/mTP/mWb/mZn/mcz/mf//zAD/zDP/zGb/zJn/zMz/"
2164                        "zP///wD//zP//2b//5n//8z///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2165                        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2166                        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlenwdAAABAHRSTlP/////////////////////////"
2167                        "////////////////////////////////////////////////////////////////////////////"
2168                        "////////////////////////////////////////////////////////////////////////////"
2169                        "////////////////////////////////////////////////////////////////////////////"
2170                        "//////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2171                        "AAAAAAAAAAAAG8mZagAAAAlwSFlzAAAOTQAADpwB3vacVwAAAA5JREFUCJlj2CLHwHodAATjAa+k"
2172                        "lTE5AAAAAElFTkSuQmCC";
2173   std::vector<unsigned char> png;
2174   fromBase64(png, base64);
2175 
2176   std::vector<unsigned char> image;
2177   unsigned width, height;
2178   unsigned error = lodepng::decode(image, width, height, png, LCT_PALETTE, 8);
2179   ASSERT_EQUALS(0, error);
2180   ASSERT_EQUALS(2, width);
2181   ASSERT_EQUALS(2, height);
2182   ASSERT_EQUALS(180, image[0]);
2183   ASSERT_EQUALS(30, image[1]);
2184   ASSERT_EQUALS(5, image[2]);
2185   ASSERT_EQUALS(215, image[3]);
2186 }
2187 
2188 //2-bit palette
testPaletteToPaletteDecode2()2189 void testPaletteToPaletteDecode2() {
2190   std::cout << "testPaletteToPaletteDecode2" << std::endl;
2191   std::string base64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAgMAAAAOFJJnAAAADFBMVEX/AAAA/wAAAP/////7AGD2AAAAE0lEQVR4AWMQhAKG3VCALDIqAgDl2WYBCQHY9gAAAABJRU5ErkJggg==";
2192   std::vector<unsigned char> png;
2193   fromBase64(png, base64);
2194 
2195   std::vector<unsigned char> image;
2196   unsigned width, height;
2197   unsigned error = lodepng::decode(image, width, height, png, LCT_PALETTE, 8);
2198   ASSERT_EQUALS(0, error);
2199   ASSERT_EQUALS(32, width);
2200   ASSERT_EQUALS(32, height);
2201   ASSERT_EQUALS(0, image[0]);
2202   ASSERT_EQUALS(1, image[1]);
2203 
2204   //Now add a user-specified output palette, that differs from the input palette. That should give error 82.
2205   LodePNGState state;
2206   lodepng_state_init(&state);
2207   state.info_raw.colortype = LCT_PALETTE;
2208   state.info_raw.bitdepth = 8;
2209   lodepng_palette_add(&state.info_raw, 0, 0, 0, 255);
2210   lodepng_palette_add(&state.info_raw, 1, 1, 1, 255);
2211   lodepng_palette_add(&state.info_raw, 2, 2, 2, 255);
2212   lodepng_palette_add(&state.info_raw, 3, 3, 3, 255);
2213   unsigned char* image2 = 0;
2214   unsigned error2 = lodepng_decode(&image2, &width, &height, &state, &png[0], png.size());
2215   lodepng_state_cleanup(&state);
2216   ASSERT_EQUALS(82, error2);
2217   free(image2);
2218 }
2219 
assertColorProfileDataEqual(const lodepng::State & a,const lodepng::State & b)2220 void assertColorProfileDataEqual(const lodepng::State& a, const lodepng::State& b) {
2221   ASSERT_EQUALS(a.info_png.gama_defined, b.info_png.gama_defined);
2222   if(a.info_png.gama_defined) {
2223     ASSERT_EQUALS(a.info_png.gama_gamma, b.info_png.gama_gamma);
2224   }
2225 
2226   ASSERT_EQUALS(a.info_png.chrm_defined, b.info_png.chrm_defined);
2227   if(a.info_png.chrm_defined) {
2228     ASSERT_EQUALS(a.info_png.chrm_white_x, b.info_png.chrm_white_x);
2229     ASSERT_EQUALS(a.info_png.chrm_white_y, b.info_png.chrm_white_y);
2230     ASSERT_EQUALS(a.info_png.chrm_red_x, b.info_png.chrm_red_x);
2231     ASSERT_EQUALS(a.info_png.chrm_red_y, b.info_png.chrm_red_y);
2232     ASSERT_EQUALS(a.info_png.chrm_green_x, b.info_png.chrm_green_x);
2233     ASSERT_EQUALS(a.info_png.chrm_green_y, b.info_png.chrm_green_y);
2234     ASSERT_EQUALS(a.info_png.chrm_blue_x, b.info_png.chrm_blue_x);
2235     ASSERT_EQUALS(a.info_png.chrm_blue_y, b.info_png.chrm_blue_y);
2236   }
2237 
2238   ASSERT_EQUALS(a.info_png.srgb_defined, b.info_png.srgb_defined);
2239   if(a.info_png.srgb_defined) {
2240     ASSERT_EQUALS(a.info_png.srgb_intent, b.info_png.srgb_intent);
2241   }
2242 
2243   ASSERT_EQUALS(a.info_png.iccp_defined, b.info_png.iccp_defined);
2244   if(a.info_png.iccp_defined) {
2245     //ASSERT_EQUALS(std::string(a.info_png.iccp_name), std::string(b.info_png.iccp_name));
2246     ASSERT_EQUALS(a.info_png.iccp_profile_size, b.info_png.iccp_profile_size);
2247     for(size_t i = 0; i < a.info_png.iccp_profile_size; ++i) {
2248       ASSERT_EQUALS(a.info_png.iccp_profile[i], b.info_png.iccp_profile[i]);
2249     }
2250   }
2251 }
2252 
2253 // Tests the gAMA, cHRM, sRGB, iCCP chunks
testColorProfile()2254 void testColorProfile() {
2255   std::cout << "testColorProfile" << std::endl;
2256   {
2257     unsigned error;
2258     unsigned w = 32, h = 32;
2259     std::vector<unsigned char> image(w * h * 4);
2260     for(size_t i = 0; i < image.size(); i++) image[i] = i & 255;
2261     std::vector<unsigned char> png;
2262     lodepng::State state;
2263     state.info_png.gama_defined = 1;
2264     state.info_png.gama_gamma = 12345;
2265     state.info_png.chrm_defined = 1;
2266     state.info_png.chrm_white_x = 10;
2267     state.info_png.chrm_white_y = 20;
2268     state.info_png.chrm_red_x = 30;
2269     state.info_png.chrm_red_y = 40;
2270     state.info_png.chrm_green_x = 100000;
2271     state.info_png.chrm_green_y = 200000;
2272     state.info_png.chrm_blue_x = 300000;
2273     state.info_png.chrm_blue_y = 400000;
2274     error = lodepng::encode(png, &image[0], w, h, state);
2275     ASSERT_NO_PNG_ERROR(error);
2276 
2277     lodepng::State state2;
2278     std::vector<unsigned char> image2;
2279     error = lodepng::decode(image2, w, h, state2, png);
2280     ASSERT_NO_PNG_ERROR(error);
2281     assertColorProfileDataEqual(state, state2);
2282     ASSERT_EQUALS(32, w);
2283     ASSERT_EQUALS(32, h);
2284     ASSERT_EQUALS(image.size(), image2.size());
2285     for(size_t i = 0; i < image.size(); i++) ASSERT_EQUALS(image[i], image2[i]);
2286   }
2287   {
2288     unsigned error;
2289     unsigned w = 32, h = 32;
2290     std::vector<unsigned char> image(w * h * 4);
2291     for(size_t i = 0; i < image.size(); i++) image[i] = i & 255;
2292     std::vector<unsigned char> png;
2293     lodepng::State state;
2294     state.info_png.srgb_defined = 1;
2295     state.info_png.srgb_intent = 2;
2296     error = lodepng::encode(png, &image[0], w, h, state);
2297     ASSERT_NO_PNG_ERROR(error);
2298 
2299     lodepng::State state2;
2300     std::vector<unsigned char> image2;
2301     error = lodepng::decode(image2, w, h, state2, png);
2302     ASSERT_NO_PNG_ERROR(error);
2303     assertColorProfileDataEqual(state, state2);
2304     ASSERT_EQUALS(32, w);
2305     ASSERT_EQUALS(32, h);
2306     ASSERT_EQUALS(image.size(), image2.size());
2307     for(size_t i = 0; i < image.size(); i++) ASSERT_EQUALS(image[i], image2[i]);
2308   }
2309   {
2310     unsigned error;
2311     unsigned w = 32, h = 32;
2312     std::vector<unsigned char> image(w * h * 4);
2313     for(size_t i = 0; i < image.size(); i++) image[i] = i & 255;
2314     std::vector<unsigned char> png;
2315     lodepng::State state;
2316     state.info_png.iccp_defined = 1;
2317     std::string testprofile = "0123456789abcdefRGB fake iccp profile for testing";
2318     testprofile[0] = testprofile[1] = 0;
2319     lodepng_set_icc(&state.info_png, "test", (const unsigned char*)testprofile.c_str(), testprofile.size());
2320     error = lodepng::encode(png, &image[0], w, h, state);
2321     ASSERT_NO_PNG_ERROR(error);
2322 
2323     lodepng::State state2;
2324     std::vector<unsigned char> image2;
2325     error = lodepng::decode(image2, w, h, state2, png);
2326     ASSERT_NO_PNG_ERROR(error);
2327     assertColorProfileDataEqual(state, state2);
2328     ASSERT_EQUALS(32, w);
2329     ASSERT_EQUALS(32, h);
2330     ASSERT_EQUALS(image.size(), image2.size());
2331     for(size_t i = 0; i < image.size(); i++) ASSERT_EQUALS(image[i], image2[i]);
2332   }
2333 
2334   // grayscale ICC profile
2335   {
2336     unsigned error;
2337     unsigned w = 32, h = 32;
2338     std::vector<unsigned char> image(w * h * 4);
2339     for(size_t i = 0; i + 4 <= image.size(); i += 4) {
2340       image[i] = image[i + 1] = image[i + 2] = image[i + 3] = i;
2341     }
2342     std::vector<unsigned char> png;
2343     lodepng::State state;
2344     state.info_png.iccp_defined = 1;
2345     std::string testprofile = "0123456789abcdefGRAYfake iccp profile for testing";
2346     testprofile[0] = testprofile[1] = 0;
2347     lodepng_set_icc(&state.info_png, "test", (const unsigned char*)testprofile.c_str(), testprofile.size());
2348     error = lodepng::encode(png, &image[0], w, h, state);
2349     ASSERT_NO_PNG_ERROR(error);
2350 
2351     lodepng::State state2;
2352     std::vector<unsigned char> image2;
2353     error = lodepng::decode(image2, w, h, state2, png);
2354     ASSERT_NO_PNG_ERROR(error);
2355     assertColorProfileDataEqual(state, state2);
2356     ASSERT_EQUALS(32, w);
2357     ASSERT_EQUALS(32, h);
2358     ASSERT_EQUALS(image.size(), image2.size());
2359     for(size_t i = 0; i < image.size(); i++) ASSERT_EQUALS(image[i], image2[i]);
2360   }
2361 
2362   // grayscale ICC profile, using an input image with grayscale colors but that
2363   // would normally benefit from a palette (which auto_convert would normally
2364   // choose). But the PNG spec does not allow combining palette with GRAY ICC
2365   // profile, so the encoder should not choose to use palette after all.
2366   {
2367     unsigned error;
2368     unsigned w = 32, h = 32;
2369     std::vector<unsigned char> image(w * h * 4);
2370     int colors[3] = {0, 3, 133};
2371     for(size_t i = 0; i + 4 <= image.size(); i += 4) {
2372       image[i] = image[i + 1] = image[i + 2] = image[i + 3] = colors[(i / 4) % 3];
2373     }
2374     std::vector<unsigned char> png;
2375     lodepng::State state;
2376     state.info_png.iccp_defined = 1;
2377     std::string testprofile = "0123456789abcdefGRAYfake iccp profile for testing";
2378     testprofile[0] = testprofile[1] = 0;
2379     lodepng_set_icc(&state.info_png, "test", (const unsigned char*)testprofile.c_str(), testprofile.size());
2380     error = lodepng::encode(png, &image[0], w, h, state);
2381     ASSERT_NO_PNG_ERROR(error);
2382 
2383     lodepng::State state2;
2384     std::vector<unsigned char> image2;
2385     error = lodepng::decode(image2, w, h, state2, png);
2386     ASSERT_NO_PNG_ERROR(error);
2387     assertColorProfileDataEqual(state, state2);
2388     ASSERT_NOT_EQUALS(LCT_PALETTE, state2.info_png.color.colortype);
2389   }
2390 
2391   // RGB ICC profile, using an input image with grayscale colors: the encoder
2392   // is forced to choose an RGB color type anyway with auto_convert
2393   {
2394     unsigned error;
2395     unsigned w = 32, h = 32;
2396     std::vector<unsigned char> image(w * h * 4);
2397     for(size_t i = 0; i + 4 <= image.size(); i += 4) {
2398       image[i] = image[i + 1] = image[i + 2] = (i / 4) & 255;
2399       image[i + 3] = 255;
2400     }
2401     std::vector<unsigned char> png;
2402     lodepng::State state;
2403     state.info_png.iccp_defined = 1;
2404     std::string testprofile = "0123456789abcdefRGB fake iccp profile for testing";
2405     testprofile[0] = testprofile[1] = 0;
2406     lodepng_set_icc(&state.info_png, "test", (const unsigned char*)testprofile.c_str(), testprofile.size());
2407     error = lodepng::encode(png, &image[0], w, h, state);
2408     ASSERT_NO_PNG_ERROR(error);
2409 
2410     lodepng::State state2;
2411     std::vector<unsigned char> image2;
2412     error = lodepng::decode(image2, w, h, state2, png);
2413     ASSERT_NO_PNG_ERROR(error);
2414     assertColorProfileDataEqual(state, state2);
2415     // LCT_RGB or LCT_PALETTE are both ok, gray is not (it likely chooses palette in practice)
2416     ASSERT_NOT_EQUALS(LCT_GREY, state2.info_png.color.colortype);
2417     ASSERT_NOT_EQUALS(LCT_GREY_ALPHA, state2.info_png.color.colortype);
2418   }
2419 
2420   // Encoder must give error when forcing invalid combination of color/gray
2421   // PNG with gray/color ICC Profile
2422   {
2423     unsigned error;
2424     unsigned w = 32, h = 32;
2425     std::vector<unsigned char> image(w * h * 4);
2426     int colors[3] = {0, 5, 33};
2427     for(size_t i = 0; i + 4 <= image.size(); i += 4) {
2428       image[i] = 255;
2429       image[i + 1] = image[i + 2] = image[i + 3] = colors[(i / 4) % 3];
2430     }
2431     std::vector<unsigned char> png;
2432     lodepng::State state;
2433     state.info_png.iccp_defined = 1;
2434     std::string testprofile = "0123456789abcdefGRAYfake iccp profile for testing";
2435     testprofile[0] = testprofile[1] = 0;
2436     lodepng_set_icc(&state.info_png, "test", (const unsigned char*)testprofile.c_str(), testprofile.size());
2437     error = lodepng::encode(png, &image[0], w, h, state);
2438     ASSERT_NOT_EQUALS(0, error);  // must give error due to color image input with gray profile
2439   }
2440 }
2441 
2442 // r, g, b is input background color to encoder, given in png color model
2443 // r2, g2, b2 is expected decoded background color, in color model it auto chose if auto_convert is on
2444 // pixels must be given in mode_raw color format
testBkgdChunk(unsigned r,unsigned g,unsigned b,unsigned r2,unsigned g2,unsigned b2,const std::vector<unsigned char> & pixels,unsigned w,unsigned h,const LodePNGColorMode & mode_raw,const LodePNGColorMode & mode_png,bool auto_convert,bool expect_encoder_error=false)2445 void testBkgdChunk(unsigned r, unsigned g, unsigned b,
2446                    unsigned r2, unsigned g2, unsigned b2,
2447                    const std::vector<unsigned char>& pixels,
2448                    unsigned w, unsigned h,
2449                    const LodePNGColorMode& mode_raw,
2450                    const LodePNGColorMode& mode_png,
2451                    bool auto_convert, bool expect_encoder_error = false) {
2452   unsigned error;
2453 
2454   lodepng::State state;
2455   LodePNGInfo& info = state.info_png;
2456   lodepng_color_mode_copy(&info.color, &mode_png);
2457   lodepng_color_mode_copy(&state.info_raw, &mode_raw);
2458   state.encoder.auto_convert = auto_convert;
2459 
2460   info.background_defined = 1;
2461   info.background_r = r;
2462   info.background_g = g;
2463   info.background_b = b;
2464 
2465   std::vector<unsigned char> png;
2466   error = lodepng::encode(png, pixels, w, h, state);
2467   if(expect_encoder_error) {
2468     ASSERT_NOT_EQUALS(0, error);
2469     return;
2470   }
2471   ASSERT_NO_PNG_ERROR(error);
2472 
2473   lodepng::State state2;
2474   LodePNGInfo& info2 = state2.info_png;
2475   state2.info_raw.colortype = LCT_RGBA;
2476   state2.info_raw.bitdepth = 16;
2477   unsigned w2, h2;
2478   std::vector<unsigned char> image2;
2479   error = lodepng::decode(image2, w2, h2, state2, &png[0], png.size());
2480   ASSERT_NO_PNG_ERROR(error);
2481 
2482   ASSERT_EQUALS(w, w2);
2483   ASSERT_EQUALS(h, h2);
2484   ASSERT_EQUALS(1, info2.background_defined);
2485   ASSERT_EQUALS(r2, info2.background_r);
2486   ASSERT_EQUALS(g2, info2.background_g);
2487   ASSERT_EQUALS(b2, info2.background_b);
2488 
2489   // compare pixels in the "raw" color model
2490   LodePNGColorMode mode_temp; lodepng_color_mode_init(&mode_temp); mode_temp.bitdepth = 16; mode_temp.colortype = LCT_RGBA;
2491   std::vector<unsigned char> image3((w * h * lodepng_get_bpp(&mode_raw) + 7) / 8);
2492   error = lodepng_convert(image3.data(), image2.data(), &mode_raw, &mode_temp, w, h);
2493   ASSERT_NO_PNG_ERROR(error);
2494   ASSERT_EQUALS(pixels.size(), image3.size());
2495   for(size_t i = 0; i < image3.size(); i++) {
2496     ASSERT_EQUALS((int)image3[i], (int)pixels[i]);
2497   }
2498 }
2499 
2500 // r, g, b is input background color to encoder, given in png color model
2501 // r2, g2, b2 is expected decoded background color, in color model it auto chose if auto_convert is on
testBkgdChunk(unsigned r,unsigned g,unsigned b,unsigned r2,unsigned g2,unsigned b2,LodePNGColorType type_pixels,unsigned bitdepth_pixels,LodePNGColorType type_raw,unsigned bitdepth_raw,LodePNGColorType type_png,unsigned bitdepth_png,bool auto_convert,bool expect_encoder_error=false)2502 void testBkgdChunk(unsigned r, unsigned g, unsigned b,
2503                    unsigned r2, unsigned g2, unsigned b2,
2504                    LodePNGColorType type_pixels, unsigned bitdepth_pixels,
2505                    LodePNGColorType type_raw, unsigned bitdepth_raw,
2506                    LodePNGColorType type_png, unsigned bitdepth_png,
2507                    bool auto_convert, bool expect_encoder_error = false) {
2508   unsigned error;
2509   Image image;
2510   generateTestImageRequiringColorType16(image, type_pixels, bitdepth_pixels, false);
2511 
2512   LodePNGColorMode mode_raw; lodepng_color_mode_init(&mode_raw); mode_raw.bitdepth = bitdepth_raw; mode_raw.colortype = type_raw;
2513   LodePNGColorMode mode_temp; lodepng_color_mode_init(&mode_temp); mode_temp.bitdepth = 16; mode_temp.colortype = LCT_RGBA;
2514   LodePNGColorMode mode_png; lodepng_color_mode_init(&mode_png); mode_png.bitdepth = bitdepth_png; mode_png.colortype = type_png;
2515   std::vector<unsigned char> temp((image.width * image.height * lodepng_get_bpp(&mode_raw) + 7) / 8);
2516   error = lodepng_convert(temp.data(), image.data.data(), &mode_raw, &mode_temp, image.width, image.height);
2517   ASSERT_NO_PNG_ERROR(error);
2518   image.data = temp;
2519 
2520   testBkgdChunk(r, g, b, r2, g2, b2,
2521                 image.data, image.width, image.height,
2522                 mode_raw, mode_png, auto_convert, expect_encoder_error);
2523 }
2524 
testBkgdChunk()2525 void testBkgdChunk() {
2526   std::cout << "testBkgdChunk" << std::endl;
2527   // color param order is: generated, raw, png ( == bKGD)
2528   // here generated means: what color values the pixels will get, so what auto_convert will make it choose
2529   testBkgdChunk(255, 0, 0, 255, 0, 0, LCT_RGBA, 8, LCT_RGBA, 8, LCT_RGBA, 8, true);
2530   testBkgdChunk(255, 0, 0, 255, 0, 0, LCT_RGBA, 8, LCT_RGB, 8, LCT_RGB, 8, true);
2531   testBkgdChunk(255, 0, 0, 255, 0, 0, LCT_RGB, 8, LCT_RGB, 8, LCT_RGB, 8, true);
2532   testBkgdChunk(255, 255, 255, 1, 1, 1, LCT_GREY, 1, LCT_RGB, 8, LCT_RGB, 8, true);
2533   testBkgdChunk(255, 255, 255, 3, 3, 3, LCT_GREY, 2, LCT_RGB, 8, LCT_RGB, 8, true);
2534   testBkgdChunk(255, 255, 255, 15, 15, 15, LCT_GREY, 4, LCT_RGB, 8, LCT_RGB, 8, true);
2535   testBkgdChunk(255, 255, 255, 255, 255, 255, LCT_GREY, 8, LCT_RGB, 8, LCT_RGB, 8, true);
2536   testBkgdChunk(255, 255, 255, 65535, 65535, 65535, LCT_GREY, 16, LCT_RGB, 16, LCT_RGB, 8, true);
2537   testBkgdChunk(123, 0, 0, 123, 0, 0, LCT_GREY, 1, LCT_RGB, 8, LCT_RGB, 8, true);
2538   testBkgdChunk(170, 170, 170, 2, 2, 2, LCT_GREY, 1, LCT_RGB, 8, LCT_RGB, 8, true); // 170 = value 2 in 2-bit
2539 
2540   // without auto_convert. Note that it will still convert if different colortype is given for raw and png, it's just
2541   // not automatic in that case.
2542   testBkgdChunk(255, 0, 0, 255, 0, 0, LCT_RGBA, 8, LCT_RGBA, 8, LCT_RGBA, 8, false);
2543   testBkgdChunk(60000, 0, 0, 60000, 0, 0, LCT_RGBA, 8, LCT_RGBA, 8, LCT_RGBA, 16, false);
2544   testBkgdChunk(128, 128, 128, 128, 128, 128, LCT_GREY, 8, LCT_RGBA, 8, LCT_GREY, 8, false);
2545  {
2546     LodePNGColorMode pal;
2547     lodepng_color_mode_init(&pal);
2548     for(int i = 0; i < 200; i++) lodepng_palette_add(&pal, i, i / 2, 0, 255);
2549     pal.colortype = LCT_PALETTE;
2550     pal.bitdepth = 8;
2551     unsigned w = 200;
2552     unsigned h = 200;
2553     std::vector<unsigned char> img(w * h);
2554     for(unsigned y = 0; y < h; y++)
2555     for(unsigned x = 0; x < w; x++) {
2556       img[y * w + x] = x;
2557     }
2558 
2559     testBkgdChunk(100, 0, 0, 100, 100, 100, img, w, h, pal, pal, true, false);
2560     testBkgdChunk(100, 0, 0, 100, 100, 100, img, w, h, pal, pal, false, false);
2561     testBkgdChunk(250, 0, 0, 250, 250, 250, img, w, h, pal, pal, true, true);
2562 
2563     std::vector<unsigned char> fourcolor(w * h);
2564     for(unsigned y = 0; y < h; y++)
2565     for(unsigned x = 0; x < w; x++) {
2566       fourcolor[y * w + x] = x & 3;
2567     }
2568     // palette index 4 expected for output bKGD: auto_convert should turn the 200-sized
2569     // palette in one of size 5, 4 values for the fourcolor image above, and then a 5th for
2570     // the bkgd index. The other two 4's actually shouldn't matter, it's not defined what
2571     // they should be though currently lodepng sets them also to the palette index...
2572     testBkgdChunk(100, 0, 0, 4, 4, 4, fourcolor, w, h, pal, pal, true, false);
2573 
2574 
2575     std::vector<unsigned char> mini(4);
2576     mini[0] = 1; mini[1] = 2; mini[2] = 3; mini[3] = 4;
2577     // here we expect RGB color from the output image, since the image is tiny so it chooses to not add PLTE
2578     testBkgdChunk(100, 0, 0, 100, 50, 0, mini, 2, 2, pal, pal, true, false);
2579 
2580     lodepng_color_mode_cleanup(&pal);
2581   }
2582 }
2583 
testBkgdChunk2()2584 void testBkgdChunk2() {
2585   std::cout << "testBkgdChunk2" << std::endl;
2586   Image image;
2587   generateTestImageRequiringColorType8(image, LCT_GREY, 2, false);
2588 
2589   // without background, it should choose 2-bit gray for this PNG
2590   std::vector<unsigned char> png0;
2591   ASSERT_NO_PNG_ERROR(lodepng::encode(png0, image.data, image.width, image.height));
2592   lodepng::State state0;
2593   unsigned w0, h0;
2594   lodepng_inspect(&w0, &h0, &state0, png0.data(), png0.size());
2595   ASSERT_EQUALS(2, state0.info_png.color.bitdepth);
2596   ASSERT_EQUALS(LCT_GREY, state0.info_png.color.colortype);
2597 
2598   // red background, with auto_convert, it is forced to choose RGB
2599   lodepng::State state;
2600   LodePNGInfo& info = state.info_png;
2601   info.background_defined = 1;
2602   info.background_r = 255;
2603   info.background_g = 0;
2604   info.background_b = 0;
2605   std::vector<unsigned char> png1;
2606   ASSERT_NO_PNG_ERROR(lodepng::encode(png1, image.data, image.width, image.height, state));
2607   lodepng::State state1;
2608   unsigned w1, h1;
2609   lodepng_inspect(&w1, &h1, &state1, png1.data(), png1.size());
2610   ASSERT_EQUALS(8, state1.info_png.color.bitdepth);
2611   ASSERT_EQUALS(LCT_RGB, state1.info_png.color.colortype);
2612 
2613   // gray output required, background color also interpreted as gray
2614   state.info_raw.colortype = LCT_RGB;
2615   state.info_png.color.colortype = LCT_GREY;
2616   state.info_png.color.bitdepth = 1;
2617   state.encoder.auto_convert = 0;
2618   info.background_defined = 1;
2619   info.background_r = 1;
2620   info.background_g = 1;
2621   info.background_b = 1;
2622   std::vector<unsigned char> png2;
2623   ASSERT_NO_PNG_ERROR(lodepng::encode(png2, image.data, image.width, image.height, state));
2624   lodepng::State state2;
2625   unsigned w2, h2;
2626   lodepng_inspect(&w2, &h2, &state2, png2.data(), png2.size());
2627   ASSERT_EQUALS(1, state2.info_png.color.bitdepth);
2628   ASSERT_EQUALS(LCT_GREY, state2.info_png.color.colortype);
2629 }
2630 
2631 // Test particular cHRM+gAMA conversion to srgb
2632 // gamma = gamma given 100000x multiplied form of PNG, or 0 to set none at all
2633 // wx..by = whitepoint and chromaticities, given in the 100000x multiplied form of PNG
2634 // r, g, b: r, g, b values to encode in the PNG's data
2635 // er, eg, eb: expected r, g, b values after decoding and converting to sRGB
testChrmToSrgb(unsigned gamma,unsigned wx,unsigned wy,unsigned rx,unsigned ry,unsigned gx,unsigned gy,unsigned bx,unsigned by,unsigned char r,unsigned char g,unsigned char b,unsigned char er,unsigned char eg,unsigned char eb,int max_dist=0)2636 void testChrmToSrgb(unsigned gamma, unsigned wx, unsigned wy, unsigned rx, unsigned ry, unsigned gx, unsigned gy, unsigned bx, unsigned by,
2637                     unsigned char r, unsigned char g, unsigned char b, unsigned char er, unsigned char eg, unsigned char eb,
2638                     int max_dist = 0) {
2639   std::vector<unsigned char> image(4);
2640   image[0] = r;
2641   image[1] = g;
2642   image[2] = b;
2643   image[3] = 255;
2644   lodepng::State state;
2645   if(gamma) {
2646     state.info_png.gama_defined = 1;
2647     state.info_png.gama_gamma = gamma;
2648   }
2649   state.info_png.chrm_defined = 1;
2650   state.info_png.chrm_white_x = wx;
2651   state.info_png.chrm_white_y = wy;
2652   state.info_png.chrm_red_x = rx;
2653   state.info_png.chrm_red_y = ry;
2654   state.info_png.chrm_green_x = gx;
2655   state.info_png.chrm_green_y = gy;
2656   state.info_png.chrm_blue_x = bx;
2657   state.info_png.chrm_blue_y = by;
2658 
2659   std::vector<unsigned char> image2(4);
2660   convertToSrgb(image2.data(), image.data(), 1, 1, &state);
2661 
2662   if(max_dist == 0) {
2663     ASSERT_EQUALS(er, image2[0]);
2664     ASSERT_EQUALS(eg, image2[1]);
2665     ASSERT_EQUALS(eb, image2[2]);
2666   } else {
2667     ASSERT_NEAR(er, image2[0], max_dist);
2668     ASSERT_NEAR(eg, image2[1], max_dist);
2669     ASSERT_NEAR(eb, image2[2], max_dist);
2670   }
2671 
2672   // Also test the opposite direction
2673 
2674   std::vector<unsigned char> image3(4);
2675   convertFromSrgb(image3.data(), image2.data(), 1, 1, &state);
2676 
2677   if(max_dist == 0) {
2678     ASSERT_EQUALS(r, image3[0]);
2679     ASSERT_EQUALS(g, image3[1]);
2680     ASSERT_EQUALS(b, image3[2]);
2681   } else {
2682     ASSERT_NEAR(r, image3[0], max_dist);
2683     ASSERT_NEAR(g, image3[1], max_dist);
2684     ASSERT_NEAR(b, image3[2], max_dist);
2685   }
2686 }
2687 
testChrmToSrgb()2688 void testChrmToSrgb() {
2689   std::cout << "testChrmToSrgb" << std::endl;
2690   // srgb gamma approximation and chromaticities defined as standard by png (multiplied by 100000)
2691   unsigned sg = 45455; // srgb gamma approximation
2692   unsigned swx = 31270;
2693   unsigned swy = 32900;
2694   unsigned srx = 64000;
2695   unsigned sry = 33000;
2696   unsigned sgx = 30000;
2697   unsigned sgy = 60000;
2698   unsigned sbx = 15000;
2699   unsigned sby = 6000;
2700 
2701   testChrmToSrgb(sg, swx, swy, srx, sry, sgx, sgy, sbx, sby, 0, 0, 0, 0, 0, 0);
2702   testChrmToSrgb(sg, swx, swy, srx, sry, sgx, sgy, sbx, sby, 255, 255, 255, 255, 255, 255);
2703 
2704   testChrmToSrgb(0, swx, swy, srx, sry, sgx, sgy, sbx, sby, 50, 50, 50, 50, 50, 50);
2705   testChrmToSrgb(0, swx, swy, srx, sry, sgx, sgy, sbx, sby, 128, 128, 128, 128, 128, 128);
2706   testChrmToSrgb(0, swx, swy, srx, sry, sgx, sgy, sbx, sby, 200, 200, 200, 200, 200, 200);
2707 
2708   testChrmToSrgb(0, swx, swy, srx, sry, sgx, sgy, sbx, sby, 255, 0, 0, 255, 0, 0);
2709   testChrmToSrgb(0, swx, swy, srx, sry, sgx, sgy, sbx, sby, 0, 255, 0, 0, 255, 0);
2710   testChrmToSrgb(0, swx, swy, srx, sry, sgx, sgy, sbx, sby, 0, 0, 255, 0, 0, 255);
2711 
2712   // swap red and green chromaticities
2713   testChrmToSrgb(0, swx, swy, sgx, sgy, srx, sry, sbx, sby, 255, 0, 0, 0, 255, 0);
2714   testChrmToSrgb(0, swx, swy, sgx, sgy, srx, sry, sbx, sby, 0, 255, 0, 255, 0, 0);
2715   testChrmToSrgb(0, swx, swy, sgx, sgy, srx, sry, sbx, sby, 0, 0, 255, 0, 0, 255);
2716 
2717   // swap red/green/blue chromaticities
2718   testChrmToSrgb(0, swx, swy, sgx, sgy, sbx, sby, srx, sry, 255, 0, 0, 0, 255, 0);
2719   testChrmToSrgb(0, swx, swy, sgx, sgy, sbx, sby, srx, sry, 0, 255, 0, 0, 0, 255);
2720   testChrmToSrgb(0, swx, swy, sgx, sgy, sbx, sby, srx, sry, 0, 0, 255, 255, 0, 0);
2721 
2722   // different whitepoint does not affect white or gray, due to the relative rendering intent (adaptation)
2723   testChrmToSrgb(0, 35000, 25000, srx, sry, sgx, sgy, sbx, sby, 0, 0, 0, 0, 0, 0);
2724   testChrmToSrgb(0, 35000, 25000, srx, sry, sgx, sgy, sbx, sby, 50, 50, 50, 50, 50, 50);
2725   testChrmToSrgb(0, 35000, 25000, srx, sry, sgx, sgy, sbx, sby, 128, 128, 128, 128, 128, 128);
2726   testChrmToSrgb(0, 35000, 25000, srx, sry, sgx, sgy, sbx, sby, 200, 200, 200, 200, 200, 200);
2727   testChrmToSrgb(0, 35000, 25000, srx, sry, sgx, sgy, sbx, sby, 255, 255, 255, 255, 255, 255);
2728 }
2729 
2730 
2731 
testXYZ()2732 void testXYZ() {
2733   std::cout << "testXYZ" << std::endl;
2734   unsigned w = 512, h = 512;
2735   std::vector<unsigned char> v(w * h * 4 * 2);
2736   for(size_t i = 0; i < v.size(); i++) {
2737     v[i] = getRandom() & 255;
2738   }
2739 
2740   // Test sRGB -> XYZ -> sRGB roundtrip
2741 
2742   unsigned rendering_intent = 3; // test with absolute for now
2743 
2744   // 8-bit
2745   {
2746     // Default state, the conversions use 8-bit sRGB
2747     lodepng::State state;
2748     std::vector<float> f(w * h * 4);
2749     float whitepoint[3];
2750     assertNoError(lodepng::convertToXYZ(f.data(), whitepoint, v.data(), w, h, &state));
2751 
2752     std::vector<unsigned char> v2(w * h * 4);
2753     assertNoError(lodepng::convertFromXYZ(v2.data(), f.data(), w, h, &state, whitepoint, rendering_intent));
2754 
2755     for(size_t i = 0; i < v2.size(); i++) {
2756       ASSERT_EQUALS(v[i], v2[i]);
2757     }
2758   }
2759 
2760   // 16-bit
2761   {
2762     // Default state but with 16-bit, the conversions use 16-bit sRGB
2763     lodepng::State state;
2764     state.info_raw.bitdepth = 16;
2765     std::vector<float> f(w * h * 4);
2766     float whitepoint[3];
2767     assertNoError(lodepng::convertToXYZ(f.data(), whitepoint, v.data(), w, h, &state));
2768 
2769     std::vector<unsigned char> v2(w * h * 8);
2770     assertNoError(lodepng::convertFromXYZ(v2.data(), f.data(), w, h, &state, whitepoint, rendering_intent));
2771 
2772     for(size_t i = 0; i < v2.size(); i++) {
2773       ASSERT_EQUALS(v[i], v2[i]);
2774     }
2775   }
2776 
2777   // Test custom RGB+gamma -> XYZ -> custom RGB+gamma roundtrip
2778 
2779   LodePNGInfo info_custom;
2780   lodepng_info_init(&info_custom);
2781   info_custom.gama_defined = 1;
2782   info_custom.gama_gamma =   30000; // default 45455
2783   info_custom.chrm_defined = 1;
2784   info_custom.chrm_white_x = 10000; // default 31270
2785   info_custom.chrm_white_y = 20000; // default 32900
2786   info_custom.chrm_red_x =   30000; // default 64000
2787   info_custom.chrm_red_y =   50000; // default 33000
2788   info_custom.chrm_green_x = 70000; // default 30000
2789   info_custom.chrm_green_y = 11000; // default 60000
2790   info_custom.chrm_blue_x =  13000; // default 15000
2791   info_custom.chrm_blue_y =  17000; // default 6000
2792 
2793   // 8-bit
2794   {
2795     lodepng::State state;
2796     lodepng_info_copy(&state.info_png, &info_custom);
2797     std::vector<float> f(w * h * 4);
2798     float whitepoint[3];
2799     assertNoError(lodepng::convertToXYZ(f.data(), whitepoint, v.data(), w, h, &state));
2800 
2801     std::vector<unsigned char> v2(w * h * 4);
2802     assertNoError(lodepng::convertFromXYZ(v2.data(), f.data(), w, h, &state, whitepoint, rendering_intent));
2803 
2804     for(size_t i = 0; i < v2.size(); i++) {
2805       // Allow near instead of exact due to numerical issues with low values,
2806       // see description at the 16-bit test below.
2807       unsigned maxdist = 0;
2808       if(v[i] <= 2) maxdist = 3;
2809       else if(v[i] <= 4) maxdist = 2;
2810       else maxdist = 0;
2811       ASSERT_NEAR(v[i], v2[i], maxdist);
2812     }
2813   }
2814 
2815   // 16-bit
2816   {
2817     lodepng::State state;
2818     lodepng_info_copy(&state.info_png, &info_custom);
2819     state.info_raw.bitdepth = 16;
2820     std::vector<float> f(w * h * 4);
2821     float whitepoint[3];
2822     assertNoError(lodepng::convertToXYZ(f.data(), whitepoint, v.data(), w, h, &state));
2823 
2824     std::vector<unsigned char> v2(w * h * 8);
2825     assertNoError(lodepng::convertFromXYZ(v2.data(), f.data(), w, h, &state, whitepoint, rendering_intent));
2826 
2827     for(size_t i = 0; i < v2.size(); i += 2) {
2828       unsigned a = v[i + 0] * 256u + v[i + 1];
2829       unsigned a2 = v2[i + 0] * 256u + v2[i + 1];
2830       // There are numerical issues with low values due to the precision of float,
2831       // so allow some distance for low values (low compared to 65535).
2832       // The issue seems to be: the combination of how the gamma correction affects
2833       // low values and the color conversion matrix operating on single precision
2834       // floating point. With the sRGB's gamma the problem seems not to happen, maybe
2835       // because that linear part near 0 behaves better than power.
2836       // TODO: check if it can be fixed without using double for the image and without slow double precision pow.
2837       unsigned maxdist = 0;
2838       if(a < 2048) maxdist = 768;
2839       else if(a < 4096) maxdist = 24;
2840       else if(a < 16384) maxdist = 4;
2841       else maxdist = 2;
2842       ASSERT_NEAR(a, a2, maxdist);
2843     }
2844   }
2845 
2846   lodepng_info_cleanup(&info_custom);
2847 }
2848 
2849 
testICC()2850 void testICC() {
2851   std::cout << "testICC" << std::endl;
2852   // approximate srgb (gamma function not exact)
2853   std::string icc_near_srgb_base64 =
2854       "AAABwHRlc3QCQAAAbW50clJHQiBYWVogB+MAAQABAAAAAAAAYWNzcFNHSSAAAAABAAAAAAAAAAAA"
2855       "AAAAAAAAAAAAAAEAAPbWAAEAAAAA0y10ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2856       "AAAAAAAAAAAAAAAAAAAAAAAJY3BydAAAAPAAAAANZGVzYwAAAQAAAABfd3RwdAAAAWAAAAAUclhZ"
2857       "WgAAAXQAAAAUZ1hZWgAAAYgAAAAUYlhZWgAAAZwAAAAUclRSQwAAAbAAAAAOZ1RSQwAAAbAAAAAO"
2858       "YlRSQwAAAbAAAAAOdGV4dAAAAABDQzAgAAAAAGRlc2MAAAAAAAAABXRlc3QAZW5VUwAAAAAAAAAA"
2859       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2860       "AAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAG+gAAA49AAAA5BYWVogAAAA"
2861       "AAAAYpYAALeHAAAY2VhZWiAAAAAAAAAkngAAD4QAALbCY3VydgAAAAAAAAABAjMAAA==";
2862   std::vector<unsigned char> icc_near_srgb;
2863   fromBase64(icc_near_srgb, icc_near_srgb_base64);
2864   lodepng::State state_near_srgb;
2865   lodepng_set_icc(&state_near_srgb.info_png, "near_srgb", icc_near_srgb.data(), icc_near_srgb.size());
2866 
2867   // a made up RGB model.
2868   // it causes (when converting from this to srgb) green to become softer green, blue to become softer blue, red to become orange.
2869   // this model intersects sRGB, but some parts are outside of sRGB, some parts of sRGB are outside of this one.
2870   // so when converting between this and sRGB and clipping the values to 8-bit, and then converting back, the values will not be the same due to this clipping
2871   std::string icc_orange_base64 =
2872       "AAABwHRlc3QCQAAAbW50clJHQiBYWVogB+MAAQABAAAAAAAAYWNzcFNHSSAAAAABAAAAAAAAAAAA"
2873       "AAAAAAAAAAAAAAMAAPbWAAEAAAAA0y10ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2874       "AAAAAAAAAAAAAAAAAAAAAAAJY3BydAAAAPAAAAANZGVzYwAAAQAAAABfd3RwdAAAAWAAAAAUclhZ"
2875       "WgAAAXQAAAAUZ1hZWgAAAYgAAAAUYlhZWgAAAZwAAAAUclRSQwAAAbAAAAAOZ1RSQwAAAbAAAAAO"
2876       "YlRSQwAAAbAAAAAOdGV4dAAAAABDQzAgAAAAAGRlc2MAAAAAAAAABXRlc3QAZW5VUwAAAAAAAAAA"
2877       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2878       "AAAAAAAAAAAAAFhZWiAAAAAAAAE7uwABAAAAARmZWFlaIAAAAAAAANAHAACTTAAACrRYWVogAAAA"
2879       "AAAABOMAAFd4AAAFzVhZWiAAAAAAAAAh6gAAFTsAAMKqY3VydgAAAAAAAAABAoAAAA==";
2880   std::vector<unsigned char> icc_orange;
2881   fromBase64(icc_orange, icc_orange_base64);
2882   lodepng::State state_orange;
2883   lodepng_set_icc(&state_orange.info_png, "orange", icc_orange.data(), icc_orange.size());
2884 
2885   // A made up RGB model which is a superset of sRGB, and has R/G/B shifted around (so it greatly alters colors)
2886   // Since this is a superset of sRGB, converting from sRGB to this model, and then back, should be lossless, but the opposite not necessarily.
2887   std::string icc_super_base64 =
2888       "AAABwHRlc3QCQAAAbW50clJHQiBYWVogB+MAAQABAAAAAAAAYWNzcFNHSSAAAAABAAAAAAAAAAAA"
2889       "AAAAAAAAAAAAAAEAAPbWAAEAAAAA0y10ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2890       "AAAAAAAAAAAAAAAAAAAAAAAJY3BydAAAAPAAAAANZGVzYwAAAQAAAABfd3RwdAAAAWAAAAAUclhZ"
2891       "WgAAAXQAAAAUZ1hZWgAAAYgAAAAUYlhZWgAAAZwAAAAUclRSQwAAAbAAAAAOZ1RSQwAAAbAAAAAO"
2892       "YlRSQwAAAbAAAAAOdGV4dAAAAABDQzAgAAAAAGRlc2MAAAAAAAAABXRlc3QAZW5VUwAAAAAAAAAA"
2893       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2894       "AAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAFW+AADL3f//70ZYWVogAAAA"
2895       "AAAAJqD////UAADsUFhZWiAAAAAAAAB6dgAANE////eXY3VydgAAAAAAAAABAjMAAA==";
2896   std::vector<unsigned char> icc_super;
2897   fromBase64(icc_super, icc_super_base64);
2898   lodepng::State state_super;
2899   lodepng_set_icc(&state_super.info_png, "super", icc_super.data(), icc_super.size());
2900 
2901   // A made up RGB model which is a subset of sRGB, and has R/G/B shifted around (so it greatly alters colors)
2902   // Since this is a subset of sRGB, converting to sRGB from this model, and then back, should be lossless, but the opposite not necessarily.
2903   std::string icc_sub_base64 =
2904       "AAABwHRlc3QCQAAAbW50clJHQiBYWVogB+MAAQABAAAAAAAAYWNzcFNHSSAAAAABAAAAAAAAAAAA"
2905       "AAAAAAAAAAAAAAEAAPbWAAEAAAAA0y10ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2906       "AAAAAAAAAAAAAAAAAAAAAAAJY3BydAAAAPAAAAANZGVzYwAAAQAAAABfd3RwdAAAAWAAAAAUclhZ"
2907       "WgAAAXQAAAAUZ1hZWgAAAYgAAAAUYlhZWgAAAZwAAAAUclRSQwAAAbAAAAAOZ1RSQwAAAbAAAAAO"
2908       "YlRSQwAAAbAAAAAOdGV4dAAAAABDQzAgAAAAAGRlc2MAAAAAAAAABXRlc3QAZW5VUwAAAAAAAAAA"
2909       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2910       "AAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAHEEAABy1AAAr8ZYWVogAAAA"
2911       "AAAAV5kAAEPkAAAMs1hZWiAAAAAAAAAuNwAASUcAABazY3VydgAAAAAAAAABAjMAAA==";
2912 
2913   std::vector<unsigned char> icc_sub;
2914   fromBase64(icc_sub, icc_sub_base64);
2915   lodepng::State state_sub;
2916   lodepng_set_icc(&state_sub.info_png, "sub", icc_sub.data(), icc_sub.size());
2917 
2918   // make 8-pixel image with following colors: white, gray, red, darkred, green, darkgreen, blue, darkblue
2919   unsigned w = 4, h = 2;
2920   std::vector<unsigned char> im(w * h * 4, 255);
2921   im[0 * 4 + 0] = 255; im[0 * 4 + 1] = 255; im[0 * 4 + 2] = 255;
2922   im[1 * 4 + 0] = 128; im[1 * 4 + 1] = 128; im[1 * 4 + 2] = 128;
2923   im[2 * 4 + 0] = 255; im[2 * 4 + 1] =   0; im[2 * 4 + 2] =   0;
2924   im[3 * 4 + 0] = 128; im[3 * 4 + 1] =   0; im[3 * 4 + 2] =   0;
2925   im[4 * 4 + 0] =   0; im[4 * 4 + 1] = 255; im[4 * 4 + 2] =   0;
2926   im[5 * 4 + 0] =   0; im[5 * 4 + 1] = 128; im[5 * 4 + 2] =   0;
2927   im[6 * 4 + 0] =   0; im[6 * 4 + 1] =   0; im[6 * 4 + 2] = 255;
2928   im[7 * 4 + 0] =   0; im[7 * 4 + 1] =   0; im[7 * 4 + 2] = 128;
2929 
2930 
2931   {
2932     std::vector<unsigned char> im2(w * h * 4, 255);
2933     assertNoError(convertToSrgb(im2.data(), im.data(), w, h, &state_orange));
2934 
2935     ASSERT_NEAR(255, im2[0 * 4 + 0], 1); ASSERT_NEAR(255, im2[0 * 4 + 1], 1); ASSERT_NEAR(255, im2[0 * 4 + 2], 1);
2936     ASSERT_NEAR(117, im2[1 * 4 + 0], 1); ASSERT_NEAR(117, im2[1 * 4 + 1], 1); ASSERT_NEAR(117, im2[1 * 4 + 2], 1);
2937     ASSERT_NEAR(255, im2[2 * 4 + 0], 1); ASSERT_NEAR(151, im2[2 * 4 + 1], 1); ASSERT_NEAR(  0, im2[2 * 4 + 2], 1);
2938     ASSERT_NEAR(145, im2[3 * 4 + 0], 1); ASSERT_NEAR( 66, im2[3 * 4 + 1], 1); ASSERT_NEAR(  0, im2[3 * 4 + 2], 1);
2939     ASSERT_NEAR(  0, im2[4 * 4 + 0], 1); ASSERT_NEAR(209, im2[4 * 4 + 1], 1); ASSERT_NEAR(  0, im2[4 * 4 + 2], 1);
2940     ASSERT_NEAR(  0, im2[5 * 4 + 0], 1); ASSERT_NEAR( 95, im2[5 * 4 + 1], 1); ASSERT_NEAR(  0, im2[5 * 4 + 2], 1);
2941     ASSERT_NEAR(  0, im2[6 * 4 + 0], 1); ASSERT_NEAR( 66, im2[6 * 4 + 1], 1); ASSERT_NEAR(255, im2[6 * 4 + 2], 1);
2942     ASSERT_NEAR(  0, im2[7 * 4 + 0], 1); ASSERT_NEAR( 25, im2[7 * 4 + 1], 1); ASSERT_NEAR(120, im2[7 * 4 + 2], 1);
2943 
2944     // Cannot test the inverse direction to see if same as original, because the color model here has values
2945     // outside of sRGB so several values were clipped.
2946   }
2947 
2948   {
2949     std::vector<unsigned char> im2(w * h * 4, 255);
2950     // convert between the two in one and then the other direction
2951     assertNoError(convertRGBModel(im2.data(), im.data(), w, h, &state_near_srgb, &state_sub, 3));
2952     std::vector<unsigned char> im3(w * h * 4, 255);
2953     assertNoError(convertRGBModel(im3.data(), im2.data(), w, h, &state_sub, &state_near_srgb, 3));
2954     // im3 should be same as im (allow some numerical errors), because we converted from a subset of sRGB to sRGB
2955     // and then back.
2956     // If state_super was used here instead (with a superset RGB color model), the test below would faill due to
2957     // the clipping of the values in the 8-bit chars (due to the superset being out of range for sRGB)
2958     for(size_t i = 0; i < im.size(); i++) {
2959       // due to the gamma (trc), small values are very imprecise (due to the 8-bit char step in between), so allow more distance there
2960       int tolerance = im[i] < 32 ? 16 : 1;
2961       ASSERT_NEAR(im[i], im3[i], tolerance);
2962     }
2963   }
2964 
2965   {
2966     std::vector<unsigned char> im2(w * h * 4, 255);
2967     assertNoError(convertFromSrgb(im2.data(), im.data(), w, h, &state_super));
2968     std::vector<unsigned char> im3(w * h * 4, 255);
2969     assertNoError(convertToSrgb(im3.data(), im2.data(), w, h, &state_super));
2970     for(size_t i = 0; i < im.size(); i++) {
2971       int tolerance = im[i] < 32 ? 16 : 1;
2972       ASSERT_NEAR(im[i], im3[i], tolerance);
2973     }
2974   }
2975 }
2976 
2977 
testICCGray()2978 void testICCGray() {
2979   std::cout << "testICCGray" << std::endl;
2980   // Grayscale, Gamma 2.2, sRGB whitepoint
2981   std::string icc22_base64 =
2982       "AAABSHRlc3QCQAAAbW50ckdSQVlYWVogB+MAAQABAAAAAAAAYWNzcFNHSSAAAAABAAAAAAAAAAAA"
2983       "AAAAAAAAAAAAAAMAAPbWAAEAAAAA0y10ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2984       "AAAAAAAAAAAAAAAAAAAAAAAEY3BydAAAALQAAAANZGVzYwAAAMQAAABfd3RwdAAAASQAAAAUa1RS"
2985       "QwAAATgAAAAOdGV4dAAAAABDQzAgAAAAAGRlc2MAAAAAAAAABXRlc3QAZW5VUwAAAAAAAAAAAAAA"
2986       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2987       "AAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMY3VydgAAAAAAAAABAjMAAA==";
2988   std::vector<unsigned char> icc22;
2989   fromBase64(icc22, icc22_base64);
2990   lodepng::State state22;
2991   state22.info_raw.colortype = LCT_GREY;
2992   lodepng_set_icc(&state22.info_png, "gray22", icc22.data(), icc22.size());
2993 
2994   // Grayscale, Gamma 2.9, custom whitepoint
2995   std::string icc29_base64 =
2996       "AAABSHRlc3QCQAAAbW50ckdSQVlYWVogB+MAAQABAAAAAAAAYWNzcFNHSSAAAAABAAAAAAAAAAAA"
2997       "AAAAAAAAAAAAAAMAAPbWAAEAAAAA0y10ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2998       "AAAAAAAAAAAAAAAAAAAAAAAEY3BydAAAALQAAAANZGVzYwAAAMQAAABfd3RwdAAAASQAAAAUa1RS"
2999       "QwAAATgAAAAOdGV4dAAAAABDQzAgAAAAAGRlc2MAAAAAAAAABXRlc3QAZW5VUwAAAAAAAAAAAAAA"
3000       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3001       "AAAAAAAAAFhZWiAAAAAAAAE7uwABAAAAARmZY3VydgAAAAAAAAABAuYAAA==";
3002   std::vector<unsigned char> icc29;
3003   fromBase64(icc29, icc29_base64);
3004   lodepng::State state29;
3005   state29.info_raw.colortype = LCT_GREY;
3006   lodepng_set_icc(&state29.info_png, "gray29", icc29.data(), icc29.size());
3007 
3008   // Grayscale, Gamma 1.5, custom whitepoint
3009   std::string icc15_base64 =
3010       "AAABSHRlc3QCQAAAbW50ckdSQVlYWVogB+MAAQABAAAAAAAAYWNzcFNHSSAAAAABAAAAAAAAAAAA"
3011       "AAAAAAAAAAAAAAMAAPbWAAEAAAAA0y10ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3012       "AAAAAAAAAAAAAAAAAAAAAAAEY3BydAAAALQAAAANZGVzYwAAAMQAAABfd3RwdAAAASQAAAAUa1RS"
3013       "QwAAATgAAAAOdGV4dAAAAABDQzAgAAAAAGRlc2MAAAAAAAAABXRlc3QAZW5VUwAAAAAAAAAAAAAA"
3014       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
3015       "AAAAAAAAAFhZWiAAAAAAAAE7uwABAAAAARmZY3VydgAAAAAAAAABAYAAAA==";
3016   std::vector<unsigned char> icc15;
3017   fromBase64(icc15, icc15_base64);
3018   lodepng::State state15;
3019   state15.info_raw.colortype = LCT_GREY;
3020   lodepng_set_icc(&state15.info_png, "gray15", icc15.data(), icc15.size());
3021 
3022 
3023   // make 8-pixel grayscale image with different shades of gray
3024   unsigned w = 4, h = 2;
3025   std::vector<unsigned char> im(w * h, 255);
3026   im[0] = 0;
3027   im[1] = 40;
3028   im[2] = 80;
3029   im[3] = 120;
3030   im[4] = 160;
3031   im[5] = 200;
3032   im[6] = 240;
3033   im[7] = 255;
3034 
3035   {
3036     std::vector<unsigned char> im2(w * h, 255);
3037     assertNoError(convertToSrgb(im2.data(), im.data(), w, h, &state29));
3038 
3039     ASSERT_NEAR(0, im2[0], 1);
3040     ASSERT_NEAR(15, im2[1], 1);
3041     ASSERT_NEAR(52, im2[2], 1);
3042     ASSERT_NEAR(94, im2[3], 1);
3043     ASSERT_NEAR(139, im2[4], 1);
3044     ASSERT_NEAR(187, im2[5], 1);
3045     ASSERT_NEAR(236, im2[6], 1);
3046     ASSERT_NEAR(255, im2[7], 1);
3047 
3048     std::vector<unsigned char> im3(w * h, 255);
3049     assertNoError(convertFromSrgb(im3.data(), im2.data(), w, h, &state29));
3050 
3051     for(size_t i = 0; i < 8; i++) {
3052       ASSERT_NEAR(im[i], im3[i], 1);
3053     }
3054   }
3055 
3056   {
3057     std::vector<unsigned char> im2(w * h , 255);
3058     assertNoError(convertRGBModel(im2.data(), im.data(), w, h, &state22, &state15, 3));
3059     std::vector<unsigned char> im3(w * h, 255);
3060     assertNoError(convertRGBModel(im3.data(), im2.data(), w, h, &state15, &state22, 3));
3061     for(size_t i = 0; i < im.size(); i++) {
3062       int tolerance = im[i] < 16 ? 8 : 1;
3063       ASSERT_NEAR(im[i], im3[i], tolerance);
3064     }
3065   }
3066 }
3067 
3068 // input is base64-encoded png image and base64-encoded RGBA pixels (8 bit per channel)
testBase64Image(const std::string & png64,bool expect_error,unsigned expect_w,unsigned expect_h,const std::string & expect_md5)3069 void testBase64Image(const std::string& png64, bool expect_error, unsigned expect_w, unsigned expect_h, const std::string& expect_md5) {
3070   std::vector<unsigned char> png, pixels;
3071   fromBase64(png, png64);
3072 
3073   std::vector<unsigned char> decoded;
3074   unsigned w, h;
3075   unsigned error = lodepng::decode(decoded, w, h, png);
3076   if(expect_error) {
3077     ASSERT_EQUALS(true, error != 0);
3078     return;
3079   }
3080   assertNoError(error);
3081   ASSERT_EQUALS(expect_w, w);
3082   ASSERT_EQUALS(expect_h, h);
3083   ASSERT_EQUALS(expect_md5, md5sum(decoded));
3084 
3085   // test decoding without alpha channel
3086   {
3087     size_t numpixels = w * h;
3088     std::vector<unsigned char> expected_rgb(numpixels * 3);
3089     for(size_t i = 0; i < numpixels; i++) {
3090       expected_rgb[i * 3 + 0] = decoded[i * 4 + 0];
3091       expected_rgb[i * 3 + 1] = decoded[i * 4 + 1];
3092       expected_rgb[i * 3 + 2] = decoded[i * 4 + 2];
3093     }
3094     std::vector<unsigned char> rgb;
3095     ASSERT_NO_PNG_ERROR(lodepng::decode(rgb, w, h, png, LCT_RGB));
3096     ASSERT_EQUALS(expect_w, w);
3097     ASSERT_EQUALS(expect_h, h);
3098     ASSERT_EQUALS(expected_rgb, rgb);
3099   }
3100 
3101   // test decoding 16-bit RGBA
3102   // TODO: get an additional md5sum for 16-bit pixels instead to compare with
3103   {
3104     size_t numpixels = w * h;
3105     std::vector<unsigned char> rgba16;
3106     ASSERT_NO_PNG_ERROR(lodepng::decode(rgba16, w, h, png, LCT_RGBA, 16));
3107     ASSERT_EQUALS(expect_w, w);
3108     ASSERT_EQUALS(expect_h, h);
3109     std::vector<unsigned char> rgba8(numpixels * 4);
3110     for(size_t i = 0; i < numpixels; i++) {
3111       rgba8[i * 4 + 0] = rgba16[i * 8 + 0];
3112       rgba8[i * 4 + 1] = rgba16[i * 8 + 2];
3113       rgba8[i * 4 + 2] = rgba16[i * 8 + 4];
3114       rgba8[i * 4 + 3] = rgba16[i * 8 + 6];
3115     }
3116     ASSERT_EQUALS(decoded, rgba8);
3117   }
3118 
3119   // test decoding 16-bit RGB
3120   {
3121     size_t numpixels = w * h;
3122     std::vector<unsigned char> expected_rgb(numpixels * 3);
3123     for(size_t i = 0; i < numpixels; i++) {
3124       expected_rgb[i * 3 + 0] = decoded[i * 4 + 0];
3125       expected_rgb[i * 3 + 1] = decoded[i * 4 + 1];
3126       expected_rgb[i * 3 + 2] = decoded[i * 4 + 2];
3127     }
3128     std::vector<unsigned char> rgb16;
3129     ASSERT_NO_PNG_ERROR(lodepng::decode(rgb16, w, h, png, LCT_RGB, 16));
3130     ASSERT_EQUALS(expect_w, w);
3131     ASSERT_EQUALS(expect_h, h);
3132     std::vector<unsigned char> rgb8(numpixels * 3);
3133     for(size_t i = 0; i < numpixels; i++) {
3134       rgb8[i * 3 + 0] = rgb16[i * 6 + 0];
3135       rgb8[i * 3 + 1] = rgb16[i * 6 + 2];
3136       rgb8[i * 3 + 2] = rgb16[i * 6 + 4];
3137     }
3138     ASSERT_EQUALS(expected_rgb, rgb8);
3139   }
3140 }
3141 // input is base64-encoded png image and base64-encoded RGBA pixels (8 bit per channel)
testPngSuiteImage(const std::string & png64,const std::string & name,bool expect_error,unsigned expect_w,unsigned expect_h,const std::string & expect_md5)3142 void testPngSuiteImage(const std::string& png64, const std::string& name, bool expect_error, unsigned expect_w, unsigned expect_h, const std::string& expect_md5) {
3143   std::cout << "testPngSuiteImage: " << name << std::endl;
3144 
3145   testBase64Image(png64, expect_error, expect_w, expect_h, expect_md5);
3146 }
3147 
3148 
3149 // Tests base64-encoded PngSuite images' pixels against expected md5 sum of their pixels
testPngSuite()3150 void testPngSuite() {
3151   std::cout << "testPngSuite" << std::endl;
3152   /*
3153   LICENSE of the PngSuite images:
3154 
3155   PngSuite
3156   --------
3157 
3158   Permission to use, copy, modify and distribute these images for any
3159   purpose and without fee is hereby granted.
3160 
3161 
3162   (c) Willem van Schaik, 1996, 2011
3163   */
3164 
3165   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQAAAAEsBnfPAAAABGdBTUEAAYagMeiWXwAAAJBJREFUeJwtjTEOwjAMRd/GgsQVGHoApC4Zergeg7En4AxWOQATY6WA2FgsZckQNXxLeLC/v99PcBaMGeesuXCj8tHe2Wlc5b9ZY9/ZKq9Mn9kn6kSeZIffW5w255m5G98IK01L1AFP5AFLAat6F67mlNKNMootY4N6cEUeFkhwLZqf9KEdL3pRqiHloYx//QCU41EdZhgi8gAAAABJRU5ErkJggg==",
3166       "basi0g01.png", false, 32, 32, "4336909be7bff35103266c9b215ab516");
3167   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAgAAAAFrpg0fAAAABGdBTUEAAYagMeiWXwAAAFFJREFUeJxjUGLoYADhcoa7YJyTw3DsGJSUlgYxNm5EZ7OuZ13PEPUh6gMDkMHKAGRE4RZDSCBkEUpIUscQuuo/GMMZGAIMMEEEA6YKwaCSOQCcUoBNhbbZfQAAAABJRU5ErkJggg==",
3168       "basi0g02.png", false, 32, 32, "b16bee35e71dce6c08c2447a62ccedea");
3169   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAAHk5vi/AAAABGdBTUEAAYagMeiWXwAAAK5JREFUeJxljlERwjAQRBccFBwUHAQchDoodRDqINRBwEHBQcFBwEGRECRUA5lJmM7Nftzs7bub28OywrZFdUX7xLrBvkNzR/fGanc8I9YNsV6I9cViczilQWwuaRqbR1qJzSftoSiVro39q0PWHlkHZPXIOiJrQNZpvsMH+TJHcBaHcjq/Mf+DoihLpbSua2OsZSCtcwyk7XsG0g4DA2m9ZyDtODKQNgQG0k4TgR8ngeup000HFgAAAABJRU5ErkJggg==",
3170       "basi0g04.png", false, 32, 32, "0b40ec7e4231183b51e1c23f818a955f");
3171   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAAEhFhW+AAAABGdBTUEAAYagMeiWXwAAALVJREFUeJy1kF0KwjAQhJ26yBxCxHv4Q88lPoh4sKoXEQ8hS9ymviQPXSGllM7T5JvNMiwWJBFVFRVJmKpCSCKoKlYkoaqKiyTFj5mZmQgTCYmgSgDXbCwJ52zyGtyyCTk6ZVNXfaFxQKLFnnDsv6OI3/HwO4L7gr0H8F98sT+AuwetL9YMARw8WI7v8fTgO77HzoMtypJ66gBeQxtiV5Y0UwewGchF5r/Du5h2nYT577AupsAPm7n/RegfnygAAAAASUVORK5CYII=",
3172       "basi0g08.png", false, 32, 32, "f6470f9f6296c5109e2bd730fe203773");
3173   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAFxhsn9AAAABGdBTUEAAYagMeiWXwAAAOJJREFUeJy1kTsOwjAQRMdJCqj4XYHD5DAcj1Okyg2okCyBRLOSC0BDERKCI7xJVmgaa/X8PFo7oESJEtkaTeLDjdjjgCMe7eTE96FGd3AL7HvZsdNEaJMVo0GNGm775bgwW6Afj/SAjAY+JsYNXIHtz2xYxTXiUoOek4AbFcCnDYEK4NMGsgXcMrGHJytkBX5HIP8FAhVANIMVIBVANMPfgUAFEM3wAVyG5cxcecY5/dup3LVFa1HXmA61LY59f6Ygp1Eg1gZGQaBRILYGdxoFYmtAGgXx9YmCfPD+RMHwuuAFVpjuiRT///4AAAAASUVORK5CYII=",
3174       "basi0g16.png", false, 32, 32, "a14e204bbf905586d3763f3cc5dcb2f3");
3175   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAGLH901AAAABGdBTUEAAYagMeiWXwAAAPJJREFUeJzVk0GqBCEMRKvAe3gTPVnTczO9iddoaLVm0Qz0Z1r4WWQxoRZifFaIkZKA4xIlfdagpM8aAQCO4xKl88acN+b8w/R+Z3agf4va9bQP7tLTPgJeL/T+LUpj4aFtkRgLc22LxFhUxW2VGGP0p+C2bc8JqQDz/6KUjUCR5TyobASKZDkPZitQSpmWYM7ZBhgrmgGovgClZASm7eGCsSI7QCXjLE3jQwRjRXaAyTqtpsmbc4Zaqy/AlJINkBogP13f4ZcNKEVngybP+6/v/NMGVPRtEZvkeT+Cc4f8DRidW8TWmjwj1Fp/24AxRleDN99NCjEh/D0zAAAAAElFTkSuQmCC",
3176       "basi2c08.png", false, 32, 32, "512c3874e30061e623739e2f9adc4eba");
3177   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAAHbjwF2AAAABGdBTUEAAYagMeiWXwAAAgpJREFUeJzVliFz4zAQhT/PGDjMYaGBgYWlPlZ4f6E/oTCFLjtYeLSwsDCBuX9wMAcLU+awV6CokSu7kWO58Qns7LxZvX3PK0VJJAnWbwDrHdg8tUl9ZUVq644QQJE7OywEUEyTbdWpx+LG67G48XpY6NBD2lbwbw+fYuUhe2ujobdvbJ6Z6GlqKnLixPseTUUukuyWUrgHSG0Stmab4A2zjZEUsMGWHjdUYaVfdmgqhcNnrW9oL/U6nCo1MZF2S3i7B9jdw8l8GVDzkWdFx7mFLHPC8hJgWkZqUCcFyDOAaci56E76uUHrOTqX1Mn9YxSDFCCfHB00NOhH6tY4DeKR1vJqJcHrtQR/XyTYXEnw8izB00KCxycJyrkEd78luJ1J8PNRgiKX4OqXBPNMgryUACRI7eUYZuVlau9dfGo4XLTYDmpTjOugTm3ySA6aqE3e20E7tcl7ODhFbfLU/sLHpwaYPnR00IX66CCoQXdqgwc4OJc6wEE/6i8dxKBucRCP2nMQm9rkiVStYL+Geqw85Ex8FYmnEc+Kgd+bIZZ52W0c7D2Lu+qiASYm34x4Au2iAbLS4CObQJhoFx/BBLqLdvELTaCfaBf/xgnEE+3iZ/0furRogMkPgOzPABMYXrSLR7oD3yvare8xgcuJdvGOExiHaBcPmMD4RLt4ywTGLdrFnQn8P6Jd/B2kFN6z3xNE9wAAAABJRU5ErkJggg==",
3178       "basi2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3179   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAAE+s9ghAAAABGdBTUEAAYagMeiWXwAAAAZQTFRF7v8iImb/bBrSJgAAAClJREFUeJxjYICCD1C4CgpD0bCxMcOZM9hJCININj8QQIgPQAAhKBADAAm6Qi12qcOeAAAAAElFTkSuQmCC",
3180       "basi3p01.png", false, 32, 32, "1ba59f527ff2cfdc68bb0c3487862e91");
3181   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAgMAAAF5E6LxAAAABGdBTUEAAYagMeiWXwAAAANzQklUAQEBfC53ggAAAAxQTFRFAP8A/wAA//8AAAD/ZT8rugAAAFFJREFUeJxjeMewmwGEXRgEwdjMjCE5GUreuAFi9Pais78u+LqAgT+KP4oByPjKAGTw4xZDSCBkEUpIUvc/dBUYIxiYQqugLAQDKvEfwaCSOQC0Wn3pH3XhAwAAAABJRU5ErkJggg==",
3182       "basi3p02.png", false, 32, 32, "0528e9ac365252a8c0e2d9ced8a2cc6b");
3183   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAAH2U1dRAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAC1QTFRFIgD/AP//iAD/Iv8AAJn//2YA3QD/d/8A/wAAAP+Z3f8A/wC7/7sAAET/AP9E0rBJvQAAALZJREFUeJxj6KljOP6QoU6W4eElhihLhsVTGCwdGKawMcQst5vIAMS+DEDMxADE2Qytp4pfQiSADBGILJBxAaIEyFCDqOsIPbOq3PjdTAYoLcgApV0YoPRdBhjNAKWVGKB0GgOU3o0wB9NATJMxrcC0C9NSTNsxnYFwT0do6Jkzq1aVlxsbv3s3cyamACpXUBBTAJXr4oIpgMq9exdTAI3LgCmAylVSwhRA5aalYQqgcnfvxhAAALN26mgMdNBfAAAAAElFTkSuQmCC",
3184       "basi3p04.png", false, 32, 32, "a339593b0d82103e30ed7b00afd68816");
3185   testPngSuiteImage("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",
3186       "basi3p08.png", false, 32, 32, "d36bdbefc126ef50bd57d51eb38f2ac4");
3187   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAAGudILpAAAABGdBTUEAAYagMeiWXwAAAI1JREFUeJztj80KgzAMx3+BHvTWvUH7KPbB9yhzT7Dt5LUeHBWiEkFWhpgQGtL/RyIZOhLJ3Zli2UgOJAvzgECcs/ygoZsDyb7wA5Hoek2pMpAXeDw3VaVbMHTUADx/biG5Wbt+Lve2LD4W4FKoZnFYQQZovtmqd8+kNR2sMG8wBU6wwQlOuDb4hw2OCozsTz0JHVlVXQAAAABJRU5ErkJggg==",
3188       "basi4a08.png", false, 32, 32, "e2212ec5fa026a41826136e983bf92b2");
3189   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAQAAAH+5F6qAAAABGdBTUEAAYagMeiWXwAACt5JREFUeJyNl39wVNd1xz9aPUlvd9Hq7a4QQjIST4jfhKAYHByEBhY10NRmCeMacAYT0ZpmpjQOjmIS9JzpOE/UNXZIXOKp8SDGQxOwYzeW49SuIy0OKzA2DlCCDQjQggSykLR6Vyvt6q10teofT0wybTyTP75zztw/7nzPued8z7nZAOZM+M3rYNdAljkTjBumPhCHJUssg5EWGIibOoy0Cuu7h7LtGvj2lqrnb96MCM0P2SENfj4PNh6AS/eBMm005D+xKaR1/Dcs442dyst/gM/2hzR1nmUElr5xQ1nfBw/Nf2NnZyfiygLICmkQESH/Fg9s8ULoNBxNwtEUXHjLMhRzJvTfhk+fCGnrfxDSru6HQ7st49FoRDx5KSJclgF3WqGjA5Z3WYaqW8bpGdDZCX2NkFX1HHQNVD2/sQ829sPK78B/TnXwq6mQpasQ0v4Iy4CI+CMU5Zbu/vAlXa3wwogHEv8BV5PQloTKt8/WKw+0Q9s2XT2+TVfXPgOdBfDr78O92Wfrv3QYoTzQDkt6oOUPunrqKV195xo8lHO2fumPEMX7QLm/C6QL1h6BE0JXf1RhGTOfRuTNBmUElLfnwLUgHDsHRtnZ+p+PYV/fDbV7oKwOlLfnQksFrDp0tn7eVxGeTjjzDDT9C9y/ELICKd29cI9mbuyDjX1Ocu7mYeyRmJ2lqxCzdffsfpgT//8IpqA9OInCP/GDMNFsGUpIg57fwc2XdPU3DbraewtGs8EzBiVDUGBDv8eJ4+MS+KgUMo9bxsKCmF36qWUrIQ0S7TDghe4P4co2Xf1Zq64mimD6NPA/B+fuOElI/8IyVo3E7PIfW3ZRPRQ0gRLSQLbDWD6kP4LkMzCwHS6X6upX39XV1wRcjVqGURuzS75p2b5ucDdCbh8oh0GxDBjtBDsCw+tgoANufg8iT8OOxyyjogIOvgzeOljUBNMWQMFhcL8PeRooEQFiLvS9Aze/DBe+BjmrLSPssli/FzFzOxz6V2jOwP7dUL0CZu+B6VMhuBWyNh6A7rDu7timq65yzayKwpIoVJ2AqigUb4fzK+Hcn+B8DcxLxuyyV2O2EhGQ1WYZs962qNyAmLULZo1D8T7whEHZCtp5KGuGsWZQvwVFTXD9EXivGbI0E3T18yEMiNmfDyVrltZ4M+w38+IwJQ7+OCT7ncROxEH+LYwEIRGEeBB6gtAVhFgh6GpsxDUrDC5TMzu26eotW1f7fqKrg/N11T6hq5lHdHUsX1eT39PVgeu62lOrqzdf19Wrhbo6u99hqFRuAPcCuFqumZcX+E3fszDttvOkmWOQ9oH1EnSXwrV2uHgPLGqM2eVxKFZBmRUG33mYEoVPFmrmBcVvFtVCZS3Ib0GyAz5rgSs/gzOtsOxWzK6cA8WrIXj3gsJTEIyC/wn4vVszT8/xm7PTMPoxDNTDJ3egpRdq18TsubehZC8E4uBTwVW5AeannHevroZwG3g2a2bkaV0d+rWuXi7V1SO9urq1CGpr4b7b8IVGp1P1uwxkFEajMPIYLH4YlkagZbVmnlvpN799AF5YF7Pn3YZALXhPQ14j5MRBUUEJHIPMi5DJh/EykI9C+Sqo2AFLl2nma68KoyoK+bsgtwKU98C1GVy/gCwTlGtvQlrAyEoYPAZ3quHi/bB/GXx8JmYfPIhx+DhG6D4ob4FAKUxpALUGcm3IXluurrm90K/ELvuVT0b9SlutX3llhV/ZdUrIvzopZO4SIY8/Zdf8/kM7MnpGyORXhBxeJ2QyKWQyI6TrejNc8jhN0tYGb1XD+raYvSgas93vx+ySUMyuWROz05cso6XFUaSLDY68xWzInnVOXXMjx69c8viVj572K9UrhLzXFnLBvULOfFxI+5aQiRIhZYeQN27YNV3ftyOZ+UKO+YQc7RRSud4MnZvgcg0sORGzZ0ehJAoFByA7Cu4mKFwJ5T8GayWcexzj4k2M1CswbINyvRmub3f6W0/B9DLwfx3cSXANQW47+G5D0VswYzUMe+HScoz2IEbahmzrirpmVlhIXQpZNl/IezYJWZwt5NQlQga3Cpn+GyGHPxIydUjI9KCQsk3IzItCDjTbNVafHcnSTBCG1ug/CoFjcNf+pT7AwGYH1pa/3Le2gGaKBkVXIREGK+w3r2/RzEIThhtg5AKkMzB+HiaOgGs35DSAehI8wqn+zIsOAdkI6XWQmgFDX4PB3RA/Av2N0Pcw9C+Avk3Qb0J/MwSOCmNW2DJ8Kii6CsNhSMRBJGHgQb952auZog6GLoF9HMZmwsRzkF0HeXXgXQWjdU73AIzOgZFVkGgC6wnoPQw9TdBzHD67BD2D0OOFopAw5iUtQ4uDLwxTUpMEUmFIdsGQCoN7YWAUepf4zfM+zRyYAUP/BemLMPFFUPrBcwwKypzWBUcDBtdCfyd0fxE6n3CWpM40dNZASUIYS+osI5ALBSnIj4M3DJ5fTRJIb4CRf4aUBslGSCwHayr0r4Dubr/ZdlIz586F4Qchsx3y/g605Y5ugBP5nXfhxiG43ARXmuDKSajQhVG9wjIKb4M/Cr7T4P038MTB/U+Q9w+TBMbCMNoP6elgN8LIkzD8ZUhUw8AA9GyDGx/4zbeqNbO3C8a6ID/iiBZAdwQuroQPHoHTM2DxPmGsb7OM4lcgEHDaaEoU3M+CmoK8fsgNQ87dGhgPw/hvQSZBPg9jUUhvBrsaUikYOgkD06H7FFxe7Tf3X9PM5GOOYgK0HHS2h7+uFMauU5ZRcg0CJyG/FjweUG9BXhRy9oLyXVDikB2G7CuTBNgAE5thIgUTjTDxJEy8A5kwZDKQ+SbInTD2AdjrYHAbdHT4zaXLNBPgtVeFsWOHZRS8AuoHkLMIlF+C6+/B5QLXi5AVhawCyLoFWXHI2gD8FBRhQGYzZDyQaYTxh2D8Asi5MNYJo6NgN0Eq5OwIPb+Fi5MRv/aqMAAe3gQ7HoNFXVC8ErR68ERA7YDcXMjxgdIE2Ysh+3VwrZ2cKQYoMRtkM4zthDEvjDaAfQBGciDZBokEDByGzwRc/Qqc3uSk+oV1gqqo8wQvrIN3jmMcvAbLX4bZd2D6CgjUgc8H3lJwF4G6E3KrIScIOUdBkZME0i2QPge2B1INMFwDiU6wfgm9vdBV7VT24mPC2FokWPxDmLfPmZIA8+oh/UMorIf/OYZxpBfmPgAzWqCoCPzfAV+ZMwg9Z0ANQt6bkFc7SWCkGVJVkPTA0B4QB6D/fbjTBp1dTjvVrhFUtEPFLijPg0CTM6LB8cs7YHwXuNuhaA10HMdoiUHZDJi2z5lIWjfkfwO8QfA0g9ueJJBshqFaSHjBaoD+a9BzjyMgyxKC0iEoTUDpEExPQCDhLBfKew4Brw8C+TAyFzLLICcfpvggmA+3fRhnfFBcB4WV4O8DXxDym8F7l0DiTRhMgeWB/gZHMhc1Coo+hWkhJ6KiNTA1BP4tMGUN5IWcQgLIa4Up74K/FUZbYSICSiu4Wx29CDRCbyvGxcNQuAf8QSh4E3wlk79FcVhrtLb4zUDK+RUFRz7H/pkzgLgH4u7/Y//c2aQd8ID/qGVodaIhW0hQq+zI9FNCFucLOe0hIaeWCjl1u5DBeUIGHhdSu09I7SkhfbVC5j8rpPfrQnr/XUj3NiGzZgg5ekDIsQeFHN8r5PgqISd+ICRfEtL1j0K6KoVUHhUyZ5qQeRuEzHML6T4h5MgX7EjPe/C/SQETOWwWx8sAAAAASUVORK5CYII=",
3190       "basi4a16.png", false, 32, 32, "f1423ebc08979252299ca238656ab0ba");
3191   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAAEEfUpiAAAABGdBTUEAAYagMeiWXwAAASBJREFUeJzFlUFOwzAQRZ+lQbi7smZBuAabhh6LTRLBwRLBRSpxCipl2EDVlJBB/EgeyYrifH8/jSfj5GSAR2AP7A0fOQ+74mM6MeKTieTk6nv9vz2aa4AKuJ8b1rVTz8uwZ56WBWPXLgqSk7cze5+YjMZ/Xw4YbSDoCAQvHJcFThMJ2kDQLX4n+S4DbL/GTfD8MRemIQobatGgDfIcGrzyoBlExxAbDLVooAGQnJz545nPPY2dRmCodUBdmmDQALBeLeVeJXgLelJo4GIhGOI5mqsGOoFYCEYvGrhokPwuA+SLsQne19Js5L9ZDbkbrABQdH/sUBXOgNoOVwAoG+Uz8M5tWQC1m8sA6m0gAxTPgB+qsgDqdSgDqNepDFA6A5+CSlP0aU5zQgAAAABJRU5ErkJggg==",
3192       "basi6a08.png", false, 32, 32, "e80a60aecf13ebd863b61167ba95960b");
3193   testPngSuiteImage("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",
3194       "basi6a16.png", false, 32, 32, "4d9d6473bb7403d7f85e3e7537c34e9d");
3195   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQAAAABbAUdZAAAABGdBTUEAAYagMeiWXwAAAFtJREFUeJwtzLEJAzAMBdHr0gSySiALejRvkBU8gsGNCmFFB1Hx4IovqurSpIRszqklUwbnUzRXEuIRsiG/SyY9G0JzJSVei9qynm9qyjBpLp0pYW7pbzBl8L8fEIdJL9AvFMkAAAAASUVORK5CYII=",
3196       "basn0g01.png", false, 32, 32, "4336909be7bff35103266c9b215ab516");
3197   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAgAAAAAcoT2JAAAABGdBTUEAAYagMeiWXwAAAB9JREFUeJxjYAhd9R+M8TCIUMIAU4aPATMJH2OQuQcAvUl/gYsJiakAAAAASUVORK5CYII=",
3198       "basn0g02.png", false, 32, 32, "b16bee35e71dce6c08c2447a62ccedea");
3199   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAEhJREFUeJxjYGAQFFRSMjZ2cQkNTUsrL2cgQwCV29FBjgAqd+ZMcgRQuatWkSOAyt29mxwBVO6ZM+QIoHLv3iVHAJX77h0ZAgAfFO4B6v9B+gAAAABJRU5ErkJggg==",
3200       "basn0g04.png", false, 32, 32, "0b40ec7e4231183b51e1c23f818a955f");
3201   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAAABGdBTUEAAYagMeiWXwAAAEFJREFUeJxjZGAkABQIyLMMBQWMDwgp+PcfP2B5MBwUMMoRkGdkonlcDAYFjI/wyv7/z/iH5nExGBQwyuCVZWQEAFDl/nE14thZAAAAAElFTkSuQmCC",
3202       "basn0g08.png", false, 32, 32, "f6470f9f6296c5109e2bd730fe203773");
3203   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAYagMeiWXwAAAF5JREFUeJzV0jEKwDAMQ1E5W+9/xtygk8AoezLVKgSj2Y8/OICnuFcTE2OgOoJgHQiZAN2C9kDKBOgW3AZCJkC3oD2QMgG6BbeBkAnQLWgPpExgP28H7E/0GTjPfwAW2EvYX64rn9cAAAAASUVORK5CYII=",
3204       "basn0g16.png", false, 32, 32, "a14e204bbf905586d3763f3cc5dcb2f3");
3205   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAYagMeiWXwAAAEhJREFUeJzt1cEJADAMAkCF7JH9t3ITO0Qr9KH4zuErtA0EO4AKFPgcoO3kfUx4QIECD0qHH8KEBxQo8KB0OCOpQIG7cHejwAGCsfleD0DPSwAAAABJRU5ErkJggg==",
3206       "basn2c08.png", false, 32, 32, "512c3874e30061e623739e2f9adc4eba");
3207   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAAAOVJREFUeJzVlsEKgzAQRKfgQX/Lfrf9rfaWHgYDkoYmZpPMehiGReQ91qCPEEIAPi/gmu9kcnN+GD0nM1/O4vNad7cC6850KHCiM5fz7fJwXdEBYPOygV/o7PICeXSmsMA/dKbkGShD51xsAzXo7DIC9ehMAYG76MypZ6ANnfNJG7BAZx8uYIfOHChgjR4F+MfuDx0AtmfnDfREZ+8m0B+9m8Ao9Chg9x0Yi877jTYwA529WWAeerPAbPQoUH8GNNA5r9yAEjp7sYAeerGAKnoUyJ8BbXTOMxvwgM6eCPhBTwS8oTO/5kL+Xge7xOwAAAAASUVORK5CYII=",
3208       "basn2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3209   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAABGdBTUEAAYagMeiWXwAAAAZQTFRF7v8iImb/bBrSJgAAABVJREFUeJxj4AcCBjTiAxCgEwOkDgC7Hz/Bk4JmWQAAAABJRU5ErkJggg==",
3210       "basn3p01.png", false, 32, 32, "1ba59f527ff2cfdc68bb0c3487862e91");
3211   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAgMAAAAOFJJnAAAABGdBTUEAAYagMeiWXwAAAANzQklUAQEBfC53ggAAAAxQTFRFAP8A/wAA//8AAAD/ZT8rugAAACJJREFUeJxj+B+6igGEGfAw8MnBGKugLHwMqNL/+BiDzD0AvUl/geqJjhsAAAAASUVORK5CYII=",
3212       "basn3p02.png", false, 32, 32, "0528e9ac365252a8c0e2d9ced8a2cc6b");
3213   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAC1QTFRFIgD/AP//iAD/Iv8AAJn//2YA3QD/d/8A/wAAAP+Z3f8A/wC7/7sAAET/AP9E0rBJvQAAAEdJREFUeJxj6OgIDT1zZtWq8nJj43fvZs5kIEMAlSsoSI4AKtfFhRwBVO7du+QIoHEZyBFA5SopkSOAyk1LI0cAlbt7NxkCAODE6tEPggV9AAAAAElFTkSuQmCC",
3214       "basn3p04.png", false, 32, 32, "a339593b0d82103e30ed7b00afd68816");
3215   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYagMeiWXwAAAwBQTFRFIkQA9f/td/93y///EQoAOncAIiL//xH/EQAAIiIA/6xVZv9m/2Zm/wH/IhIA3P//zP+ZRET/AFVVIgAAy8v/REQAVf9Vy8sAMxoA/+zc7f//5P/L/9zcRP9EZmb/MwAARCIA7e3/ZmYA/6RE//+q7e0AAMvL/v///f/+//8BM/8zVSoAAQH/iIj/AKqqAQEARAAAiIgA/+TLulsAIv8iZjIA//+Zqqr/VQAAqqoAy2MAEf8R1P+qdzoA/0RE3GsAZgAAAf8BiEIA7P/ca9wA/9y6ADMzAO0A7XMA//+ImUoAEf//dwAA/4MB/7q6/nsA//7/AMsA/5mZIv//iAAA//93AIiI/9z/GjMAAACqM///AJkAmQAAAAABMmYA/7r/RP///6r/AHcAAP7+qgAASpkA//9m/yIiAACZi/8RVf///wEB/4j/AFUAABER///+//3+pP9EZv///2b/ADMA//9V/3d3AACI/0T/ABEAd///AGZm///tAAEA//XtERH///9E/yL//+3tEREAiP//AAB3k/8iANzcMzP//gD+urr/mf//MzMAY8sAuroArP9V///c//8ze/4A7QDtVVX/qv//3Nz/VVUAAABm3NwA3ADcg/8Bd3f//v7////L/1VVd3cA/v4AywDLAAD+AQIAAQAAEiIA//8iAEREm/8z/9SqAABVmZn/mZkAugC6KlUA/8vLtP9m/5sz//+6qgCqQogAU6oA/6qqAADtALq6//8RAP4AAABEAJmZmQCZ/8yZugAAiACIANwA/5MiAADc/v/+qlMAdwB3AgEAywAAAAAz/+3/ALoA/zMz7f/t/8SIvP93AKoAZgBmACIi3AAA/8v/3P/c/4sRAADLAAEBVQBVAIgAAAAiAf//y//L7QAA/4iIRABEW7oA/7x3/5n/AGYAuv+6AHd3c+0A/gAAMwAzAAC6/3f/AEQAqv+q//7+AAARIgAixP+IAO3tmf+Z/1X/ACIA/7RmEQARChEA/xER3P+6uv//iP+IAQAB/zP/uY7TYgAAAbFJREFUeJwNwQcACAQQAMBHqIxIZCs7Mwlla1hlZ+8VitCw9yoqNGiYDatsyt6jjIadlVkysve+u5jC9xTmV/qyl6bcJR7kAQZzg568xXmuE2lIyUNM5So7OMAFIhvp+YgGvEtFNnOKeJonSEvwP9NZzhHiOfLzBXPoxKP8yD6iPMXITjP+oTdfsp14lTJMJjGtOMFQfiFe4wWK8BP7qUd31hBNqMos2tKYFbRnJdGGjTzPz2yjEA1ZSKymKCM5ylaWcJrZxCZK8jgfU4vc/MW3xE7K8RUvsZb3Wc/XxCEqk4v/qMQlFvMZcZIafMOnLKM13zGceJNqPMU4KnCQAqQgbrKHpXSgFK/Qn6REO9YxjWE8Sx2SMJD4jfl8wgzy0YgPuEeUJQcD6EoWWpCaHsQkHuY9RpGON/icK0RyrvE680jG22TlHaIbx6jLnySkF+M5QxzmD6pwkTsMoSAdidqsojipuMyHzOQ4sYgfyElpzjKGErQkqvMyC7jFv9xmBM2JuTzDRDLxN4l4jF1EZjIwmhfZzSOMpT4xiH70IQG/k5En2UKcowudycsG8jCBmtwHgRv+EIeWyOAAAAAASUVORK5CYII=",
3216       "basn3p08.png", false, 32, 32, "d36bdbefc126ef50bd57d51eb38f2ac4");
3217   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAABGdBTUEAAYagMeiWXwAAADVJREFUeJxj/M/AwAGFnGg0MSKcLN8ZKAMsP4a+AaNhMBoGVDFgNBBHw4AqBowG4mgYUMMAAN8qIH3E64XIAAAAAElFTkSuQmCC",
3218       "basn4a08.png", false, 32, 32, "e2212ec5fa026a41826136e983bf92b2");
3219   testPngSuiteImage("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",
3220       "basn4a16.png", false, 32, 32, "f1423ebc08979252299ca238656ab0ba");
3221   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAYagMeiWXwAAAG9JREFUeJzt1jEKgDAMRuEnZGhPofc/VQSPIcTdxUV4HVLoUCj8H00o2YoBMF57fpz/ujODHXUFRwPKBqj5DVigB041HiJ9gFyCVOMbsEIPXNwuAHkgiJL/4qABNqB7QAeUPBAE2QAZUDZAfwEb8ABSIBqcFg+4TAAAAABJRU5ErkJggg==",
3222       "basn6a08.png", false, 32, 32, "e80a60aecf13ebd863b61167ba95960b");
3223   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAYAAAAj6qa3AAAABGdBTUEAAYagMeiWXwAADSJJREFUeJzdmV9sHNd1xn/zj7NLck0u5VqOSwSgrIcEkQDKtNvYxlKJAstNEIgWIFkuUtQyWsCQW8mKlAJecf1iLLUGWsmKDCgwUMByigC25UKh0SaIXNMpiSiJHZoERAN+kEQ0lR1LkLhLL8nd4fzrwzl3qVVVNI9BHhbfzp07d+537r3nfOeMlaZpCtB8FwCaE+3YmLh9+x/LfStNG/8hfzPfgN6x5iZ98P/B5ubfr98fWn/TD5rvZrbVRt01W/AsQGYuMwf5clqWxnRMMDH4N4LxccFI28O/F3T12tHnnW8JWj9U1PvsUjTv2aL41zr+TxT1fvT0Le97RPGQYPBrRb3fHFU013/ZIr4pc6FaguZIZhxuMkCqNhLq2VK2BL3ldFiJTynerxM7rBPSdm9SJ6SjuM8I2nrf1vvWvYpP6du0PTXj36P4RPv4kRm/T3FECU+1YzOr+KhgY8oQb5Szo7USNDdl5gCCCX8buGunJDmmU1GbCfXO4c5hyJfTfu31VTWArmD0r4rzOrFP1AC2oPNFNcBDSvwLOp8HFHUnpfp8ohj/VsdNdNw/FVz9MyX8J4rPKuHLSlOfX5k3xFcmOwvVEjTHMqMAzdHMGEDwqv9U2w5IdO1am11tJ9S7NnRtgN5yuqh3/0snWteJXtGJfqQTm1FD/LsaYlYNoe2WYqrtiV7HipHBh5W4XgerSvi6Eo6V5oLgcov48uWugVoJGlPZAqwZINjgXwZYnejY1maAeJ9ORU+52exmzYV695buLZAvpz/Vu6d1ohU1gK5EcF7Q03ZH0VaXy48Uv6Pj6P34Ax1Hr1cVAzV88w0lrO3LvxNcmjXEl2a6B6slWFno7ANoTmaGAYLf+PcDBL/2/xwg/IG3r90ApxR1U5pTbja7WXOhnjuSOwK95eTv1AA6wXDrLRP+J0FXr+29gtb7OpoeheRVHUfPcHj4lnH+Qonr9fK/CNY/N8TrR3PFWgmW7+76DKARZx2AYMovAATH/MMA4WbvAkD4Je/jNh8QbVfUI9ByP3rKzWY3ay7Ue3p6eiBfTvSsRpHgqtmqDUHPE3QcNYClBkh1dN3KYajEA8GGPr+8rDR1Fost4ouLPXdUS7Bc6SoCrOztPA3QzGXqNxsgHPHGAcJN3hxAeM7b3rYDIvUBJqAZv27cmznlZrObNRfq+Xw+D73l5EkdRb10U3FF0VW0dqoBduhoxqvr8w29XlJcVKyOGOLVar63VoJ6PZcDWKl0FgGab2T2AAT9/hWA1cmOYYBwzBsFiH7ufg0gmnDbfYBjApiJtMYg6teNezOn3Gx2s+ZCfd3b696GfDk6p4ReVAPoynlK0Nb7iXr18DUl/leC9ecEa9rvRov4jR3rxqslWDzRcxBgebmrC6BZyRQBgkW/B2B1taMDIAw8HyCaczcBRE+7rwDEE067AWxdCyNhTCQ3Ac34dePezOk0m92suVBfv339dugth3NqAPXStf/Ut9zicZpNJa5xfuFTwavvGOJXz61/pFaC2kjvOMBStTsP0GhkswDBUf8IwOpDHecBoofdXwBEl9x7AaJT7j6AuMf5HCD5Z/tv23yArafYaDcjYUwkNwHN+HXj3swpN5vdrLlQ7z/Ufwjy5aYepKoqPrdXzVUTNF78+lnBKy8Z4leO93+3WoKFT/vuAag/l3sRoDGTHQQIAt8HCCteESB8wXseIJp3BwDi3wqD5An7dYD4J8IwmbBv2QH7BY1oNdrNSBgTyU1AM37duDdzys1mN2su1De+vPFl6C0vTkvrfz+m5lLC1+4QvHjAEL+4f+PJWgmun71zJ0C9L7cA0Phl9kGA4Fn/BEAYygyiilsEiD9wHgCIv+x8DJCctx8ESMbsUYB0s3UBIHnZ3t9mAEvPvFHrLdGq2s1IGBPJTUAzft24N3PKzWY3ay7Uh4aGhiBfvnxJ71YFpz80xKenh+6rluDagbtOAiwVuicBmlszkwDha/KGqOrmAeJYZpB83z4IkKyzbwAkX7V/BZBOWcMA6SVhlG6y5gDSCat9B/BNRY37Rq0b0Wq0m5EwJpKbgGb8unFv5pSbzW7WXKjvfnz349BbfnyPIX7mzd27aiWoVvN5gODH/k6AqCYjxIGTAUhG7HGA9Kz1GECaygzSilUE4Dsyw3TeGgBgigJA+qoyeksZ/pRvtvkAVNu18jM9Ai21brSWajcjYUwkNwHN+PVWvqin3Gx2s+Zr1GWE3bvOvAmQz0sP/0BwUgwoIzin4mcA7HJSArAeS88CWJY8bx1NjwAwyyCAVUnFIJMMA1hPpSK2dvEWAP/AP94+GzSJqckFTJqiO8CIVqPdjIQxkdwENOPXjXszp1w2+5k3YfeuWmn3Lvl/5q0zb+1+HGDovulpgLveu7YNoHtwaQYgM9ncCuA9KW9wq1EewHFkBnYlKQLYM8kWAHs+GQCwptICgDWWjgJYYeoBWBNp+xFIjDTRjLyVmJr8zKQrqtZbotVoNyNhTCTXgGb8uri36WkYuq9aqlYhn5dftQpD98m96Q+nPxwaAth48uJ+gDt3ygi5BRkxW2/kAPwTkgl6nszArURFAOcBmaEzHw8A2JNJAcB+XVJs64fC0H4lebrdAForMaUIk5G3ElM1gElTWmrdiFbdAUbCmEguAe3ifth4sla6dgDuOgnBj8HfCf4BCE7CXe/BtW2w8aT0vXjg4oGNLwM05zMDAH33yIi5F+UN2cHGDIDvywy8Y+H3ALznwxcA3MvRBgAnit2bDeBsji8A2Elit9cDDiphU4MxuYBR+SYxvSU/M2rdiFaj3UTCXDkO/d+tlq6fhTt3wlIBuifFM7i98otq0D0ISzPS5/pZCZ6ZAbjy0pWX+g8BhI945wCCEX8coHt2aRAgm5UZ+JWgCNAxu7oFwJ2PBgBcWxi4+6JTAM6meA7APpEcbM8G1Qe0ik+mBmNKEUYJ3pKfmTTFqHURrVfPwfpHaqWFT6HvHjkQuQVoboXMJMQBOBmJFfEz0tbcKn3qffLMwqdS+vLOwdV3rr6zfjtANO7uAAjf874Oa5I3c7R5BMDvkRl2fLT6FQDvE2HgjkUlAPcVYehMxO0+IPq2oskF9Ay3ajAmvzMZuRrC5GeSptzYAevGq6XaCPSOy4HIvQiNX0L2QXGR3pOQjIA9DnYZkpK0ha9Btg6NnDxTfw6CEfDHIRoHdwfcGLkxsu5tgKTXrgJEkevCTUpwj/cGgH8l6AfoeF8YeOMi1t2vRT8HcP8t+nabAUI9u61yo5G2WnwyNZhWKUIzcklMq1XI99ZKiyeg5yAsVaE7D40ZyA5K6co/AVEV3DykZ8F6TH7pWXCrEOWlT/CsPNOYge5ZWBqE8D3wvg5JL9hVqNaqNdELSWLbsKYEo9PuXoCo7uYAokl3+GYDeL8LvwDgHQqPt/mA8EuKps5qyo1adTPFJ1ODkVLE4iL03FEt1euQy8mB6OoSz5DNiov0fYkVnidB03Ek9luW/NJU2uJY+oShPBMEMkajISlXR4fknq4rSbhtw+Lni5/39AAkFbsIkHxm3w0QO04MEE25BQD/cHAMIDruHoLbpMPhbiVsCsymzqrpr9H2EtfrRyFXrJWWK9BVlH3RWYRmBTJFCI6Cf0RihleUKoJbhOT7YB+EtAJWEayjkB4BuwJJEdwKREXwjkH4PfArEBQhcxSatxuvAnYR6pV6JXcEIB0UzZr02QsA8ZRTAIjLTgnA3xxcAIj3OT9oM8CqOsFWZV3jvKmzSrlxaQa6B6ul5buh6zNY2Qudp8UzZPaIi/R7YPUh6DgP4QvgPS/qwXkAknVg30D05I+AWWBQMo1ki/SJP5BnwhegYxZWt8iYwSKEe8B7A6LT4O6F5DOw74Z0UMT60uzSbPcWgHTAugyQTNrDAMnP7EcBkk32HNymHhBoXG99UtDKuhSYly9D10CttLIAnX1yILIONHOQqUPQD/6Vm7bqw+D+QupJ7gDEXwbnYymx2r8SfWkNgFWBtAj2PCQD4MxDPADuZYg2gDsP0QB0fASrX5F3BP0Q1cHNQeyAE0PSB/YCpANgXYbl+eX5rg0A6ZRVaDOAZoXJMftwmw8ItOhpvqXIJ4WVSegsVEuNKcgWoDkJmWE5IH5hDVcnoWMYwgA8H6JL4N4rMsr5IiTnwX5QBLY1DEwBBWASGAZrCtKCJOFJAZwIYlfKMVEC3icSkDvel7gUTYI7LGrFLUA8BU4Bkkmwh/U9BViZWpnqlGxwzJJ0WLPB/1UPMAUN+YjUKEN2tFZqjkFmVMySGYXgN+DfD8Ex8A9LrPDGIRwDbxSiOXA3QXQK3H2iJ+3X5WuDPQrpJUm001cl37Se0v9jkI5q3yfW0N2nY41BVNJ3jayhf1jmEpfBKUHyM7AfXcN0DKxRaIw1xrIlgPSCJP7puDUCVppmtinxCfNxNHNBPiZm5/5vbG7+/fr9ofVvbgb5NJbZ1ny3NmqZZLb5LmS2iRluxsYEZG/T/kdx/xvwP2XY7MOt27XzAAAAAElFTkSuQmCC",
3224       "basn6a16.png", false, 32, 32, "4d9d6473bb7403d7f85e3e7537c34e9d");
3225   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAAGudILpAAAABGdBTUEAAYagMeiWXwAAAI1JREFUeJztj80KgzAMx3+BHvTWvUH7KPbB9yhzT7Dt5LUeHBWiEkFWhpgQGtL/RyIZOhLJ3Zli2UgOJAvzgECcs/ygoZsDyb7wA5Hoek2pMpAXeDw3VaVbMHTUADx/biG5Wbt+Lve2LD4W4FKoZnFYQQZovtmqd8+kNR2sMG8wBU6wwQlOuDb4hw2OCozsTz0JHVlVXQAAAABJRU5ErkJggg==",
3226       "bgai4a08.png", false, 32, 32, "e2212ec5fa026a41826136e983bf92b2");
3227   testPngSuiteImage("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",
3228       "bgai4a16.png", false, 32, 32, "f1423ebc08979252299ca238656ab0ba");
3229   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAYagMeiWXwAAAG9JREFUeJzt1jEKgDAMRuEnZGhPofc/VQSPIcTdxUV4HVLoUCj8H00o2YoBMF57fpz/ujODHXUFRwPKBqj5DVigB041HiJ9gFyCVOMbsEIPXNwuAHkgiJL/4qABNqB7QAeUPBAE2QAZUDZAfwEb8ABSIBqcFg+4TAAAAABJRU5ErkJggg==",
3230       "bgan6a08.png", false, 32, 32, "e80a60aecf13ebd863b61167ba95960b");
3231   testPngSuiteImage("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",
3232       "bgan6a16.png", false, 32, 32, "4d9d6473bb7403d7f85e3e7537c34e9d");
3233   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAABGdBTUEAAYagMeiWXwAAAAJiS0dEAACqjSMyAAAANUlEQVR4nGP8z8DAAYWcaDQxIpws3xkoAyw/hr4Bo2EwGgZUMWA0EEfDgCoGjAbiaBhQwwAA3yogfcTrhcgAAAAASUVORK5CYII=",
3234       "bgbn4a08.png", false, 32, 32, "e2212ec5fa026a41826136e983bf92b2");
3235   testPngSuiteImage("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",
3236       "bggn4a16.png", false, 32, 32, "f1423ebc08979252299ca238656ab0ba");
3237   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAYagMeiWXwAAAAZiS0dEAP8A/wD/oL2nkwAAAG9JREFUeJzt1jEKgDAMRuEnZGhPofc/VQSPIcTdxUV4HVLoUCj8H00o2YoBMF57fpz/ujODHXUFRwPKBqj5DVigB041HiJ9gFyCVOMbsEIPXNwuAHkgiJL/4qABNqB7QAeUPBAE2QAZUDZAfwEb8ABSIBqcFg+4TAAAAABJRU5ErkJggg==",
3238       "bgwn6a08.png", false, 32, 32, "e80a60aecf13ebd863b61167ba95960b");
3239   testPngSuiteImage("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",
3240       "bgyn6a16.png", false, 32, 32, "4d9d6473bb7403d7f85e3e7537c34e9d");
3241   testPngSuiteImage("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",
3242       "ccwn2c08.png", false, 32, 32, "5189ed8d023b977fa90833e90e4a830a");
3243   testPngSuiteImage("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",
3244       "ccwn3p08.png", false, 32, 32, "1a63f18f17006d850d1c041e49a7721f");
3245   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAgAAAAgCAIAAACgkq6HAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAlwSFlzAAAAAQAAAAQAMlIwkwAAASdJREFUeJxV0mFx7DAMBOCvmRAQBVMIhVAIhaNwFPogvFI4CA2FQGggVBDcH3acNpMZja1daVfWWwWClWRvZ3OPGwGSA6YOjw5QepxgcX+lg2ZYKc7BXNip1G9f1bP6X9WqvqtMregBTk691NTCcbUYCXX19d0qbuqyVvVTDZNwdjWFJS+/c/PEw/5QZNnTGa1HIsNHeAUlEc0gztheyguRLlWN8XRs2Vv0Hm12xRGt5j2rS/qY753w6+oPI+OefuPNA/KyHuISZZYCJf+VyKVrlINR8nyw3I95MRy2XeCMwSiwK0FGSwxGODk4yyV8lgpP0o612UlTU3EtjXL5nNozrQTLr8RbxZMix9Z9cDQfxz1B2kK0WY0dabc5EtlRf0B1/Ku63McfFzN1pnMg8LcAAAAASUVORK5CYII=",
3246       "cdfn2c08.png", false, 8, 32, "dbfdad37268883ddeeecc745da77130c");
3247   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAICAIAAAAX52r4AAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAlwSFlzAAAABAAAAAEAH+hVZQAAAOtJREFUeJx9kmuxwyAUhL/M1MBawEIsxEIsxEIs3FiohVjAAhaOhSMh9wePQtt0hwEG5rx2d7r4QADVxbg3eN3zxbr7iEc5BTOssJaHFtIHeleo9RDao8EBCawvIFgglN5dRIjwLLNsuHBh3RRy5AQgwSn8D2aYA+TlEEuZB+sr0EpeHJE/zl1PtshGrMPICAdz3GFNzIJoJANr8+foE6xRdAeBMJGQqhSGnE6kOzjAdPUULfjyRtECAQfXIEJmCYMY8D1T5HDU1JWi6WqdhkFkH63xZhCNIr8oPsAGkacvNu2d8YOH3ql+a9N/CM1cqmi++6QAAAAASUVORK5CYII=",
3248       "cdhn2c08.png", false, 32, 8, "650268c7196860898cbe701005cf2407");
3249   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAlwSFlzAAAAAQAAAAEATyXE1gAAAHtJREFUeJxFzlENwkAURNFTgoFnYS3UQisBC1gACSCBSsDCVgIroSuhlbB8NIX5mUwyubldQzCQ2KjMcBZ8zKFiP0zcaRd53Stb3n2LNWvJSVIwX/PoNvbbNlQkJ0dqRI0Qxz5Qg+VlffxQXQuyEsphFxNP3V93hxQKfAEqsC/QF17WrgAAAABJRU5ErkJggg==",
3250       "cdsn2c08.png", false, 8, 8, "9e580d6237f77bfa8e49cfef19236bcb");
3251   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAlwSFlzAAAD6AAAA+gBtXtSawAAAmdJREFUeJyVluGR3CAMhb/bcQNqgRZowVeCr4RLCZsSsiXcteASQglxC7RACckPEEbYeDeandkZDHpP0hPi7S/PzIPoL1uCCBHS08O8DQEczI3TkW0Q/hdAYAb3nF2xBAHiiwAOlpddtzYIxQLM8Hl+PPNLh3L0GI8LAAdfMJvPNfqunA48+M5Zgo8+jqn8S+8aWGE7ZaoiCrB0xfKQzLFb+beCSfA99v5km3U1FfpWM48+mR6cJj93wVbTtsLvYxyaqFvBbMxKzsGnyjYTE/DwWdWWYO2K5PcgpuKkibopkoM/ZXVTWNESAyzwUU8ZebuSu6lLTuNdSjojPApDqUw93NF2D8DWJX8E0CTHg5DgJ6zMSroIdwXJTeNrPWIrXHU7tRW3endQzt7hXjwncIn5HWLUxlO2sesMgWQBkvkoGUBKLN/6PQKeOda8qIv+bhVI3AZdr6spB9L1cnTG5Rhgb7SRSa2usRcGQdl0G+zVVcnk25tEyPmhVtIGYm3SQjX7y5kEgoeVFaToKBdZr4drgFQBGm670nMFPXhCZAOPCBKr9yL7A1wPYMXV3CJb+fALZlJoejAnzNdtZc0AaENN3ajzppnXwjO7q8LfCYUK4LsU7QAN10xk2a/SBD9gAbF+K/fQhmRsBICOKo0j3/nucF3vnXEyxcNeyak4sRj3/bKqfM5fDXIcapi9OjJDv2sBacfKmTndZswOh2boC3z10dZB0PKvE+FEl+/9CLXPFn9KaT+ert9jAdZ+7fDwkiuMKwvnr4TB23Q+inJs0cjmNQD2iXkVTS7R5fNmDFCtNsDx+f6C/QMQQNfOLmy7EgAAAABJRU5ErkJggg==",
3252       "cdun2c08.png", false, 32, 32, "fbe519db5608cf411e933ccbd1f92f87");
3253   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAC1QTFRFIgD/AP//iAD/Iv8AAJn//2YA3QD/d/8A/wAAAP+Z3f8A/wC7/7sAAET/AP9E0rBJvQAAAB5oSVNUAEAAcAAwAGAAYAAgACAAUAAQAIAAQAAQADAAUABwSJlZQQAAAEdJREFUeJxj6OgIDT1zZtWq8nJj43fvZs5kIEMAlSsoSI4AKtfFhRwBVO7du+QIoHEZyBFA5SopkSOAyk1LI0cAlbt7NxkCAODE6tEPggV9AAAAAElFTkSuQmCC",
3254       "ch1n3p04.png", false, 32, 32, "a339593b0d82103e30ed7b00afd68816");
3255   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYagMeiWXwAAAwBQTFRFIkQA9f/td/93y///EQoAOncAIiL//xH/EQAAIiIA/6xVZv9m/2Zm/wH/IhIA3P//zP+ZRET/AFVVIgAAy8v/REQAVf9Vy8sAMxoA/+zc7f//5P/L/9zcRP9EZmb/MwAARCIA7e3/ZmYA/6RE//+q7e0AAMvL/v///f/+//8BM/8zVSoAAQH/iIj/AKqqAQEARAAAiIgA/+TLulsAIv8iZjIA//+Zqqr/VQAAqqoAy2MAEf8R1P+qdzoA/0RE3GsAZgAAAf8BiEIA7P/ca9wA/9y6ADMzAO0A7XMA//+ImUoAEf//dwAA/4MB/7q6/nsA//7/AMsA/5mZIv//iAAA//93AIiI/9z/GjMAAACqM///AJkAmQAAAAABMmYA/7r/RP///6r/AHcAAP7+qgAASpkA//9m/yIiAACZi/8RVf///wEB/4j/AFUAABER///+//3+pP9EZv///2b/ADMA//9V/3d3AACI/0T/ABEAd///AGZm///tAAEA//XtERH///9E/yL//+3tEREAiP//AAB3k/8iANzcMzP//gD+urr/mf//MzMAY8sAuroArP9V///c//8ze/4A7QDtVVX/qv//3Nz/VVUAAABm3NwA3ADcg/8Bd3f//v7////L/1VVd3cA/v4AywDLAAD+AQIAAQAAEiIA//8iAEREm/8z/9SqAABVmZn/mZkAugC6KlUA/8vLtP9m/5sz//+6qgCqQogAU6oA/6qqAADtALq6//8RAP4AAABEAJmZmQCZ/8yZugAAiACIANwA/5MiAADc/v/+qlMAdwB3AgEAywAAAAAz/+3/ALoA/zMz7f/t/8SIvP93AKoAZgBmACIi3AAA/8v/3P/c/4sRAADLAAEBVQBVAIgAAAAiAf//y//L7QAA/4iIRABEW7oA/7x3/5n/AGYAuv+6AHd3c+0A/gAAMwAzAAC6/3f/AEQAqv+q//7+AAARIgAixP+IAO3tmf+Z/1X/ACIA/7RmEQARChEA/xER3P+6uv//iP+IAQAB/zP/uY7TYgAAAgBoSVNUAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAARNzPXjAAABsUlEQVR4nA3BBwAIBBAAwEeojEhkKzszCWVrWGVn7xWK0LD3Kio0aJgNq2zK3qOMhp2VWTKy9767mML3FOZX+rKXptwlHuQBBnODnrzFea4TaUjJQ0zlKjs4wAUiG+n5iAa8S0U2c4p4midIS/A/01nOEeI58vMFc+jEo/zIPqI8xchOM/6hN1+ynXiVMkwmMa04wVB+IV7jBYrwE/upR3fWEE2oyiza0pgVtGcl0YaNPM/PbKMQDVlIrKYoIznKVpZwmtnEJkryOB9Ti9z8xbfETsrxFS+xlvdZz9fEISqTi/+oxCUW8xlxkhp8w6csozXfMZx4k2o8xTgqcJACpCBusoeldKAUr9CfpEQ71jGNYTxLHZIwkPiN+XzCDPLRiA+4R5QlBwPoShZakJoexCQe5j1GkY43+JwrRHKu8TrzSMbbZOUdohvHqMufJKQX4zlDHOYPqnCROwyhIB2J2qyiOKm4zIfM5DixiB/ISWnOMoYStCSq8zILuMW/3GYEzYm5PMNEMvE3iXiMXURmMjCaF9nNI4ylPjGIfvQhAb+TkSfZQpyjC53JywbyMIGa3AeBG/4Qh5bI4AAAAABJRU5ErkJggg==",
3256       "ch2n3p08.png", false, 32, 32, "d36bdbefc126ef50bd57d51eb38f2ac4");
3257   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAAd0SU1FB9ABAQwiON2c/4AAAADISURBVHicXdHBDcIwDAVQHypACPAIHaEjsAojVOLIBTEBGzACbFBGYAPYoEY9lQKfxElR4hwq58V17ZRgFiVxa4ENSJ7xmoip8bSAbQL3f80I/LXg358J0Y09LBS4ZuxPSwrnB6DQdI7AKMjvBeSS1x6m7UYLO+hQuoCvvnt4cOddAzmHLwdwjyokKOwq6Xns1YOg1/4e2unn6ED3Q7wgEglj1HEWnotO21UjhCkxMbcujYEVchDk8GYDF+QwsIHkZ2gopYF0/QAe2cJF+P+JawAAAABJRU5ErkJggg==",
3258       "cm0n0g04.png", false, 32, 32, "cf2f1ab4f34d0c70f15f636ef584d53a");
3259   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAAd0SU1FB7IBAQAAAB4KVgsAAADISURBVHicXdHBDcIwDAVQHypACPAIHaEjsAojVOLIBTEBGzACbFBGYAPYoEY9lQKfxElR4hwq58V17ZRgFiVxa4ENSJ7xmoip8bSAbQL3f80I/LXg358J0Y09LBS4ZuxPSwrnB6DQdI7AKMjvBeSS1x6m7UYLO+hQuoCvvnt4cOddAzmHLwdwjyokKOwq6Xns1YOg1/4e2unn6ED3Q7wgEglj1HEWnotO21UjhCkxMbcujYEVchDk8GYDF+QwsIHkZ2gopYF0/QAe2cJF+P+JawAAAABJRU5ErkJggg==",
3260       "cm7n0g04.png", false, 32, 32, "cf2f1ab4f34d0c70f15f636ef584d53a");
3261   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAAd0SU1FB88MHxc7O3UwH+AAAADISURBVHicXdHBDcIwDAVQHypACPAIHaEjsAojVOLIBTEBGzACbFBGYAPYoEY9lQKfxElR4hwq58V17ZRgFiVxa4ENSJ7xmoip8bSAbQL3f80I/LXg358J0Y09LBS4ZuxPSwrnB6DQdI7AKMjvBeSS1x6m7UYLO+hQuoCvvnt4cOddAzmHLwdwjyokKOwq6Xns1YOg1/4e2unn6ED3Q7wgEglj1HEWnotO21UjhCkxMbcujYEVchDk8GYDF+QwsIHkZ2gopYF0/QAe2cJF+P+JawAAAABJRU5ErkJggg==",
3262       "cm9n0g04.png", false, 32, 32, "cf2f1ab4f34d0c70f15f636ef584d53a");
3263   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAAAANzQklUDQ0N0DeNwQAAAH5JREFUeJztl8ENxEAIAwcJ6cpI+q8qKeNepAgelq2dCjz4AdQM1jRcf3WIDQ13qUNsiBBQZ1gR0cARUFIz3pug3586wo5+rOcfIaBOsCSggSOgpcB8D4D3R9DgfUyECIhDbAhp4AjoKPD+CBq8P4IG72MiQkCdYUVEA0dAyQcwUyZpXH92ZwAAAABJRU5ErkJggg==",
3264       "cs3n2c16.png", false, 32, 32, "023541189afc3aa4ae617158b59fe635");
3265   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYagMeiWXwAAAANzQklUAwMDo5KgQgAAAFRQTFRFkv8AAP+SAP//AP8AANv/AP9t/7YAAG3/tv8A/5IA2/8AAEn//yQA/wAAJP8ASf8AAP/bAP9JAP+2//8AAP8kALb//9sAAJL//20AACT//0kAbf8A33ArFwAAAEtJREFUeJyFyscBggAAALGzYldUsO2/pyMk73SGGE7QF3pDe2gLzdADHA7QDqIfdIUu0AocntAIbaAFdIdu0BIc1tAEvaABOkIf+AMiQDPhd/SuJgAAAABJRU5ErkJggg==",
3266       "cs3n3p08.png", false, 32, 32, "6b15613bf70a37c37de24edfb8f6d1df");
3267   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAYagMeiWXwAAAANzQklUBQUFGCbeQwAAAGJJREFUeJztlbERgEAMw5Q7L0EH+w/Fd4zxbEAqUUUDROfCcW1cwmELLltw2gI9wQgaastFyOPeJ7ctWLZATzCCjsLuAfIgBPlXBHkQ/kgwgm8KeRCCPAhB/hVh2QI9wQgaXuXOFG8QELloAAAAAElFTkSuQmCC",
3268       "cs5n2c08.png", false, 32, 32, "3211fb3ede03caf163fe33b4cf6d78f6");
3269   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYagMeiWXwAAAANzQklUBQUFGCbeQwAAAGBQTFRF/xkAQv8Axf8AAP97AP+9AP//AP8AAMX/AKX//94Apf8AAGP//5wAACH//1oAAP86/zoAY/8A5v8A/wAAAP9aIf8AAP+cAP/eAOb///8AAIT//70AAEL//3sAhP8AAP8ZRy+F9QAAAEtJREFUeJyFwQUBwAAAgDDu7u79Wz4CG5NA9YJW8AhqwSUoBIdgFISCUvAKBkEgWASp4BN0glkQCVZBLNgEiWAXZIJccAoqwS1oxA/GcT4B7dbxuwAAAABJRU5ErkJggg==",
3270       "cs5n3p08.png", false, 32, 32, "3211fb3ede03caf163fe33b4cf6d78f6");
3271   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAYagMeiWXwAAAExJREFUeJzt1UENADAMQlGa4GPzr2pT0olo/mkgoO9EqRYba9HADhBgmGq4CL7sffkECDBNie6B4EGw4F8R4AOgBA+CBQ+CdQIEGOYB69wUb0ah5KoAAAAASUVORK5CYII=",
3272       "cs8n2c08.png", false, 32, 32, "023541189afc3aa4ae617158b59fe635");
3273   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYagMeiWXwAAAGBQTFRFIP8A/x8AAP8fAP/foP8AAP8/AP//AP8AgP8AAP9fAP9/YP8A/wAA4P8AAP+fAOD/QP8A//8AAMD//98AAKD//78AAID/wP8AAP+//58AAGD//38AAED//18AACD//z8As4GzYwAAAEtJREFUeJyFwQUBwAAAgDDu7u79Wz4CG7UgEHyCR3AJDsEimASDoBFsgliQCypBL1CZIBQkgkJQClrBLogEqaATjIJZsApOwS14xQ8p4j4B+PNT2QAAAABJRU5ErkJggg==",
3274       "cs8n3p08.png", false, 32, 32, "023541189afc3aa4ae617158b59fe635");
3275   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAMhJREFUeJxd0cENwjAMBVAfKkAI8AgdoSOwCiNU4sgFMQEbMAJsUEZgA9igRj2VAp/ESVHiHCrnxXXtlGAWJXFrgQ1InvGaiKnxtIBtAvd/zQj8teDfnwnRjT0sFLhm7E9LCucHoNB0jsAoyO8F5JLXHqbtRgs76FC6gK++e3hw510DOYcvB3CPKiQo7CrpeezVg6DX/h7a6efoQPdDvCASCWPUcRaei07bVSOEKTExty6NgRVyEOTwZgMX5DCwgeRnaCilgXT9AB7ZwkX4/4lrAAAAAElFTkSuQmCC",
3276       "ct0n0g04.png", false, 32, 32, "cf2f1ab4f34d0c70f15f636ef584d53a");
3277   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAA50RVh0VGl0bGUAUG5nU3VpdGVPVc9MAAAAMXRFWHRBdXRob3IAV2lsbGVtIEEuSi4gdmFuIFNjaGFpawood2lsbGVtQHNjaGFpay5jb20pjsxHHwAAADh0RVh0Q29weXJpZ2h0AENvcHlyaWdodCBXaWxsZW0gdmFuIFNjaGFpaywgU2luZ2Fwb3JlIDE5OTUtOTaEUAQ4AAAA+3RFWHREZXNjcmlwdGlvbgBBIGNvbXBpbGF0aW9uIG9mIGEgc2V0IG9mIGltYWdlcyBjcmVhdGVkIHRvIHRlc3QgdGhlCnZhcmlvdXMgY29sb3ItdHlwZXMgb2YgdGhlIFBORyBmb3JtYXQuIEluY2x1ZGVkIGFyZQpibGFjayZ3aGl0ZSwgY29sb3IsIHBhbGV0dGVkLCB3aXRoIGFscGhhIGNoYW5uZWwsIHdpdGgKdHJhbnNwYXJlbmN5IGZvcm1hdHMuIEFsbCBiaXQtZGVwdGhzIGFsbG93ZWQgYWNjb3JkaW5nCnRvIHRoZSBzcGVjIGFyZSBwcmVzZW50Lk0JDWsAAAA5dEVYdFNvZnR3YXJlAENyZWF0ZWQgb24gYSBOZVhUc3RhdGlvbiBjb2xvciB1c2luZyAicG5tdG9wbmciLmoSZHkAAAAUdEVYdERpc2NsYWltZXIARnJlZXdhcmUuX4AsSgAAAMhJREFUeJxd0cENwjAMBVAfKkAI8AgdoSOwCiNU4sgFMQEbMAJsUEZgA9igRj2VAp/ESVHiHCrnxXXtlGAWJXFrgQ1InvGaiKnxtIBtAvd/zQj8teDfnwnRjT0sFLhm7E9LCucHoNB0jsAoyO8F5JLXHqbtRgs76FC6gK++e3hw510DOYcvB3CPKiQo7CrpeezVg6DX/h7a6efoQPdDvCASCWPUcRaei07bVSOEKTExty6NgRVyEOTwZgMX5DCwgeRnaCilgXT9AB7ZwkX4/4lrAAAAAElFTkSuQmCC",
3278       "ct1n0g04.png", false, 32, 32, "cf2f1ab4f34d0c70f15f636ef584d53a");
3279   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAABlpVFh0VGl0bGUAAABlbgBUaXRsZQBQbmdTdWl0ZdWsxR4AAAA4aVRYdEF1dGhvcgAAAGVuAEF1dGhvcgBXaWxsZW0gdmFuIFNjaGFpayAod2lsbGVtQHNjaGFpay5jb20pRVcgpAAAAEFpVFh0Q29weXJpZ2h0AAAAZW4AQ29weXJpZ2h0AENvcHlyaWdodCBXaWxsZW0gdmFuIFNjaGFpaywgQ2FuYWRhIDIwMTHS6zPBAAABDGlUWHREZXNjcmlwdGlvbgAAAGVuAERlc2NyaXB0aW9uAEEgY29tcGlsYXRpb24gb2YgYSBzZXQgb2YgaW1hZ2VzIGNyZWF0ZWQgdG8gdGVzdCB0aGUgdmFyaW91cyBjb2xvci10eXBlcyBvZiB0aGUgUE5HIGZvcm1hdC4gSW5jbHVkZWQgYXJlIGJsYWNrJndoaXRlLCBjb2xvciwgcGFsZXR0ZWQsIHdpdGggYWxwaGEgY2hhbm5lbCwgd2l0aCB0cmFuc3BhcmVuY3kgZm9ybWF0cy4gQWxsIGJpdC1kZXB0aHMgYWxsb3dlZCBhY2NvcmRpbmcgdG8gdGhlIHNwZWMgYXJlIHByZXNlbnQufjUNRAAAAEdpVFh0U29mdHdhcmUAAABlbgBTb2Z0d2FyZQBDcmVhdGVkIG9uIGEgTmVYVHN0YXRpb24gY29sb3IgdXNpbmcgInBubXRvcG5nIi7EGQUHAAAAJGlUWHREaXNjbGFpbWVyAAAAZW4ARGlzY2xhaW1lcgBGcmVld2FyZS7TvjIJAAAATElEQVQokWP4DwbGxi4uoaFpaeXlDGQJKCkhuB0d5An8/4/gzpxJngDcSRBAlgAIQAxctYo8AYSTwFyyBBDc3bvPnCFPAMGFeo50AQDds/NRVdY0lwAAAABJRU5ErkJggg==",
3280       "cten0g04.png", false, 32, 32, "ac076245d12023e111ec36acb36dcff1");
3281   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAABtpVFh0VGl0bGUAAABmaQBPdHNpa2tvAFBuZ1N1aXRl8x/ISQAAADlpVFh0QXV0aG9yAAAAZmkAVGVraWrDpABXaWxsZW0gdmFuIFNjaGFpayAod2lsbGVtQHNjaGFpay5jb20pTbKY1QAAAEhpVFh0Q29weXJpZ2h0AAAAZmkAVGVraWrDpG5vaWtldWRldABDb3B5cmlnaHQgV2lsbGVtIHZhbiBTY2hhaWssIEthbmFkYSAyMDExGP2/hwAAAOtpVFh0RGVzY3JpcHRpb24AAABmaQBLdXZhdXMAa29rb2VsbWEgam91a29uIGt1dmlhIGx1b3R1IHRlc3RhdGEgZXJpIHbDpHJpLXR5eXBwaXNpw6QgUE5HLW11b2Rvc3NhLiBNdWthbmEgb24gbXVzdGF2YWxrb2luZW4sIHbDpHJpLCBwYWxldHRlZCwgYWxwaGEta2FuYXZhLCBhdm9pbXV1ZGVuIG11b2Rvc3NhLiBLYWlra2kgYml0LXN5dnl5ZGVzc8OkIG11a2FhbiBzYWxsaXR0dWEgc3BlYyBvbiDigIvigItsw6RzbsOkLsc2cVkAAAA/aVRYdFNvZnR3YXJlAAAAZmkAT2hqZWxtaXN0b3QATHVvdHUgTmVYVHN0YXRpb24gdsOkcmnDpCAicG5tdG9wbmciLlFtpV0AAAAtaVRYdERpc2NsYWltZXIAAABmaQBWYXN0dXV2YXBhdXNsYXVzZWtlAEZyZWV3YXJlLvx3Hi8AAABISURBVCiRY/gPBsbGLi6hoWlp5eUMZAkoKSG4HR3kCfz/j+DOnEmeAAqXgTwBBHfVKvIE0LhkCSC4u3efOUOeAILLAAGkCwAA+XLyQRLQxL0AAAAASUVORK5CYII=",
3282       "ctfn0g04.png", false, 32, 32, "0428cabaa4c89cb12cd5cf0f269a0ff1");
3283   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAACBpVFh0VGl0bGUAAABlbADOpM6vz4TOu86/z4IAUG5nU3VpdGUgh0C5AAAARmlUWHRBdXRob3IAAABlbADOo8+FzrPOs8+BzrHPhs6tzrHPggBXaWxsZW0gdmFuIFNjaGFpayAod2lsbGVtQHNjaGFpay5jb20p1io2ZgAAAIlpVFh0Q29weXJpZ2h0AAAAZWwAzqDOvc61z4XOvM6xz4TOuc66zqwgzrTOuc66zrHOuc+OzrzOsc+EzrEAzqDOvc61z4XOvM6xz4TOuc66zqwgzrTOuc66zrHOuc+OzrzOsc+EzrEgU2NoYWlrIHZhbiBXaWxsZW0sIM6azrHOvc6xzrTOrM+CIDIwMTHXI+R2AAAB9WlUWHREZXNjcmlwdGlvbgAAAGVsAM6gzrXPgc65zrPPgc6xz4bOrgDOnM65zrEgz4PPhc67zrvOv86zzq4gzrHPgM+MIM6tzr3OsSDPg8+Nzr3Ov867zr8gzrXOuc66z4zOvc+Jzr0gz4DOv8+FIM60zrfOvM65zr/Phc+BzrPOrs64zrfOus6xzr0gzrPOuc6xIM+EzrcgzrTOv866zrnOvM6uIM+Ez4nOvSDOtM65zrHPhs+Mz4HPic69IM+Hz4HPic68zqzPhM+Jzr0tz4TPjc+Az4nOvSDPhM6/z4UgzrzOv8+Bz4bOriBQTkcuIM6gzrXPgc65zrvOsc68zrLOrM69zr/Ovc+EzrHOuSDOv865IM6xz4PPgM+Bz4zOvM6xz4XPgc61z4IsIM+Hz4HPjs68zrEsIHBhbGV0dGVkLCDOvM61IM6szrvPhs6xIM66zrHOvc6szrvOuSwgzrzOtSDOvM6/z4HPhs6tz4Igz4TOt8+CIM60zrnOsc+GzqzOvc61zrnOsc+CLiDOjM67zr/OuSDOu86vzrPOvy3Oss6szrjOtyDOtc+AzrnPhM+Bzq3PgM61z4TOsc65IM+Dz43OvM+Gz4nOvc6xIM68zrUgz4TOvyBzcGVjIM61zq/Ovc6xzrkgz4DOsc+Bz4zOvc+EzrXPgi6miCkYAAAAiWlUWHRTb2Z0d2FyZQAAAGVsAM6bzr/Os865z4POvM65zrrPjADOlM63zrzOuc6/z4XPgc6zzq7OuM63zrrOtSDPg861IM6tzr3OsSDPh8+Bz47OvM6xIE5lWFRzdGF0aW9uIM+Hz4HOt8+DzrnOvM6/z4DOv865z47Ovc+EzrHPgiAicG5tdG9wbmciLkN4y+sAAABDaVRYdERpc2NsYWltZXIAAABlbADOkc+Azr/PgM6/zq/Ot8+DzrcAzpTPic+BzrXOrM69IM67zr/Os865z4POvM65zrrPjC4snq9sAAAAXUlEQVQokZ3OQREAIQxD0WjBAhawgAUsYKEWsFALWEALFrLTnd3pPcf/DpkAIEuptbXex5gTAkSSf5ppkINma2nQGvl9hLsCkeR7KRIK5CX3vTXIBM7RIAcj7xXgAUU58kEPspNFAAAAAElFTkSuQmCC",
3284       "ctgn0g04.png", false, 32, 32, "32546f7ef2cce19fcbaa6b8849592c38");
3285   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAACZpVFh0VGl0bGUAAABoaQDgpLbgpYDgpLDgpY3gpLfgpJUAUG5nU3VpdGVT/Uu3AAAAPmlUWHRBdXRob3IAAABoaQDgpLLgpYfgpJbgpJUAV2lsbGVtIHZhbiBTY2hhaWsgKHdpbGxlbUBzY2hhaWsuY29tKc9NfecAAABoaVRYdENvcHlyaWdodAAAAGhpAOCkleClieCkquClgOCksOCkvuCkh+CknwDgpJXgpYngpKrgpYDgpLDgpL7gpIfgpJ8gV2lsbGVtIHZhbiBTY2hhaWssIDIwMTEg4KSV4KSo4KS+4KSh4KS+3xTVhQAAAmVpVFh0RGVzY3JpcHRpb24AAABoaQDgpLXgpL/gpLXgpLDgpKMA4KSV4KSw4KSo4KWHIOCkleClhyDgpLLgpL/gpI8gUE5HIOCkquCljeCksOCkvuCksOClguCkqiDgpJXgpYcg4KS14KS/4KSt4KS/4KSo4KWN4KSoIOCksOCkguCklyDgpKrgpY3gpLDgpJXgpL7gpLAg4KSq4KSw4KWA4KSV4KWN4KS34KSjIOCkrOCkqOCkvuCkr+CkviDgpJvgpLXgpL/gpK/gpYvgpIIg4KSV4KS+IOCkj+CklSDgpLjgpYfgpJ8g4KSV4KS+IOCkj+CklSDgpLjgpILgpJXgpLLgpKguIOCktuCkvuCkruCkv+CksiDgpJXgpL7gpLLgpYcg4KSU4KSwIOCkuOCkq+Clh+Ckpiwg4KSw4KSC4KSXLCDgpKrgpYjgpLLgpYfgpJ/gpYfgpKEg4KS54KWI4KSCLCDgpIXgpLLgpY3gpKvgpL4g4KSa4KWI4KSo4KSyIOCkleClhyDgpLjgpL7gpKUg4KSq4KS+4KSw4KSm4KSw4KWN4KS24KS/4KSk4KS+IOCkuOCljeCkteCksOClguCkquCli+CkgiDgpJXgpYcg4KS44KS+4KSlLiDgpLjgpK3gpYAg4KSs4KS/4KSfIOCkl+CkueCksOCkvuCkiCDgpJXgpLLgpY3gpKrgpKjgpL4g4KSV4KWHIOCkheCkqOClgeCkuOCkvuCksCDgpJXgpYAg4KSF4KSo4KWB4KSu4KSk4KS/IOCkpuClgCDgpK7gpYzgpJzgpYLgpKYg4KS54KWI4KSCLvrUkQYAAACRaVRYdFNvZnR3YXJlAAAAaGkA4KS44KWJ4KSr4KWN4KSf4KS14KWH4KSv4KSwAOCkj+CklSBOZVhUc3RhdGlvbiAicG5tdG9wbmcgJ+CkleCkviDgpIngpKrgpK/gpYvgpJcg4KSV4KSwIOCksOCkguCklyDgpKrgpLAg4KSs4KSo4KS+4KSv4KS+IOCkl+Ckr+Ckvi4VxVHXAAAAQmlUWHREaXNjbGFpbWVyAAAAaGkA4KSF4KS44KWN4KS14KWA4KSV4KSw4KSjAOCkq+CljeCksOClgOCkteClh+Ckr+CksC4tT0C7AAAAYElEQVQokWP4/19Q8P9/Y2MXl9DQtLTycgayBJSU/v+HcTs6yBMAARh35kzyBFxc/v8HO4kByGUgTyA09P9/sJMYVq0iTwDJSRBAhgCMCzLwzBnyBGDc3bsZGO7eJUsAAEBI89kMzfvBAAAAAElFTkSuQmCC",
3286       "cthn0g04.png", false, 32, 32, "c570e7393458556ecef30b71824e0d6e");
3287   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAACBpVFh0VGl0bGUAAABqYQDjgr/jgqTjg4jjg6sAUG5nU3VpdGUPGlwCAAAAOGlUWHRBdXRob3IAAABqYQDokZfogIUAV2lsbGVtIHZhbiBTY2hhaWsgKHdpbGxlbUBzY2hhaWsuY29tKeXxzKEAAABTaVRYdENvcHlyaWdodAAAAGphAOacrOaWh+OBuADokZfkvZzmqKnjgqbjgqPjg6zjg6Djg7TjgqHjg7Pjgrfjg6PjgqTjgq/jgIHjgqvjg4rjg4AyMDExhF9tvgAAAXdpVFh0RGVzY3JpcHRpb24AAABqYQDmpoLopoEAUE5H5b2i5byP44Gu5qeY44CF44Gq6Imy44Gu56iu6aGe44KS44OG44K544OI44GZ44KL44Gf44KB44Gr5L2c5oiQ44GV44KM44Gf44Kk44Oh44O844K444Gu44K744OD44OI44Gu44Kz44Oz44OR44Kk44Or44CC5ZCr44G+44KM44Gm44GE44KL44Gu44Gv6YCP5piO5bqm44Gu44OV44Kp44O844Oe44OD44OI44Gn44CB44Ki44Or44OV44Kh44OB44Oj44ON44Or44KS5oyB44Gk44CB55m96buS44CB44Kr44Op44O844CB44OR44Os44OD44OI44Gn44GZ44CC44GZ44G544Gm44Gu44OT44OD44OI5rex5bqm44GM5a2Y5Zyo44GX44Gm44GE44KL5LuV5qeY44Gr5b6T44Gj44Gf44GT44Go44GM44Gn44GN44G+44GX44Gf44CCwwUNtAAAAGNpVFh0U29mdHdhcmUAAABqYQDjgr3jg5Xjg4jjgqbjgqfjgqIAInBubXRvcG5nIuOCkuS9v+eUqOOBl+OBpk5lWFRzdGF0aW9u6Imy5LiK44Gr5L2c5oiQ44GV44KM44G+44GZ44CCwoP4MAAAADJpVFh0RGlzY2xhaW1lcgAAAGphAOWFjeiyrOS6i+mghQDjg5Xjg6rjg7zjgqbjgqfjgqLjgIJ28EPmAAAAZUlEQVQokWNgYPgPBMbGLi6hoWlp5eUMZAgICiop/f8P43Z0kCOgpGRs/P8/jDtzJjkCIAP//4cayLBqFTkCaFwGcgSQnMSwe/eZM+QIwLggA8+cuXuXHAEYd/duoKMY3r0jQwAATn/xuQxIlj4AAAAASUVORK5CYII=",
3288       "ctjn0g04.png", false, 32, 32, "81fd25285e6b46f3996cfd02b1f16071");
3289   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAA50RVh0VGl0bGUAUG5nU3VpdGVPVc9MAAAAMXRFWHRBdXRob3IAV2lsbGVtIEEuSi4gdmFuIFNjaGFpawood2lsbGVtQHNjaGFpay5jb20pjsxHHwAAAEF6VFh0Q29weXJpZ2h0AAB4nHPOL6gsykzPKFEIz8zJSc1VKEvMUwhOzkjMzNZRCM7MS08syC9KVTC0tDTVtTQDAIthD6RSWpQSAAAAu3pUWHREZXNjcmlwdGlvbgAAeJwtjrEOwjAMRPd+xU1Mpf/AhFgQv2BcQyLcOEoMVf8eV7BZvnt3dwLbUrOSZyuwBwhdfD/yQk/p4CbkMsMNLt3hSYYPtWzv0EytHX2r4QsiJNyuZzysLeQTLoX1PQdLTYa7Er8Oa8ou4w8cUUnFI3zEmj2BtCYCJypF9PcbvFHpNQIKb//gPuGkinv24yzVUw9Qbd17mK3NuTyHfW2s6VV4b0dt0qX49AUf8lYE8mJ6iAAAAEB6VFh0U29mdHdhcmUAAHiccy5KTSxJTVHIz1NIVPBLjQgpLkksyQTykvNz8osUSosz89IVlAryckvyC/LSlfQApuwRQp5RqK4AAAAdelRYdERpc2NsYWltZXIAAHiccytKTS1PLErVAwARVQNg1K617wAAAMhJREFUeJxd0cENwjAMBVAfKkAI8AgdoSOwCiNU4sgFMQEbMAJsUEZgA9igRj2VAp/ESVHiHCrnxXXtlGAWJXFrgQ1InvGaiKnxtIBtAvd/zQj8teDfnwnRjT0sFLhm7E9LCucHoNB0jsAoyO8F5JLXHqbtRgs76FC6gK++e3hw510DOYcvB3CPKiQo7CrpeezVg6DX/h7a6efoQPdDvCASCWPUcRaei07bVSOEKTExty6NgRVyEOTwZgMX5DCwgeRnaCilgXT9AB7ZwkX4/4lrAAAAAElFTkSuQmCC",
3290       "ctzn0g04.png", false, 32, 32, "cf2f1ab4f34d0c70f15f636ef584d53a");
3291   testPngSuiteImage("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",
3292       "exif2c08.png", false, 32, 32, "7acea6df2b0e2a7613981decc569b2fb");
3293   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAABBklEQVR4nIXSL0xCURTH8a/gGHNjBjc3AoFioFhIr7z0molmsxFpVCONSLPRbCYSiWKxWAwWN4ObG5ubcwzk6f3jds71hXPr/eye3/3dy/VkOruZ394tlqv7h8en55fXt/f1x+fXZrv73pflD2NDMDIEQ0NwZQguDcHAEFwYgkILwkoEuRJQFWQi3Jafkgr6IiDmAJWDcxEQkroTVFJ6IsAn9SHUXTgTgX+5kFLdlq4I8DlwZ6g+6IgANwV/W9UYbRHh9DBFdcqpCL8f+1CtcyLC7Sd9BMGxCEj6iIKWCKIg9vEnOEpFWPr1aVZF8j9oJCLLi38/iENDUDcENUNwYAgsgSWwxC/EfcpYUKbOtgAAAABJRU5ErkJggg==",
3294       "f00n0g08.png", false, 32, 32, "f34b8a71205dc26cd37d58fb19179172");
3295   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAJcklEQVR4nHWWb3BU5RXGn/fe3U02sMmGsAksSbMB2Qyw/BGWprho0EWCsIBAdoIM8UaHENiWhA6zBAditoIJDGsiomQ7ILGUTcJIQ2GBtFaMt/yJoIFlKFKoekPAoEgvFK18fLpMKDjank/vnA+/55z3nHeeF0Qyk9NozeKQXDryOWo8Hy3glEI+WcRZ87ighIsVvljBQBVXV3NdLTfUc0sj32zizmbuaeW+/TzUwaOdPNHF7rO8cJFfaOy7Tv0Wv79LEnpOEnOT6Uzj2Cy6c+nJp3c8ZxVwfiEXFbFsHitKWKkwWMH1VdxYzS21fKOev23k75rY1sz9rTyyn0c7eKKTn3Tx/FlevshejV9f5+1bvHsXWkGS7kliYTKfTuPsLM7PZUk+S8dzaQEDhVxVxDXzuL6EGxRurmBjFd+q5o5a7q5nWyPbm3iome+1Ut3Prg52d/J8Fy+dZc9F9mm8eZ13biE+x6QtTNIXJVFJ5tI0rshiZS5X53PteNYUcEMhNxXxtXl8o4RNCndWcHcVW6u5r5YH6nmkkX9potrMk638eD/jHbzQyctd7DnLLy/yhsZb16GWGeMVRq3KpK8xsTaJG9JYn8UtuWzM57ZxbCrgjkK+U8Q9c9lWwn0K/1jBQ5X8UzXfr6VazxMNPNXE7maea+GFdl7q4Oed7D3JvjO8cZG6hliVQV1rjP/GqG0x6W+a2JzE3WmMZrEtl+/ms30cDxTwUCE7ivjeXB4toarweAW7Knm6mt21jNfzfAM/beKlZn7Wwp52Xu1gXye/PsmbZ3jrIqLrDbE6g/q6Mb7DqLWa9IMmdiZRTeOxLJ7IZVc+T43jxwXsLuTZIp6by/MlvKDwYgUvVfIf1fy8lj317G3gtSb2NfOrFt5o580O6p28fZJ3ziDyqiG61RDbaVD3GuOHjdoxkx43UUtiTxqvZLE3l1fzeW0cvyxgXyGvF/Grufy6hDcUflPBm5X8ZzX1Wt6q5+0G/quJd5r5bQu/a+e/O/h9J++eRDgsRyJyNCrHYgZVNcTjBk0z6rqRNJGpZCb5M9KJnwT5PLmMrCTXkC+TdWQDuZ3cRbaQ7eQR8gOsCsnrwnJdRN4ald+OGfaqhiNxw3HNeE439tB0ham9zPwpvT++4fM3uewmK3WuucWXb7PuNhvucPu33PUtW75j+/c8gkVBqSwkrwjLqyPy+qhcHzNsVQ0744Y2zRjTjR/S9AD3EZ2nOe4T/vwMn3iQ/JTP/53LLrPyM675gi/3sK6XDde4vY+7vmLLDbbjqYD0TFB6NiQtCktKRFoelVfF5JdU+ZW4IawZ3tIN/aAW2vYyZx9H7ufYg5x8mI/35z+gX2XpcZZ3ceVpBrtZc451f2PDRW6/zF2fswUTFDE5ID0WlKaFpBlhyReRFkblxTH5BVVeHjes0u4LbKRlE21h5rzOkW9y7IMO9nBOG/1/YOkBlh/myj8zeJQ1KutOsOEUt3dzFxx+8Ygi8gOSKyhNCEnusDQlIj0Rlb0xeaYqz43fFyijsZyWAG1VzPnhGDbz6QbO2UZ/hKVvs3w3V7YyuI81B1nXwYb3uR0ZPmHziyGKsAeknKDkCEkjwpIzIo2KymNj8gRV7gd5dMM0GmfQ8qM5/5KP/5pPV3NODf0bWLqZ5a9z5XYGd7JmN+va2IBkrzD7RIpfDFSEJSBSg8IaktLDUkZEGhyVMmNSPyhbk3N0+QF3MrP7D7PpXsCpz3F6GX0VLK5i6RqW13DlRga3sGYbX03UBuGF8EH4IRSIAEQQUghSGFIEUvQ+UY4/rHogkwfT2n92cZSbj07llOl80sdZxVxQysXlfHElA0GuruE6wG2CJ0l4k4XPLPwpQhkgAgNFMFUKpUnhdCky6Ed3Ius5BuYO/O/Te4QeF71uzprK+dO5yMeyYlaUsrKcwZVcH+TGRA0D4B4ITyq8VvgGCb9NKFkiYBfBbBHKFeHhP6RL8UmSViDpHpmF/ZlhnD+CJWNYOolLPQxM5yof1xRz/RJuWMrNv2Ij4EyFywp3BjyZ8A6FL1v4HUIZIQL5IjhGhMY/pMeektSZUnyOpC2U9EX9yQyuGMbKEVw9hmsnscbDDdO5ycfXivnGEjYt5U7AkQZnBlyZcA+FJwfePPicwj9aKONFwC2Cj/WDRMQnoguk2HOSWibFKyStqj8/gBsyWD+MW0awcQy3TWKThzum8x0f9xSzbQn3AXYrHIPhzIJrGNwOeEbCOxq+8cI/WSgeEXjqQQcioohohRSrktS1D0fC5gHcncHoMLaN4Ltj2D6JBzw8NJ0dPr5XzKOAzQp7BhxD4MyGKw9uJzwueCfCNwX+aVCKEJiH/xNCaxX6QYmdKVQH8ZidJ4azazRPTeTHHnZ7eXY2zwHWVNgGwZ4FRzaceXDlwz0WHje8Hvi88M+GshCBJf+Dru4V8cNCOyb0uEQthT2DeMXO3uG8OprXJvJLD/u8vA5YLLBaYbPBbofDAacTLhfcbng88Hrh88Hvh6IgEEAwKEIhEQ6LSEREoyIWE6oq4nGhaULXJTKFHETayeHkaHIi6Un8i5BsxgALUq0YZEOWHdkO5DmR78JYN9weeLzw+jDbj2IFpQEsCyYMBOvCqItgaxRvx7BXxZE4jms4p4semq8wvZdDrzLvGkdd48S+hIDBhCQzzBYMtMJqQ4YdQxzIdiLPhXw3XB5M8mKKD9P8mKlgXiBhICgLYUUYqyNYH0V9DFtV7IyjLfGB0MWHNP+V6cc59CTzPuKo0wkByXBPw2hGsgUpVlhssNox2IEsJ7JdcLgx0oPRXkzwYbIfU5WEgeCZIJ4NYVEYSgTLo1gVw0sqXokjrOEtXbxD8++Z3sKhe5m3LyEgpHsasgkGM0wWJFuRYoPFDqsDGU5kumB3I8eD4V44fRjjTxgIJgfwWBDTQpgRhi+ChVEsjuEFFcvjWKWhWhchmjcyfROHhnlvHRJdQBggmSCbYbDAZEWyDWY7BjqQ6oTVhQw3Mj0Y6kW2L2EgeERBfgCuICaE4A5jSgRPROGNYaaKuXEUa3hOTxhIcjmtAd5fufsawgTJDNkCgxVGG0x2JDtgdmKACxY3Uj1I9yYMBDY/hiiwB5AThCOEEWE4IxgVxdgYJqhwx/ELLWEgmMbkGXy41vc0kPAvE4QZwgLJCskG2Q6DAwYnjC6Y3EjyJAwEZh9S/BiowBJAahDWENLDyIhgcBSZMQxRYY8nDAQ5Ohz8D28m/FokjZPFAAAAAElFTkSuQmCC",
3296       "f00n2c08.png", false, 32, 32, "d70ea8925988413a9fe9de1633a31033");
3297   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAABCElEQVR4nIXSIUvEQRAF8Pd2dnb2BDEIgsFgMVgsJovJZhIMNsFgFC4IpuOSYDi4IlwQDIJBMIjB5Cew+I0MHvff2bC7+ce+meFxki2bmaWUVFWjShQRCSGQJMjbUUfcWFvwOnfEpXXEhXXEmXXEaWoLnpgT5/j2gsepFFfAl/+DR1qIMYAPn8LDNIgpALz5OXigKzEHZmO8+Em5ryuxwCTf4cnvwr04iGyjKR79ttxVJx4w8/fgTnRijnt/MW5HJxaoGsQtceIZVYO4KU68omoQN6IT76gaxPXgxCeqBnFNBvGD/1emMIdB/C5BmcIUClHedCkYQ1tQ2BYMbAuSbUF0BNERREf8AZVRLIMTf6sKAAAAAElFTkSuQmCC",
3298       "f01n0g08.png", false, 32, 32, "38446c18ff7e0ca3951b7ad5fa5e81c0");
3299   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAEY0lEQVR4nK2WP+wlVRmGn/f8/c6cM+fsCDQEIhRYidlCY4GRBBIrsdCQmFCwncZGCk0oLGhIKCgsjDGxojBWkoCxNdBSkKWl2cJCowkNJSzXYu7cndn97Yagk6d4zzfJfZtv7nN0wrCM2ZliV+ev9qqYPnk8L07kTLYzZlfnr/RKt76bR2AJImWS3SHb/+Womy+kkTQiSxYxE+1Asv9xovdvxJEZppFZigi2IxMKwYi7fN95Jtg2v5P111+GXjQKY9IoLFV425Hx5ZDDfeZrCHYne8MX/ek3oU/0SaMymkZlmYWzHRlXHpT9fp5xts/6w+thbvRKnzUao2vMLEPIdmRUvnTOyC5Zb77pW2Oe6V29MwZjaAyWRWB3IX0AnE4/uvfV/dArr/naqI0607paZx70oXkwFgm78Jg+BoB/nX4A5rb5lRlMa/7pr51VlcbUKDO1a+rUQRuqg3mRwxz2Pf2b7fnw9P11+GXQc79wuZIr1siNMss6pVOGpkEZ1EU39Bm7593Tdzx2PwJlf9T1lxWrYiVVUiM18qzcyZ08ZIPfPvn5+rtvnB55Vf8Bfnd6OmB74vEYKJesJ15UmPBVsRIqoREbcVbsxE4aevf658CNU4zYH/Up8KvTUxFbSVu4i0RZgx76oVzBT7gqX/EV3/ANPyt0fCcMhYEfxEXv6TPgx6fHE7aSt3DVpCRM9rxUUMFNqKKKq1LDNTTjOq7LDdxAg3987TbwrdPDGcvbv3zeYZTj0cQzyKBAgQkqVFShQYMZOuowYHD7SYB2epAKyvEovp3IkokiiphEFdWpiuZoYnZ0qTuGu339n0A4ff3BKii7o/hmxUR2mKM4Fc/kqJ7qqJ7maZ7Zqwe6/+LZjwD3yTNawtEAZwmUe5wgvtFJDvNkj3mKVwlMnhrOtEgLzFE9fvHC3wF36yeMqCXf44FopHKciCcGKZA85snrEkeVwBSpkZqokZZomTmdXnobcDd/xjBG1lLsKBA7eyBesnj02rkgBSySIxYpUSUxJWqmJqrRMs1OP38LcO+/yiiMiVG0VDsKZOXiCvHINaInRVIgRSyS1yXOlMyUqcbv3+GqR7f+zKhaZjsKxHbSENc6MRAjaSVhiZyxTDGKMRlv/eXqgpt/Y3TGrGXYUSAXIYh5xntiJEZSOmNGXr+bQilME7VSq2qlNTaBsAmEMbQs99qggLCCD3hPiMRITMS1xs6XJStYoUyUSqlMlZ1A2ATCPDQW2wsEikOEhPe4rcNHYiKsNUbM5/3OBZvIlVKxyk4gbAKhDs3LXUIQLuAc8viA8/iIj4SET8R0voOc97uQJ1LlKBA2gTANylBd9n4QchseF3AeF/ERn84Ew2fiut+FOBErR4GwCQQb5KGyXMwgVi4d2joU8QmXcGl/zyEUwoSvHAXCJhDSIA7ysppB676dO9g65FFEEZfQWmMo49cVPwuEo0DYBMImEEvngq2DrYOAPEQUUYKE0vHOcxAIR4FwEYhf/gtC7nstgnuX5wAAAABJRU5ErkJggg==",
3300       "f01n2c08.png", false, 32, 32, "a9081889af0c30f206d793919792a0b6");
3301   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAABKklEQVR4nIXRL0uDURgF8MP5OBaLIIggCIJBDAODTdgHGCxYh0kwDFYEwwsLA8Ng4U2CYBLBYrEYLIJBEARB9H3uX8Om97nvwr35x+Wc83BwOjyvJtP66ub2/uHx6fnl9e394/PruzHW+RAifxppRESMMdZa66x33nsfQogxRkRKQbApCEpBUAqCUhA0BUHR4mB/d3tzPRM0SnQBAMgEbRJ9oJpM61zQJAEMRURqQOWgTQKYJwVUUtokesfzLoDqQqfEogug2tIuiS6g9qBriz5QqcXoWuJk0eVP0OdiBAyy1ekzMQZ6+V3otJgBR63LMShxDXTat6VP4g7A7HJ8MTpTgiEJ/D/1B0MSK6trG1s7e51DnYNBieXVRRgLgrEgGAuCsSCIgiAK4hfp5Je/v8zr/QAAAABJRU5ErkJggg==",
3302       "f02n0g08.png", false, 32, 32, "9af1c44cbb489e5385f422d047612dfc");
3303   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAGiElEQVR4nG3VSYgkeRXH8W9ELVlLV2Vl7dXrDIjiwe2ieNDGkyCIoA6ic+jBy0AjeNDGg4cZ8KAwAyIIjiCIg+0CguAoKiLSiLjggj30lN21de1V2VUV9Y+Mf74XEZnxPERGV9Z0x/F/+H9478X//UJjxEbqNrVgi9fsmXfZu99nH/iQffi6fezj9olP2ac/Z1+4YV980W5+2b7yNfv6S/aNb9or37bvfs9+8EP78U/tF7+0X//W/vgn+8tf7V//sXvLtr5he/t2EllbzCyMrhgLKfPKnDKrTCvTSkOZUiaVSWVCuaCMK6PKqDKi1JQhZUgZVAaUUEFBMaVQOkpHyZVMUQ3dRaLLxlLKorKgzCuzyowyo0wrU0q9TxpXxiqppgxXzKASKkEf0+0xoZs3t0i0ZFxMWdKnM42KmagKGuurpna+mvNM6GbMzRZuwaKFgkvKRe1jpI+Rs75NSK9p48qY9JhhYUgqRgikZMK4bq6BmzY3RzRnXNY+JmVBqmrSntFQplLqwmQ5m5QxYVQZSakpNWFYGUwrRsN4gnjSXB03ZW6GaMa4on1MyqL0mjaXMivVL1AZE8pEygVhXBlLGamMoZRBZUDC1ijxOPEFc5O4SXMNooZxVfuYlCWpmpYyV/VtOqUhVdP6jFFlRKgpwylDGiY1a9UsHrV4zNwFcxOFq1tUL7gmXBWuCJeFSxpc+ntw8U6w9Ptg8VfBws+D+R8xK9VshCmhrkzK2XjGhFFhRMOdhO2EzRbrsa3G3HcsO3vLcTeyTXQL3UaD4AFPfEHw+hF6jB6jEXqKOtShLTRBE9SjgoYH3nYTthO2WmzEth6z4vifs2XHm5FtoFeDZnnj3+yd/7D3/tM++G/7aHkyF7zeRI/QUjpBTyvpMRM2PYfe9hPbTWy7ZZuxbcS25uyBs/vO7kVFeddPbG4T2UK2kR3kN/aR8vwAOUSayCPkCDlGHlcToy00PPF25Gl6DhL2E3Zath2zGbPhbNWx4noNWUc30Ifo476V53voPnqINtFHvWqkrKaUwtM2kbdjz5GnmXCQsNeynZitmIfO1h2f3Rj8/MngKrqG9jMlsIvuoSVzcCadGWFLcG2ctxPPsecooZlw0LK9mN2YLWcPHRuOlchW0H6mBMpqdtDdiimNJlIWFHohEeI2sbdTbyfejhMeJTRbth/bXmw7zracbTpbi4oHyAqyivwsWCmBh0j/bM5XI4+QUNVUTMR82xJvLW/OFy4poqQ4aRVHcdGMu4euu++6e667HXXWSO4GR+Xt77BnNvFb+G38Dn6X9i5+H3+AP8Q3aTdph6TDpjVkBBmlPYYfx18wP0lSJ2nQmiaetXgOt4Bbwl3qBL2xz9p7nhogcj5AQnSIdMh02KRmMtJnTFgyacmUtRoWz1g8Z26+++xuefuAXRcWhQVhXpgVZoQZqQJEmJTesx4PyQbQQdIhdBipmdRoj+JHS4ZkgqROa8riRnH9v+Xt4cZnLFp622YvV648ESAhWUA2gA6QDqCDyJDJMO0afqTHJOMkE/b8n3u333kBN4tbsGhBnwgQ7W2ox8xUCQRkARpWxqDJEO1hfI+xr/6ht39uv0hcxzVw07g5i+b0fICcz6lppRGSQ2aVEZAGaIgMmAxae8j8kL3yu8cLzp7/fvHJ7xTXv1W8/6Xi2VvF9JeKaObxyhUuCkt9s5kTZkPygtzIjAwy+owQGaA9+OQePfe5hkUNPR8g2hcgIV0jL8gLsoLMyAw1UlAQkIDnnuPGDW7e5Nat4OWXg1dfDV57Lbh9O3jjjeDOHdwErm5RXbn2NkZYUhZD8g55lzRHcySjneEzWkqc4pRIOBGO2jQ9B972vO0ktp3YZsvWY1uN7b6zZWdvueJudO5N7yK7yD4hnS6dDnmXLCfNkQzJ8BmJ0kpxymllPPIceg48fQFCFSAsO3szOrdyd5AdQoqCbpdOh06XLCfL0QwtS1GSlFhxwqlw3ObY0/QcevYTdhO2W2zGbMSsOR447ju7F+n5zR5iBUVBURl5TpaTZqQZktFWfEpLiQUnRG1Oys1+FiBUAcKqY8XZctS/2UPMKCqj26HTpZOTV4ZmtJV2SqK0BCectonKzX4WIFQBwrpjzdn9SFaRNWSdEAwMK7CCokvRodulk9PJyTKyklEkxSteqAKE8wFCFSBUAaIr6Cph+YCeYnRzOjl5Rl4ZmtJW+gKE05LpBQj7MXsxO44tx6ZjLdIH/B9DPhSnV2U9PQAAAABJRU5ErkJggg==",
3304       "f02n2c08.png", false, 32, 32, "14658e750fd12c4777c46a949bb3399c");
3305   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAABTElEQVR4nH3SsUtCURTH8e/phERREBENIUWCUBQ0BC4OQcsDB6EhCIoiECEDg6JIzOfaXxBCBUHQIDg0tTgINTQEDUHgH+C/8RrU53nKe3e5HPhw77n3d9R1Mtndvf3Do5Nc/vSseH5xeXV9UyqXbysV1626VU2JIIDQ24ZK3fKihW5KtNANooWuEi00SbTQBNFCl8QXhUb99eX56aF2nx8IjeOLJv2VG5yhi/ii+6d1+DC36IIMhCAcwLvtQ+cJiALUA53qHFaU4DH4Fp3FiDvgrZG1QmfM8/nGdZoEhE7bD0qlPRkSOoUViCdOk4yJe5IR0cIxcU8wIj7ZMXHHxBetdje5L7ZN3DHPFx3aCaAGaRP3uPgi3qH99/sDRZO+KgEBcGznQ8ewYnklubYemCAVrAgmJ4D2yzDRBRFCe0MWKvogVPggTAxAiPgHY2dcQrz+CzkAAAAASUVORK5CYII=",
3306       "f03n0g08.png", false, 32, 32, "bab714eea8df8ab97f4095442247c9e1");
3307   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAE0klEQVR4nH2WXYhUZRjHf8+8Z2fnzNcZv1r7kCyyD7Gy1CiN2kK3kAXDQjJCKk2FCr0QDAp6D3hjflB30lV30k1Xe9FtIMEiXlh2YRBi5UWCre7sfO6cfbo45505M7O7w2GY4Rze3/v/P8/7/I9RcjZXsMWKray2q9fa+x+y69bbRx6zG560GzfZpzfb57babS/al162r4zb13faiTft7km75y279x2771373vv2wAf24CF75Kj95FN77Lg9ccKe/Nx+8aX9ytpTp8yxdcYvRQRQhjKUoARFKEIBCpCHPPiQc9+jkHXfIzACHnhgwEAGMiAgAOboU55W8IOIgARTSmG6jEIKk0thYka2n2F6DPPh84ZANMBfkWKUHaCL6erIp3R0pSytw+zfnqGsVNBA/ZUDDKUozi6lIMnqvpITp0PJClkYUUbAEzzwFAMZIYN5+9UMJaEMFdEAf3WaIZSUklCEglBQ8kIB8oKv+EIORsUxJPFqRPDE6RAzuStDkT7GmiUYRcfIgy8pHcKoMuoYiY6EYSbeyCQmlIWSY4wty4i9WkZHimHGd0vSJHFJy0qABuqv7cQMCf4Kz/8bnr8VnrsZnvszPHs9PPt7eOZqeOZK+PW0Pb2l11qj/a01Ah5m4/ZMA+pQgzmkCrMwi9xVmn40C9+ELZb+fGafbUArdc3DPLRhHiIw67dJA6lDHeaglmLMKHU/+sgWDtrgkF31sR07bB88Yh/+LrwVr35N99WhAQ1oQtMx2g4zD+a+zdJ0D9USHTgGM6o1v3PP/a3CTvktXv0n3VWDeGdpRhtppxgm2EiLAYY4hszCjFL1o5hxWP6OV7+g2+bchgYATWghsY42mNzj0oYm0oKG29EwY9aPzko1Xv2EbqjCHMy555fRYcyjya8mEt9zNZdaijG1otMt7C/hf5fC2w/bVV0Raa8GdBhdJ/NOTiu516t5tx7VCwqsV2/M5u+EbeBqeHuFXTmXtEbXK+nXgek8QAQd11ttaKEttIk20DpaQ2to5jiZk8zqwozfzttcO+wAN8LbozaooXW0jjaggTbRJtpCW9BCDWNZ8Nz5y7rxGA+BvJvUBaEEZQjQSuSX8nasHd4ByvaJ4QCRVIAYVuYQA158+CQ5jjmXL11GHBFlCFQrHT/Q8Cbg263pAJGhADFUfNQgnjvdMSM7zBCKbo4HaKCnrwFZ+9pAgEh/gBhKOfBQk9IRD/hYiq92mql/ZOIZx4h1VPTbaSBj9wyFVFFSdhnyfpJAgzqSYnD5BsDUHzLxQpexsPlc3LIL9gCDQdjnlSGXA0mCrl9Hcu3YxOXrAFNX+fGKXpzW7y/Fq8uNi6pBx1+zKCMuuyGbdQEaM7yUji5jC5d/HZij8vMPUIIKGkT+2DAjDhDDSBaVfkbslZeSMsqOHYyPy8SETE7K3r2yfz+9egRoEPlrF2UYMgYVFpQFkiuCSOlIcvwGDnqjN0zSg1fvaqfp96ZufNWSFwxQQRWFKMWIhHnoOEDbjfzuUIynRGq4R3Wf9HCvYpIXMAWEBUWX1tFyjGUDJKr1MUyvaup0DHjV1bGoV4syqj2GcdvvZ6S96iiR9AGGvRpidGYThulrvZjUZSyvo5myq+6kpBl3fe4NAAYYw14t2lfNVM0HdMz4/wOljpe9l86W/gAAAABJRU5ErkJggg==",
3308       "f03n2c08.png", false, 32, 32, "eef71a6ef947497fe0c45ea2ba65c5dd");
3309   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAAA1ElEQVR4nIXRwW3CMBSA4d/2s81MnaFiBqQOwA0pp26A1EsnqJQtWAtCIebAAdsP2zlEetGn/9mKfG/iJsYYQwjeey/eiXPOWWuNMQYjZ1qPBUySpQmeQi5tgAV6BbAjgB0BrFz7QBW2nCqgCtUH+S/GLw3qwl+1syxMUN+qWsFRgVs2/OhAXTioX5MXZlhg4re5gt0FoKjIPZ+W7P0WzABMHFsrytITrC/x4UMMcWYfs1PIHdUoD7mixFKDUnwGDfSWDKSBkERfSKIvJNEXwkAIA/EAFiZMByGZYIEAAAAASUVORK5CYII=",
3310       "f04n0g08.png", false, 32, 32, "2bb4337fabd31e8786cbb3aec25315b1");
3311   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAADoElEQVR4nK2WzY4bRRSFv1tV/ed225SigSgiCx6AF+AJ2CTvAXv27Fmxy1vwAKyyZ8kqQooQUQQsBjwzjstjuy+Lqm6XPWPLIFpH1q3qdp+qW+ee206pqSvqOqGpH4//262mdn89V2/WVOxRn4jzYQEFOLBgSJdCD1vYwgYMCG7xDJx6t6bkANVlw0jj0uv2NDvYgsEtPlZKoVBfrdO6cpQXz4y7OaRxiydKpdRCpb4JaTkJmoIii0/Oa4otGEU00ribudIIjTIRGvVtwHIO7uK78QxuOpgoE6FVpkKrvgsY/gXsubvutoEWWqUTpspM6NTPA8L/AndXKRU0MIEpdMpcmKv3K9AMgIq8BlRfHs0/iEfZqnt3Rxv3gE6RKXToDOnQuQ/5asbrDwKDXuL8wxgQMOB+X2qNxA00aItMBrIW7XwY8/mFvIkE7wmXH5D7c0mFjkXaQA3NkLMGbf3KonbY+A/6+TvSzKM4Upm7XmqBFPsi1QqpiKxSQ4U2Pnwrt5HgV8JBqYz1cAp/f8ChFin2TyfKAi2REoph+V/r1VvC+bo+mne3qyhlNUi2NbWIA4s65KfPtpHgF8J5x3o445arJACDDoGMQ5N55fNr+4ZVheaoj4dH5qsuBM0lmPSeDfoXKXi/2AHi77ZyB3yqT2u2NbsMfU3fHA4d61IROaw/xUjSscA1YF9/wsKAUQz8BgSuLmkgjlDEN8Z8SHIWq8llbCTQm6vBzFwkWPFUKTNUmiU/DpXScW/Zv8sqVpIljkqLifr5KI9L+XEJT/Sr8+3CcS+HbuuUQpK44x/OXYFnj6l/XxiRYJDPAUdSnXzzJW3NtGJa09Uyq/sX3wPm7XfMm0B7tj9YxybaXn7I8QzGTVRQSbKPRpkkqS0+gqnSrnynmCMwBI5NDybz2JHDZCdRKKUkkTTpwcUMpjBTuuDnpxqCYxfbc4QeGjp56oa8VfLqFV3HTWogMFfmwftHD8mx2aaX74ZvjQ1sYA1rCLCCD7CEBo0eOzQQpgPFDO1Yzb0KewAGx3ZHvofxs+ke7iFAGCzmyNAnENvtJJFpS+j8cU+m72FITw8WduCGfThYZ/quBrITDUQbQutzHTm0pwcBBZPlysI2+xIp2MtqrJAy4xvtrSI0fiwJhyrapzOPmzBDrmympoNazCgfY9WCVeW1QAtc0oz2jPUQaQR2g92ZIcgpzYOqcgcrCIWnTFbzgIPsNw+OyjEP8qUMCwrW/wPZ2mq+jvKj/AAAAABJRU5ErkJggg==",
3312       "f04n2c08.png", false, 32, 32, "82a6745345706f5c5a662a94fdd0ea29");
3313   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAABcUlEQVR4nHVRsU4CQRDd5Y5kj2oXtDi7u1IbNFRWiom1iYk/IMYfMIpfQPwCPf0CobAzAQmxMkaOxMLCgl3srNzdCtaCrLNgMEGdu8zt7cy8eW/GQ3PmT7xXpsj2n2e3C3snYAeb7oxdfDdmkKFEF3IycLEVRwwsH5dcFGDKS2EYBAFCJvvmQMt5xjCUIBvJe5dzmDTaaa+fdlvJcRFAF/fjmDKIKCvE000GrTIG/wxezFgBQEvLYY5ARmCIRurB9xiUOTaIKipZEfnVqzaX0lopebdZ28DZo7Vo2lYrJXkzM+VPvx2w8NbDfECAJjLQWXF/fh4oe9pIBWAC6kfaOt/5DWqt1giUIefh7OGVkGFMjEF2ZN5lzx8rJ9yhaXgUzGz7rJFy4Mp52rqo/CVfKqu00nbyGYB8W8gR+kkMtB2KWzfTTkQpU473oD8lu11NLuv166RW+W9R446QQgzEZLmeqxm+kpGSL48/2x/fzdR/AW8Fs1uE53SkAAAAAElFTkSuQmCC",
3314       "f99n0g04.png", false, 32, 32, "207c771481d8e0786644d1d3ccdc1253");
3315   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAIi4vcVJsAAAARBJREFUeJy11U0KwjAQBeBXrFpFUCjFXcFTNJfwtF4itxBcCCKCpeJfbXUhQTMTE0N0FoEZ6Os3pbTR/Q6tokjvpdT7otD7uGn0wXwOa9EbsIAsswdQMQsYjwMFo1GgYDgMFAwGnoLbTR/0+4GCJAkU9HqBAtcKTkG36ynwXeH/AlcAE9T1jwVxrPdt6ymgr/Ll4hDQACqgAU4BDaDFBNerX8DXgtkMWC7VVAj1eWUCumOnAwB5vlqpExBCSnUygXmF9fq9k9IiOJ9NAgCYTjcbtYBFQFdQzyBNdzsYiglOJ5NgMgHSFNjvhZDyfQUmOB5NAVWl+udlrx8cExwOpoDPxQRl6RfABNttoGCxCBM8AHUVjIYrRN23AAAAAElFTkSuQmCC",
3316       "g03n0g16.png", false, 32, 32, "33bca103ab06d5288fc5a40d52b46648");
3317   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAIi4vcVJsAAAASlJREFUeJzllk2KwkAQRqsx/kQEERR3LrzEeAiP6yH6FC4EFzKCGGRGZ0bjwojJJI/kw7iyVpVKpV+/LgLtYisOZ/DGu+L6R3E5OANgPi+uL6DfgIuA0YhWggBhBPT7IoAM/qC/1xMBqkG3KwLUGYShCFANOh0RoM6g3RYBqoEMUA1aLRFABrUBVINmUwS8n0EQiAAy+IV+NLhAXTUIyeAH6qoBHhEByID6Xz4DGfCMwXTqzGy5zK4xMzMzf38kg1LAZOJWqzidJKv7bEIGJwA0GkmyXsf5ovnKBgT4N4Px2G02qU1WNzgC4LFZs+HQbbd0Q7sHGXyXAQYDd2OY2W4XJ1vOHxEZfJUBoij7qc8ltyCDAwBq+w/20J+eQaUgg8+6AGRAt+W6DK5anlkjB1vfagAAAABJRU5ErkJggg==",
3318       "g03n2c08.png", false, 32, 32, "5ab30d7747a459c1051650a1351a4519");
3319   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAAIi4vcVJsAAAAB5QTFRFAAAAAP///wD/AMjIra0A3d0A//////8A/93//63/MbogiAAAAGNJREFUeJxjKAcCJSAwBgJBIGBAFmAAAfqoCAWCmUAAV4EsQEcVLkDQAQRwFcgClKlg6DA2YEZS0dDBYcxsgGIGB1wFCKSlJaTBVUAE2MACCBUJDGzMQC1IKtLS4O5AFiBTBQBS03C95h21qwAAAABJRU5ErkJggg==",
3320       "g03n3p04.png", false, 32, 32, "cab490ee86d478d165f2a516345d0ff0");
3321   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAK/INwWK6QAAASJJREFUeJytlDkOwjAQRSciLAEkmjQpUtJwAE6AT+0bcAAaCgoKmhQgZWEJCUVkhZkxGVnGhaX5Up6fvxQHbQtoBQGetcbzbofnsK5xsN3C4KIHMEAcDwOocfh+42C18jRYLh0NKGCxcDR4vXAwn3saRJGjAQXMZp4G06mjAe1AAjADV4DYwWTiaSABxA6cDZ7PPxuMx3huGkcD+i/c74IBBVADChANKIAu0SAMhwHM4PGwG2w2AIeDSZUyzyszsAPW6+PR7ABKaW120aC7wun0PX0/7cyAttx3kKbnc59351sMqsoOSJLLhX9uMShLHHQdxDFAkgBkmVJaK9XXyAyKwmZwvZpZa6GDPLdf4ddiBrcbDkajYQAzyDJPg/3eDUANPik0iSilDmOAAAAAAElFTkSuQmCC",
3322       "g04n0g16.png", false, 32, 32, "e38a1551172886575b1d91af694ecfde");
3323   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAK/INwWK6QAAATBJREFUeJzVlj1uwkAQRr+VzJ+MRAMFBS0FB+AG8aF9hByAgoKGgoJIKFIifpLIFBiwg1+cT3GTKaz1eHfevJ3GIVN1BMGXNFTnn6rT0ScA5vPq/DPsF3ARMBxSJQgQRsBgYAJcg37fBLgGcWwCXINezwS4BjaADD5gf7drAlwDG+DOoNMxAWRAV9RumwB3Bv/fwAa4Bq2WCSCDE+xHgy/IuwYxGRDANcArOkCeDGwABRkcmwL8xWA2C5IWi3KNRJKUXl9dgyjKF9NpWC6z4iKvnpYXZEAzuwFWq+wxeW/8FmRAgG8zmEzCev3QZFIgkcEeAPdmpfE4bDY/Vhcb1AJGo3BhSNpus7xucmWobgbvdYDdrnw0LTyLQQZvdYDfBhm8NgUgg5emAGRAf8tNGZwBkU1XhkiDotcAAAAASUVORK5CYII=",
3324       "g04n2c08.png", false, 32, 32, "daa8561d65a6598e69d6ddb060d802b7");
3325   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAAK/INwWK6QAAAB5QTFRFAAAAAP///9T/1NQA/wD/ALq6//////8A/5v/m5sAIugsggAAAGhJREFUeJy9zsEJgDAQRNEhsLnbgaQFW7CAXOae07ZgC7Zgt04IhPWq4D8Oj2VxqF1RLQpxQO8fsalTTRGHH8WlipoiDt8ECqsFsZZEq48biaxD9NybkzbEGLILBNGQDYjCff4Rh5fiBou1fg11pxGVAAAAAElFTkSuQmCC",
3326       "g04n3p04.png", false, 32, 32, "0f81d4307736954402890d7203244bd0");
3327   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAANbY1E9YMgAAAQpJREFUeJyt1b0KgzAQB/AI0X4gSMcOzu3SxTdpHvQexdk+QRdBCqK2VewgQXOnCUeaQS8B//nlQA3GURgjCMw5gDm/3825/H7NhctFWAfeQPa9uXA62QOwmAiShCnAAXHsKTgemQLcA1eAU3A4MAWfDy/AKdjvmQJuABHgI+x2ngJXwP8F3ACnIIo8BThgGJgC/DK1rUPwftsFOIAIXAF4OAVhaA9gCLIsz3WtlP68EkHXrQtut7lWCkBfiWAroCiuV10DWAS4y8sm6toqwAHLJq41lAiaBi3I6X4+C5Gmz6dSAMsjEAEO0LuW5XSfHpt/cERQ19tHWBtE8HrxAoigqtCCZAoeDz/BD+1fhGYCQbPgAAAAAElFTkSuQmCC",
3328       "g05n0g16.png", false, 32, 32, "5f67c34aadb2f3a602fea6d4ad14fa6d");
3329   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAANbY1E9YMgAAARVJREFUeJzlljkOwjAQRcdS2EJEQUdDiWiochI4aG5Cj7gADaJA7ItCwSJC8iR/cMdUzvjHL8+xorjcqssZzGSuuj+ubkdnAAwG1f055A24COh2aSUoEI4ukO90RIBqkCQigAwI0G6LANUgjkWAatBqiQDVQAaoBs2mCCCDE+QbDRHwfwYyQDWo10UAGQTbomAGV+iTwRHyCQH20A9mQADVoFaDCSoyIECwU3SA/IdBmrrptLjGxMzMsuflLwajkfvo2OS59Gvwi8Fslg+HruCUeRvQoSi/5ELH3+BLQLnIYOcB6PWcmfX7brHIH49c3iIy2HoAlsu3u7PS4F5ksPEAeBUZrCEfRSKADFaQD2ZAf8uhvkU3ajlNmZwVLFcAAAAASUVORK5CYII=",
3330       "g05n2c08.png", false, 32, 32, "30cda048c618598b39f96c40141851fa");
3331   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAANbY1E9YMgAAAB5QTFRFAAAAAP//zMwA/8z/AK6u/wD/i4sA//////8A/4v/c+IkkgAAAFtJREFUeJxj6ACCUCBwAQJBIGBAFmAAAfqoUAKCmUAAV4EsQEcVaUBgDARwFcgClKkwMHZxYEFWwWDswuKAQwUIlJcXlMNVIAsgqWBgZwFqQVJRXg53B7IAmSoA1Ah4O0rtoFUAAAAASUVORK5CYII=",
3332       "g05n3p04.png", false, 32, 32, "2be19a2ad1bdba9734899e453a27625b");
3333   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAARFwiTtYVgAAAPhJREFUeJzNlbsNhDAMhg1C4SVomYABqFiASchcmYkxEC2Ip4S4AuVEbCAXpbm/SUzx+cMC2TkOUOI4ai2EWte1Wnvbpj7IMngNbkAAafoOwMYEkCSWBnFsaRBFlgY6gNYgDC0NdACtQRAYGqyrGeAPDUwBWgPftzTQAYwN9t3QAP/O02RpgAHEYFneATjEwBSADdwFhX1TVYwxBgDA+dVAzaNBWd7baGdw9gRomqKQ92vIDOb5HoDvnJ8bghj8BuBcIrCBO6HIEeY5QJ4zxjmAEELIHXWgePhDkV3b9jzlapMnmcE4Pr/CXcgMhsEMQAz63tKg6+wMPgLFodTQLHMsAAAAAElFTkSuQmCC",
3334       "g07n0g16.png", false, 32, 32, "cdd82be241cbfadbceffc98d967dfe30");
3335   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAARFwiTtYVgAAAQtJREFUeJzVlkEKgzAQRSciiaK49QS5gCsv4EnqsXImryHdlhZtKdhFK1U6HzM0YDvMIowhz+dXUE3ElyJwxSl+fuDH8Q0AypKfH8F+AlwIKAohAAhDQJ6jk0BJDbJMCJAaiAFSgzQVAqQGYgAyuIYC7GaAAEkiBCAD9IjEgJ8zMEYIkL5F/28AAXcwlxoUUgAyGMF+aHAB890yQAZaCwHAIBqJ2DZm1U2jnotXtZwB114Gda22nVAGgweg66aqUhsAlAECfIbMxN4SuXn9jQE/adcMYBANRGxr/W5rFRFZq7Sez3XzuUsDrmP03Szvt+8X/o74NcrAB+BVKINzKAAyOIUCIAP0MxvK4AEWgFoVP+GhCgAAAABJRU5ErkJggg==",
3336       "g07n2c08.png", false, 32, 32, "0dcc8b7a828dd05df802b636673ed0ab");
3337   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAARFwiTtYVgAAAB5QTFRFAAAAAP//AJycv78A/3b/dnYA/wD///////8A/7//TpdUbAAAAFxJREFUeJxj6ACCNCBQAgJBIGBAFmAAAfqoMAYCFyCAq0AWoKOKUCCYCQRwFcgClKmYMFOJCUUFA1gAuwoQKC8vKFdiYoKogAswMCCrYGBnUkJRUV4OdweyAJkqACOga73pcj3PAAAAAElFTkSuQmCC",
3338       "g07n3p04.png", false, 32, 32, "8f1a3f91ca328ca507273e80324087e9");
3339   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAYagMeiWXwAAAL1JREFUeJztlTEOhCAQRT8bCyw9hlzD0tIDIQfyCF7D0ktYSGLBFoTFmUQC2WRjsv4CZqaYefwQEM6BSAiaa03zcaR5ZS0tSImk+IDiBpy42ndaqOtfEzwe3MGDrwlKTfxHD46jkKBp0g2KPdi2QoI73YNhmKYQGxOe12wP+j7Gxmgd1myCee66sx/G+J0TvCyT/Ajwa2QAAMeUNDHG8XvhBKJtaSEYpxQALItS/vyhSfbPtK7n2dcEz6sMvAHqCJi/5fyWiAAAAABJRU5ErkJggg==",
3340       "g10n0g16.png", false, 32, 32, "75b64641f0a3c0899ae3b466fcb97c06");
3341   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAYagMeiWXwAAANRJREFUeJztljEKhDAURP8HC+32HpYewdbS+/zNfbyCx7D1FAu7xUK2cA0aM0j4ARWcKhlNJsNTkS2FxQSuCIf9Z9jO3iAgz8P+B9xPIDdDC6IDQOHoAKhUDaBQA8SgKCIDDmtwM3C6GezqsAbJIF+HwRf4sQ0eKOAF/GQMUMB1GCApG7Qtd916D0NERDJPNQ2ahv1IM2/tBpqvad/buuYAdrMY6xn4znR2l6F/inxH1lNNg7JkIqoqHgb7P7hsIGsYjONitWwGk87+HuzrdA1S/VX8ANStTVTe34+eAAAAAElFTkSuQmCC",
3342       "g10n2c08.png", false, 32, 32, "69926b0e52c1371c81ca49d7cd0cf2b1");
3343   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAAYagMeiWXwAAAB5QTFRFAAAAqakAAP///6r/VFQA/wD/AH9///////8A/1X/7g7bWgAAAGNJREFUeJxj6ACCUCBIAwIlIGBAFmAAAfqoEASCmUAAV4EsQEcVLkBgDARwFcgClKkwME5LYENWwWCcxpaApoKNAaICBMrLC8rTGKAq4AJALUgqGNjZgIYiqSgvh7sDWYBMFQBG4oXJmToRDgAAAABJRU5ErkJggg==",
3344       "g10n3p04.png", false, 32, 32, "832e5401524ab7238a6eccd5d852b8ef");
3345   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAA9CQ+FSITwAAATZJREFUeJyllMsNwjAMQN0SQHwixGeNbsSBAToHXQDuHLoCi5A1CgjxhxY4RFGxLRJZ+FDXVvLy6laN3m9AEUW4ThJcbza4VkUBoqAHqO1WBqDGarfznxA02O9lAGYgBTCDw+FPAwqIY6HB8YgbjYbQQApgBqfTnwbnM2koocHlghvNptDgepUBmAEFtFpCg9sNN9ptocH97geUZcCAAgYDXNPXzAweD9zodPwAZvB8+gE0mAEFdLt+ADOgQ+r1bF6tAGYze29M/WtlBlWFG/0+AMBikabuGjCgAK1dzrK6qoMaxBUJrbXWGiDL5vNvgDHOAId6vTDRfQfL5XdljJsEmwF9Jrslz6dTgDy325KkHiSbAW0Mhzav1za7+bscNHCAXxE0GI38AGZAF4zHQgO6YDKRGXwAuz+aGCA4FKQAAAAASUVORK5CYII=",
3346       "g25n0g16.png", false, 32, 32, "698f892bb4453fdd325ae414dc82b34f");
3347   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAA9CQ+FSITwAAAUxJREFUeJytlcttAjEQQMeLgSAQ4SPK2I44UAB1oC1gC+BACVQSykB8hIgSSIJzwFq8xE/KSB75MIxn5+lpLGGcxMMI3OQmXn+Ll+0WAOoArt2lAoCw3acCkMGB+uED2hkaHFMByIAAWRav3whABiclAIMMkgHI4Az9jYYSQAYEsFYJIIP3VAAySAYggw/ob7WUADIgQLOpBJDBJ/S320oAGVy0gB+okwEBXl/ggl4FGXxBf6ejBJDBVQugIINv6O92lQAy+A9guTQiMpsFMzYief0DrUGv55OyNPO5C5N4kAG9ugpwz4vCPBWfAwyym0j09Pv+iEhRmMXCififj9jUDWLH0l9gOKss3d+in14tg3ZAgMHAJ6uVm07NPXlMzOvThXdAW6sAIrJeB13h4wlzMiDAcAgXFGRA/aOREkAG1D8eKwFag8lECQCDX4gtYR8yuXeNAAAAAElFTkSuQmCC",
3348       "g25n2c08.png", false, 32, 32, "a64f63bacd6a0edec500179d538ede01");
3349   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAA9CQ+FSITwAAAB5QTFRFAAAAAC0tAP//EBAA/1z//xD//wD/XFwA//////8AUlHX5QAAAGRJREFUeJy9zrENgDAMRFFbSpHWK7ACC7jICqzACrSUXoFtc1EkczVI+eX5FZYHncjQhoQHGa0RFzpQCh4Wih01lIKHf0KaKQtvZQyvcC8pRnHXaqpTzCEqziRCQo0Fyj94+Cg6NXRmxzu0UNgAAAAASUVORK5CYII=",
3350       "g25n3p04.png", false, 32, 32, "c2b4d9eb0587bc254212b05beb972578");
3351   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAYagMeiWXwAAAF5JREFUeJzV0jEKwDAMQ1E5W+9/xtygk8AoezLVKgSj2Y8/OICnuFcTE2OgOoJgHQiZAN2C9kDKBOgW3AZCJkC3oD2QMgG6BbeBkAnQLWgPpExgP28H7E/0GTjPfwAW2EvYX64rn9cAAAAASUVORK5CYII=",
3352       "oi1n0g16.png", false, 32, 32, "a14e204bbf905586d3763f3cc5dcb2f3");
3353   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAAAOVJREFUeJzVlsEKgzAQRKfgQX/Lfrf9rfaWHgYDkoYmZpPMehiGReQ91qCPEEIAPi/gmu9kcnN+GD0nM1/O4vNad7cC6850KHCiM5fz7fJwXdEBYPOygV/o7PICeXSmsMA/dKbkGShD51xsAzXo7DIC9ehMAYG76MypZ6ANnfNJG7BAZx8uYIfOHChgjR4F+MfuDx0AtmfnDfREZ+8m0B+9m8Ao9Chg9x0Yi877jTYwA529WWAeerPAbPQoUH8GNNA5r9yAEjp7sYAeerGAKnoUyJ8BbXTOMxvwgM6eCPhBTwS8oTO/5kL+Xge7xOwAAAAASUVORK5CYII=",
3354       "oi1n2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3355   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAYagMeiWXwAAAEBJREFUeJzV0jEKwDAMQ1E5W+9/xtygk8AoezLVKgSj2Y8/OICnuFcTE2OgOoJgHQiZAN2C9kDKBOgW3AZCJkC3oD2QMjqwwDMAAAAeSURBVAG6BbeBkAnQLWgPpExgP28H7E/0GTjPfwAW2EvYX7J6X30AAAAASUVORK5CYII=",
3356       "oi2n0g16.png", false, 32, 32, "a14e204bbf905586d3763f3cc5dcb2f3");
3357   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAAAIBJREFUeJzVlsEKgzAQRKfgQX/Lfrf9rfaWHgYDkoYmZpPMehiGReQ91qCPEEIAPi/gmu9kcnN+GD0nM1/O4vNad7cC6850KHCiM5fz7fJwXdEBYPOygV/o7PICeXSmsMA/dKbkGShD51xsAzXo7DIC9ehMAYG76MypZ6ANnfNJG7BAZx+ZiKBzAAAAZUlEQVQuYIfOHChgjR4F+MfuDx0AtmfnDfREZ+8m0B+9m8Ao9Chg9x0Yi877jTYwA529WWAeerPAbPQoUH8GNNA5r9yAEjp7sYAeerGAKnoUyJ8BbXTOMxvwgM6eCPhBTwS8oTO/5kL+Xk13nmIAAAAASUVORK5CYII=",
3358       "oi2n2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3359   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAYagMeiWXwAAAB9JREFUeJzV0jEKwDAMQ1E5W+9/xtygk8AoezLVKgSj2Y8/OIdtk98AAAAfSURBVICnuFcTE2OgOoJgHQiZAN2C9kDKBOgW3AZCJkC3oD3Oo8vsAAAAAklEQVSQMsVtZiAAAAAeSURBVAG6BbeBkAnQLWgPpExgP28H7E/0GTjPfwAW2EvYX7J6X30AAAAASUVORK5CYII=",
3360       "oi4n0g16.png", false, 32, 32, "a14e204bbf905586d3763f3cc5dcb2f3");
3361   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAAAGNJREFUeJzVlsEKgzAQRKfgQX/Lfrf9rfaWHgYDkoYmZpPMehiGReQ91qCPEEIAPi/gmu9kcnN+GD0nM1/O4vNad7cC6850KHCiM5fz7fJwXdEBYPOygV/o7PICeXSmsMA/dKbkGShDblRaWAAAAB1JREFU51xsAzXo7DIC9ehMAYG76MypZ6ANnfNJG7BAZx9l6MXmAAAAY0lEQVQuYIfOHChgjR4F+MfuDx0AtmfnDfREZ+8m0B+9m8Ao9Chg9x0Yi877jTYwA529WWAeerPAbPQoUH8GNNA5r9yAEjp7sYAeerGAKnoUyJ8BbXTOMxvwgM6eCPhBTwS8oTO/5kIg4uIpAAAAAklEQVT+XnoXDXoAAAAASUVORK5CYII=",
3362       "oi4n2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3363   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAYagMeiWXwAAAAFJREFUeHbmhOYAAAABSURBVJzRgaKHAAAAAUlEQVTV3oFbswAAAAFJREFU0kDlzhAAAAABSURBVDF55n3SAAAAAUlEQVQKyO2U9gAAAAFJREFUwLNcv1gAAAABSURBVDAO4U1EAAAAAUlEQVQMIY4xwwAAAAFJREFUQ8ftbcIAAAABSURBVFE0VByKAAAAAUlEQVQ5dz314AAAAAFJREFUW9SB9ZQAAAABSURBVO8YjYIBAAAAAUlEQVR/6IIRRQAAAAFJREFUxlo/Gm0AAAABSURBVNynXeMXAAAAAUlEQVSg/u7eAAAAAAFJREFUk0E+vxYAAAABSURBVMCzXL9YAAAAAUlEQVQoHY3VEgAAAAFJREFUe+/v1VwAAAABSURBVDLg7yxoAAAAAUlEQVTV3oFbswAAAAFJREFUKvODtD4AAAABSURBVAQvVbnxAAAAAUlEQVSjZ+ePugAAAAFJREFU2dc3F5gAAAABSURBVI9VP+NZAAAAAUlEQVQ/nl5Q1QAAAAFJREFUOAA6xXYAAAABSURBVIDFgP7IAAAAAUlEQVSnYIpLowAAAAFJREFUuO2CRlYAAAABSURBVFfdN7m/AAAAAUlEQVQTrIY8NgAAAAFJREFUE6yGPDYAAAABSURBVGP8g00KAAAAAUlEQVSg/u7eAAAAAAFJREFUOu40pFoAAAABSURBVIIrjp/kAAAAAUlEQVRgZYocsAAAAAFJREFUHUs+ETEAAAABSURBVAgm4/XaAAAAAUlEQVSZoetWCAAAAAFJREFUACg4fegAAAABSURBVN3QWtOBAAAAAUlEQVSCK46f5AAAAAFJREFU9nzmKsEAAAABSURBVEBe5Dx4AAAAAUlEQVTKU4lWRgAAAAFJREFUBC9VufEAAAABSURBVOiG6ReiAAAAAUlEQVQW3OzIuQAAAAFJREFU3Kdd4xcAAAABSURBVAbBW9jdAAAAAUlEQVRCsOpdVAAAAAFJREFUJvo1+BUAAAABSURBVEBe5Dx4AAAAAUlEQVS3fT1bxwAAAAFJREFUoP7u3gAAAAABSURBVD1wUDH5AAAAAUlEQVSQ2DfurAAAAAFJREFUMuDvLGgAAAABSURBVAFfP01+AAAAAUlEQVS6A4wnegAAAAFJREFUBVhSiWcAAAABSURBVLd9PVvHAAAAAUlEQVSBsofOXgAAAAFJREFUkNg37qwAAAABSURBVAlR5MVMAAAAAUlEQVTQruuvPAAAAAFJREFULW3nIZ0AAAABSURBVGhrUZSCAAAAAUlEQVQPuIdgeQAAAAFJREFUpPmDGhkAAAABSURBVExXUnBTAAAAAUlEQVRgZYocsAAAAAFJREFUP55eUNUAAAABSURBVG/1NQEhAAAAAUlEQVQHtlzoSwAAAAFJREFU7IGE07sAAAABSURBVE/OWyHpAAAAAUlEQVT0kuhL7QAAAAFJREFUGUxT1SgAAAABSURBVDgAOsV2AAAAAUlEQVTPI+OiyQAAAAFJREFUf+iCEUUAAAABSURBVAAoOH3oAAAAAUlEQVQW3OzIuQAAAAFJREFU2KAwJw4AAAABSURBVEvJNuXwAAAAAUlEQVTYoDAnDgAAAAFJREFUX9PsMY0AAAAASUVORK5CYII=",
3364       "oi9n0g16.png", false, 32, 32, "a14e204bbf905586d3763f3cc5dcb2f3");
3365   testPngSuiteImage("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",
3366       "oi9n2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3367   testPngSuiteImage("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QOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDCAASABQ+gAAgAUDhAwgAEgAUPoAAIAFA4QMIABIAFD6AACABQOEDrNu2zb4Gs2n9C98FlZObRxMyAAAAAElFTkSuQmCC",
3368       "PngSuite.png", false, 256, 256, "183c2504778cb2b6384dbbad46fa2a2a");
3369   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAAAohQTFRFAAAAAAAzAABmAACZAADMAAD/ADMAADMzADNmADOZADPMADP/AGYAAGYzAGZmAGaZAGbMAGb/AJkAAJkzAJlmAJmZAJnMAJn/AMwAAMwzAMxmAMyZAMzMAMz/AP8AAP8zAP9mAP+ZAP/MAP//MwAAMwAzMwBmMwCZMwDMMwD/MzMAMzMzMzNmMzOZMzPMMzP/M2YAM2YzM2ZmM2aZM2bMM2b/M5kAM5kzM5lmM5mZM5nMM5n/M8wAM8wzM8xmM8yZM8zMM8z/M/8AM/8zM/9mM/+ZM//MM///ZgAAZgAzZgBmZgCZZgDMZgD/ZjMAZjMzZjNmZjOZZjPMZjP/ZmYAZmYzZmZmZmaZZmbMZmb/ZpkAZpkzZplmZpmZZpnMZpn/ZswAZswzZsxmZsyZZszMZsz/Zv8AZv8zZv9mZv+ZZv/MZv//mQAAmQAzmQBmmQCZmQDMmQD/mTMAmTMzmTNmmTOZmTPMmTP/mWYAmWYzmWZmmWaZmWbMmWb/mZkAmZkzmZlmmZmZmZnMmZn/mcwAmcwzmcxmmcyZmczMmcz/mf8Amf8zmf9mmf+Zmf/Mmf//zAAAzAAzzABmzACZzADMzAD/zDMAzDMzzDNmzDOZzDPMzDP/zGYAzGYzzGZmzGaZzGbMzGb/zJkAzJkzzJlmzJmZzJnMzJn/zMwAzMwzzMxmzMyZzMzMzMz/zP8AzP8zzP9mzP+ZzP/MzP///wAA/wAz/wBm/wCZ/wDM/wD//zMA/zMz/zNm/zOZ/zPM/zP//2YA/2Yz/2Zm/2aZ/2bM/2b//5kA/5kz/5lm/5mZ/5nM/5n//8wA/8wz/8xm/8yZ/8zM/8z///8A//8z//9m//+Z///M////Y7C7UQAAAOVJREFUeJzVlsEKgzAQRKfgQX/Lfrf9rfaWHgYDkoYmZpPMehiGReQ91qCPEEIAPi/gmu9kcnN+GD0nM1/O4vNad7cC6850KHCiM5fz7fJwXdEBYPOygV/o7PICeXSmsMA/dKbkGShD51xsAzXo7DIC9ehMAYG76MypZ6ANnfNJG7BAZx8uYIfOHChgjR4F+MfuDx0AtmfnDfREZ+8m0B+9m8Ao9Chg9x0Yi877jTYwA529WWAeerPAbPQoUH8GNNA5r9yAEjp7sYAeerGAKnoUyJ8BbXTOMxvwgM6eCPhBTwS8oTO/5kL+Xge7xOwAAAAASUVORK5CYII=",
3370       "pp0n2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3371   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAYagMeiWXwAAAohQTFRFAAAAAAAzAABmAACZAADMAAD/ADMAADMzADNmADOZADPMADP/AGYAAGYzAGZmAGaZAGbMAGb/AJkAAJkzAJlmAJmZAJnMAJn/AMwAAMwzAMxmAMyZAMzMAMz/AP8AAP8zAP9mAP+ZAP/MAP//MwAAMwAzMwBmMwCZMwDMMwD/MzMAMzMzMzNmMzOZMzPMMzP/M2YAM2YzM2ZmM2aZM2bMM2b/M5kAM5kzM5lmM5mZM5nMM5n/M8wAM8wzM8xmM8yZM8zMM8z/M/8AM/8zM/9mM/+ZM//MM///ZgAAZgAzZgBmZgCZZgDMZgD/ZjMAZjMzZjNmZjOZZjPMZjP/ZmYAZmYzZmZmZmaZZmbMZmb/ZpkAZpkzZplmZpmZZpnMZpn/ZswAZswzZsxmZsyZZszMZsz/Zv8AZv8zZv9mZv+ZZv/MZv//mQAAmQAzmQBmmQCZmQDMmQD/mTMAmTMzmTNmmTOZmTPMmTP/mWYAmWYzmWZmmWaZmWbMmWb/mZkAmZkzmZlmmZmZmZnMmZn/mcwAmcwzmcxmmcyZmczMmcz/mf8Amf8zmf9mmf+Zmf/Mmf//zAAAzAAzzABmzACZzADMzAD/zDMAzDMzzDNmzDOZzDPMzDP/zGYAzGYzzGZmzGaZzGbMzGb/zJkAzJkzzJlmzJmZzJnMzJn/zMwAzMwzzMxmzMyZzMzMzMz/zP8AzP8zzP9mzP+ZzP/MzP///wAA/wAz/wBm/wCZ/wDM/wD//zMA/zMz/zNm/zOZ/zPM/zP//2YA/2Yz/2Zm/2aZ/2bM/2b//5kA/5kz/5lm/5mZ/5nM/5n//8wA/8wz/8xm/8yZ/8zM/8z///8A//8z//9m//+Z///M////Y7C7UQAAAFVJREFUeJzt0DEKwDAMQ1EVPCT3v6BvogzO1KVLQcsfNBgMeuixLcnrlf1x//WzS2pJjgUAAAADyPWrwgMAAABgAMF+VXgAAAAAXIAdS3U3AAAAooADG8P2VRMVDwMAAAAASUVORK5CYII=",
3372       "pp0n6a08.png", false, 32, 32, "de9a6b2025046b20b3a408990a2b7e71");
3373   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAAABGdBTUEAAYagMeiWXwAABRpzUExUc2l4LWN1YmUACAAAAP8AAAAAM/8AAAAAZv8AAAAAmf8AAAAAzP8AAAAA//8AAAAzAP8AAAAzM/8AAAAzZv8AAAAzmf8AAAAzzP8AAAAz//8AAABmAP8AAABmM/8AAABmZv8AAABmmf8AAABmzP8AAABm//8AAACZAP8AAACZM/8AAACZZv8AAACZmf8AAACZzP8AAACZ//8AAADMAP8AAADMM/8AAADMZv8AAADMmf8AAADMzP8AAADM//8AAAD/AP8AAAD/M/8AAAD/Zv8AAAD/mf8AAAD/zP8AAAD///8AADMAAP8AADMAM/8AADMAZv8AADMAmf8AADMAzP8AADMA//8AADMzAP8AADMzM/8AADMzZv8AADMzmf8AADMzzP8AADMz//8AADNmAP8AADNmM/8AADNmZv8AADNmmf8AADNmzP8AADNm//8AADOZAP8AADOZM/8AADOZZv8AADOZmf8AADOZzP8AADOZ//8AADPMAP8AADPMM/8AADPMZv8AADPMmf8AADPMzP8AADPM//8AADP/AP8AADP/M/8AADP/Zv8AADP/mf8AADP/zP8AADP///8AAGYAAP8AAGYAM/8AAGYAZv8AAGYAmf8AAGYAzP8AAGYA//8AAGYzAP8AAGYzM/8AAGYzZv8AAGYzmf8AAGYzzP8AAGYz//8AAGZmAP8AAGZmM/8AAGZmZv8AAGZmmf8AAGZmzP8AAGZm//8AAGaZAP8AAGaZM/8AAGaZZv8AAGaZmf8AAGaZzP8AAGaZ//8AAGbMAP8AAGbMM/8AAGbMZv8AAGbMmf8AAGbMzP8AAGbM//8AAGb/AP8AAGb/M/8AAGb/Zv8AAGb/mf8AAGb/zP8AAGb///8AAJkAAP8AAJkAM/8AAJkAZv8AAJkAmf8AAJkAzP8AAJkA//8AAJkzAP8AAJkzM/8AAJkzZv8AAJkzmf8AAJkzzP8AAJkz//8AAJlmAP8AAJlmM/8AAJlmZv8AAJlmmf8AAJlmzP8AAJlm//8AAJmZAP8AAJmZM/8AAJmZZv8AAJmZmf8AAJmZzP8AAJmZ//8AAJnMAP8AAJnMM/8AAJnMZv8AAJnMmf8AAJnMzP8AAJnM//8AAJn/AP8AAJn/M/8AAJn/Zv8AAJn/mf8AAJn/zP8AAJn///8AAMwAAP8AAMwAM/8AAMwAZv8AAMwAmf8AAMwAzP8AAMwA//8AAMwzAP8AAMwzM/8AAMwzZv8AAMwzmf8AAMwzzP8AAMwz//8AAMxmAP8AAMxmM/8AAMxmZv8AAMxmmf8AAMxmzP8AAMxm//8AAMyZAP8AAMyZM/8AAMyZZv8AAMyZmf8AAMyZzP8AAMyZ//8AAMzMAP8AAMzMM/8AAMzMZv8AAMzMmf8AAMzMzP8AAMzM//8AAMz/AP8AAMz/M/8AAMz/Zv8AAMz/mf8AAMz/zP8AAMz///8AAP8AAP8AAP8AM/8AAP8AZv8AAP8Amf8AAP8AzP8AAP8A//8AAP8zAP8AAP8zM/8AAP8zZv8AAP8zmf8AAP8zzP8AAP8z//8AAP9mAP8AAP9mM/8AAP9mZv8AAP9mmf8AAP9mzP8AAP9m//8AAP+ZAP8AAP+ZM/8AAP+ZZv8AAP+Zmf8AAP+ZzP8AAP+Z//8AAP/MAP8AAP/MM/8AAP/MZv8AAP/Mmf8AAP/MzP8AAP/M//8AAP//AP8AAP//M/8AAP//Zv8AAP//mf8AAP//zP8AAP////8AACL/aC4AAABBSURBVHicY2RgJAAUCMizDAUFjA8IKfj3Hz9geTAcFDDKEZBnZKJ5XAwGBYyP8Mr+/8/4h+ZxMRgUMMrglWVkBABQ5f5xNeLYWQAAAABJRU5ErkJggg==",
3374       "ps1n0g08.png", false, 32, 32, "f6470f9f6296c5109e2bd730fe203773");
3375   testPngSuiteImage("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",
3376       "ps1n2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3377   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAAABGdBTUEAAYagMeiWXwAACHpzUExUc2l4LWN1YmUAEAAAAAAAAAD/AAAAAAAAADMA/wAAAAAAAABmAP8AAAAAAAAAmQD/AAAAAAAAAMwA/wAAAAAAAAD/AP8AAAAAADMAAAD/AAAAAAAzADMA/wAAAAAAMwBmAP8AAAAAADMAmQD/AAAAAAAzAMwA/wAAAAAAMwD/AP8AAAAAAGYAAAD/AAAAAABmADMA/wAAAAAAZgBmAP8AAAAAAGYAmQD/AAAAAABmAMwA/wAAAAAAZgD/AP8AAAAAAJkAAAD/AAAAAACZADMA/wAAAAAAmQBmAP8AAAAAAJkAmQD/AAAAAACZAMwA/wAAAAAAmQD/AP8AAAAAAMwAAAD/AAAAAADMADMA/wAAAAAAzABmAP8AAAAAAMwAmQD/AAAAAADMAMwA/wAAAAAAzAD/AP8AAAAAAP8AAAD/AAAAAAD/ADMA/wAAAAAA/wBmAP8AAAAAAP8AmQD/AAAAAAD/AMwA/wAAAAAA/wD/AP8AAAAzAAAAAAD/AAAAMwAAADMA/wAAADMAAABmAP8AAAAzAAAAmQD/AAAAMwAAAMwA/wAAADMAAAD/AP8AAAAzADMAAAD/AAAAMwAzADMA/wAAADMAMwBmAP8AAAAzADMAmQD/AAAAMwAzAMwA/wAAADMAMwD/AP8AAAAzAGYAAAD/AAAAMwBmADMA/wAAADMAZgBmAP8AAAAzAGYAmQD/AAAAMwBmAMwA/wAAADMAZgD/AP8AAAAzAJkAAAD/AAAAMwCZADMA/wAAADMAmQBmAP8AAAAzAJkAmQD/AAAAMwCZAMwA/wAAADMAmQD/AP8AAAAzAMwAAAD/AAAAMwDMADMA/wAAADMAzABmAP8AAAAzAMwAmQD/AAAAMwDMAMwA/wAAADMAzAD/AP8AAAAzAP8AAAD/AAAAMwD/ADMA/wAAADMA/wBmAP8AAAAzAP8AmQD/AAAAMwD/AMwA/wAAADMA/wD/AP8AAABmAAAAAAD/AAAAZgAAADMA/wAAAGYAAABmAP8AAABmAAAAmQD/AAAAZgAAAMwA/wAAAGYAAAD/AP8AAABmADMAAAD/AAAAZgAzADMA/wAAAGYAMwBmAP8AAABmADMAmQD/AAAAZgAzAMwA/wAAAGYAMwD/AP8AAABmAGYAAAD/AAAAZgBmADMA/wAAAGYAZgBmAP8AAABmAGYAmQD/AAAAZgBmAMwA/wAAAGYAZgD/AP8AAABmAJkAAAD/AAAAZgCZADMA/wAAAGYAmQBmAP8AAABmAJkAmQD/AAAAZgCZAMwA/wAAAGYAmQD/AP8AAABmAMwAAAD/AAAAZgDMADMA/wAAAGYAzABmAP8AAABmAMwAmQD/AAAAZgDMAMwA/wAAAGYAzAD/AP8AAABmAP8AAAD/AAAAZgD/ADMA/wAAAGYA/wBmAP8AAABmAP8AmQD/AAAAZgD/AMwA/wAAAGYA/wD/AP8AAACZAAAAAAD/AAAAmQAAADMA/wAAAJkAAABmAP8AAACZAAAAmQD/AAAAmQAAAMwA/wAAAJkAAAD/AP8AAACZADMAAAD/AAAAmQAzADMA/wAAAJkAMwBmAP8AAACZADMAmQD/AAAAmQAzAMwA/wAAAJkAMwD/AP8AAACZAGYAAAD/AAAAmQBmADMA/wAAAJkAZgBmAP8AAACZAGYAmQD/AAAAmQBmAMwA/wAAAJkAZgD/AP8AAACZAJkAAAD/AAAAmQCZADMA/wAAAJkAmQBmAP8AAACZAJkAmQD/AAAAmQCZAMwA/wAAAJkAmQD/AP8AAACZAMwAAAD/AAAAmQDMADMA/wAAAJkAzABmAP8AAACZAMwAmQD/AAAAmQDMAMwA/wAAAJkAzAD/AP8AAACZAP8AAAD/AAAAmQD/ADMA/wAAAJkA/wBmAP8AAACZAP8AmQD/AAAAmQD/AMwA/wAAAJkA/wD/AP8AAADMAAAAAAD/AAAAzAAAADMA/wAAAMwAAABmAP8AAADMAAAAmQD/AAAAzAAAAMwA/wAAAMwAAAD/AP8AAADMADMAAAD/AAAAzAAzADMA/wAAAMwAMwBmAP8AAADMADMAmQD/AAAAzAAzAMwA/wAAAMwAMwD/AP8AAADMAGYAAAD/AAAAzABmADMA/wAAAMwAZgBmAP8AAADMAGYAmQD/AAAAzABmAMwA/wAAAMwAZgD/AP8AAADMAJkAAAD/AAAAzACZADMA/wAAAMwAmQBmAP8AAADMAJkAmQD/AAAAzACZAMwA/wAAAMwAmQD/AP8AAADMAMwAAAD/AAAAzADMADMA/wAAAMwAzABmAP8AAADMAMwAmQD/AAAAzADMAMwA/wAAAMwAzAD/AP8AAADMAP8AAAD/AAAAzAD/ADMA/wAAAMwA/wBmAP8AAADMAP8AmQD/AAAAzAD/AMwA/wAAAMwA/wD/AP8AAAD/AAAAAAD/AAAA/wAAADMA/wAAAP8AAABmAP8AAAD/AAAAmQD/AAAA/wAAAMwA/wAAAP8AAAD/AP8AAAD/ADMAAAD/AAAA/wAzADMA/wAAAP8AMwBmAP8AAAD/ADMAmQD/AAAA/wAzAMwA/wAAAP8AMwD/AP8AAAD/AGYAAAD/AAAA/wBmADMA/wAAAP8AZgBmAP8AAAD/AGYAmQD/AAAA/wBmAMwA/wAAAP8AZgD/AP8AAAD/AJkAAAD/AAAA/wCZADMA/wAAAP8AmQBmAP8AAAD/AJkAmQD/AAAA/wCZAMwA/wAAAP8AmQD/AP8AAAD/AMwAAAD/AAAA/wDMADMA/wAAAP8AzABmAP8AAAD/AMwAmQD/AAAA/wDMAMwA/wAAAP8AzAD/AP8AAAD/AP8AAAD/AAAA/wD/ADMA/wAAAP8A/wBmAP8AAAD/AP8AmQD/AAAA/wD/AMwA/wAAAP8A/wD/AP8AAJbQi4YAAABBSURBVHicY2RgJAAUCMizDAUFjA8IKfj3Hz9geTAcFDDKEZBnZKJ5XAwGBYyP8Mr+/8/4h+ZxMRgUMMrglWVkBABQ5f5xNeLYWQAAAABJRU5ErkJggg==",
3378       "ps2n0g08.png", false, 32, 32, "f6470f9f6296c5109e2bd730fe203773");
3379   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAIAAACsiDHgAAAABGdBTUEAAYagMeiWXwAACHpzUExUc2l4LWN1YmUAEAAAAAAAAAD/AAAAAAAAADMA/wAAAAAAAABmAP8AAAAAAAAAmQD/AAAAAAAAAMwA/wAAAAAAAAD/AP8AAAAAADMAAAD/AAAAAAAzADMA/wAAAAAAMwBmAP8AAAAAADMAmQD/AAAAAAAzAMwA/wAAAAAAMwD/AP8AAAAAAGYAAAD/AAAAAABmADMA/wAAAAAAZgBmAP8AAAAAAGYAmQD/AAAAAABmAMwA/wAAAAAAZgD/AP8AAAAAAJkAAAD/AAAAAACZADMA/wAAAAAAmQBmAP8AAAAAAJkAmQD/AAAAAACZAMwA/wAAAAAAmQD/AP8AAAAAAMwAAAD/AAAAAADMADMA/wAAAAAAzABmAP8AAAAAAMwAmQD/AAAAAADMAMwA/wAAAAAAzAD/AP8AAAAAAP8AAAD/AAAAAAD/ADMA/wAAAAAA/wBmAP8AAAAAAP8AmQD/AAAAAAD/AMwA/wAAAAAA/wD/AP8AAAAzAAAAAAD/AAAAMwAAADMA/wAAADMAAABmAP8AAAAzAAAAmQD/AAAAMwAAAMwA/wAAADMAAAD/AP8AAAAzADMAAAD/AAAAMwAzADMA/wAAADMAMwBmAP8AAAAzADMAmQD/AAAAMwAzAMwA/wAAADMAMwD/AP8AAAAzAGYAAAD/AAAAMwBmADMA/wAAADMAZgBmAP8AAAAzAGYAmQD/AAAAMwBmAMwA/wAAADMAZgD/AP8AAAAzAJkAAAD/AAAAMwCZADMA/wAAADMAmQBmAP8AAAAzAJkAmQD/AAAAMwCZAMwA/wAAADMAmQD/AP8AAAAzAMwAAAD/AAAAMwDMADMA/wAAADMAzABmAP8AAAAzAMwAmQD/AAAAMwDMAMwA/wAAADMAzAD/AP8AAAAzAP8AAAD/AAAAMwD/ADMA/wAAADMA/wBmAP8AAAAzAP8AmQD/AAAAMwD/AMwA/wAAADMA/wD/AP8AAABmAAAAAAD/AAAAZgAAADMA/wAAAGYAAABmAP8AAABmAAAAmQD/AAAAZgAAAMwA/wAAAGYAAAD/AP8AAABmADMAAAD/AAAAZgAzADMA/wAAAGYAMwBmAP8AAABmADMAmQD/AAAAZgAzAMwA/wAAAGYAMwD/AP8AAABmAGYAAAD/AAAAZgBmADMA/wAAAGYAZgBmAP8AAABmAGYAmQD/AAAAZgBmAMwA/wAAAGYAZgD/AP8AAABmAJkAAAD/AAAAZgCZADMA/wAAAGYAmQBmAP8AAABmAJkAmQD/AAAAZgCZAMwA/wAAAGYAmQD/AP8AAABmAMwAAAD/AAAAZgDMADMA/wAAAGYAzABmAP8AAABmAMwAmQD/AAAAZgDMAMwA/wAAAGYAzAD/AP8AAABmAP8AAAD/AAAAZgD/ADMA/wAAAGYA/wBmAP8AAABmAP8AmQD/AAAAZgD/AMwA/wAAAGYA/wD/AP8AAACZAAAAAAD/AAAAmQAAADMA/wAAAJkAAABmAP8AAACZAAAAmQD/AAAAmQAAAMwA/wAAAJkAAAD/AP8AAACZADMAAAD/AAAAmQAzADMA/wAAAJkAMwBmAP8AAACZADMAmQD/AAAAmQAzAMwA/wAAAJkAMwD/AP8AAACZAGYAAAD/AAAAmQBmADMA/wAAAJkAZgBmAP8AAACZAGYAmQD/AAAAmQBmAMwA/wAAAJkAZgD/AP8AAACZAJkAAAD/AAAAmQCZADMA/wAAAJkAmQBmAP8AAACZAJkAmQD/AAAAmQCZAMwA/wAAAJkAmQD/AP8AAACZAMwAAAD/AAAAmQDMADMA/wAAAJkAzABmAP8AAACZAMwAmQD/AAAAmQDMAMwA/wAAAJkAzAD/AP8AAACZAP8AAAD/AAAAmQD/ADMA/wAAAJkA/wBmAP8AAACZAP8AmQD/AAAAmQD/AMwA/wAAAJkA/wD/AP8AAADMAAAAAAD/AAAAzAAAADMA/wAAAMwAAABmAP8AAADMAAAAmQD/AAAAzAAAAMwA/wAAAMwAAAD/AP8AAADMADMAAAD/AAAAzAAzADMA/wAAAMwAMwBmAP8AAADMADMAmQD/AAAAzAAzAMwA/wAAAMwAMwD/AP8AAADMAGYAAAD/AAAAzABmADMA/wAAAMwAZgBmAP8AAADMAGYAmQD/AAAAzABmAMwA/wAAAMwAZgD/AP8AAADMAJkAAAD/AAAAzACZADMA/wAAAMwAmQBmAP8AAADMAJkAmQD/AAAAzACZAMwA/wAAAMwAmQD/AP8AAADMAMwAAAD/AAAAzADMADMA/wAAAMwAzABmAP8AAADMAMwAmQD/AAAAzADMAMwA/wAAAMwAzAD/AP8AAADMAP8AAAD/AAAAzAD/ADMA/wAAAMwA/wBmAP8AAADMAP8AmQD/AAAAzAD/AMwA/wAAAMwA/wD/AP8AAAD/AAAAAAD/AAAA/wAAADMA/wAAAP8AAABmAP8AAAD/AAAAmQD/AAAA/wAAAMwA/wAAAP8AAAD/AP8AAAD/ADMAAAD/AAAA/wAzADMA/wAAAP8AMwBmAP8AAAD/ADMAmQD/AAAA/wAzAMwA/wAAAP8AMwD/AP8AAAD/AGYAAAD/AAAA/wBmADMA/wAAAP8AZgBmAP8AAAD/AGYAmQD/AAAA/wBmAMwA/wAAAP8AZgD/AP8AAAD/AJkAAAD/AAAA/wCZADMA/wAAAP8AmQBmAP8AAAD/AJkAmQD/AAAA/wCZAMwA/wAAAP8AmQD/AP8AAAD/AMwAAAD/AAAA/wDMADMA/wAAAP8AzABmAP8AAAD/AMwAmQD/AAAA/wDMAMwA/wAAAP8AzAD/AP8AAAD/AP8AAAD/AAAA/wD/ADMA/wAAAP8A/wBmAP8AAAD/AP8AmQD/AAAA/wD/AMwA/wAAAP8A/wD/AP8AAJbQi4YAAADlSURBVHic1ZbBCoMwEESn4EF/y363/a32lh4GA5KGJmaTzHoYhkXkPdagjxBCAD4v4JrvZHJzfhg9JzNfzuLzWne3AuvOdChwojOX8+3ycF3RAWDzsoFf6OzyAnl0prDAP3Sm5BkoQ+dcbAM16OwyAvXoTAGBu+jMqWegDZ3zSRuwQGcfLmCHzhwoYI0eBfjH7g8dALZn5w30RGfvJtAfvZvAKPQoYPcdGIvO+402MAOdvVlgHnqzwGz0KFB/BjTQOa/cgBI6e7GAHnqxgCp6FMifAW10zjMb8IDOngj4QU8EvKEzv+ZC/l4Hu8TsAAAAAElFTkSuQmCC",
3380       "ps2n2c16.png", false, 32, 32, "a3774d09367dd147a3539d2d2f6ca133");
3381   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAFS3GZcAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAANQTFRFAAD/injSVwAAAApJREFUeJxjYAAAAAIAAUivpHEAAAAASUVORK5CYII=",
3382       "s01i3p01.png", false, 1, 1, "c987217b78dd44056a9da58cf06b8c7a");
3383   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAANQTFRFAAD/injSVwAAAApJREFUeJxjYAAAAAIAAUivpHEAAAAASUVORK5CYII=",
3384       "s01n3p01.png", false, 1, 1, "c987217b78dd44056a9da58cf06b8c7a");
3385   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAQMAAAE/f6/xAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAANQTFRFAP//GVwvJQAAAAtJREFUeJxjYAABAAAGAAH+jGfIAAAAAElFTkSuQmCC",
3386       "s02i3p01.png", false, 2, 2, "e1b1f768e50f5269db92782b4ad62247");
3387   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAQMAAABIeJ9nAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAANQTFRFAP//GVwvJQAAAAxJREFUeJxjYGBgAAAABAAB9hc4VQAAAABJRU5ErkJggg==",
3388       "s02n3p01.png", false, 2, 2, "e1b1f768e50f5269db92782b4ad62247");
3389   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAMAAAADAQMAAAEb4RdqAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAZQTFRFAP8A/3cAseWlnwAAAAxJREFUeJxjYIADBwAATABB2snmHAAAAABJRU5ErkJggg==",
3390       "s03i3p01.png", false, 3, 3, "b05c579eb095ddac5d3b30e0329c33f4");
3391   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAMAAAADAQMAAABs5if8AAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAZQTFRFAP8A/3cAseWlnwAAAA5JREFUeJxjYGBwYGAAAADGAEE5MQxLAAAAAElFTkSuQmCC",
3392       "s03n3p01.png", false, 3, 3, "b05c579eb095ddac5d3b30e0329c33f4");
3393   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAQAAAAEAQMAAAHkODyrAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAZQTFRF/wB3//8AmvdDuQAAABRJREFUeJxjaGAAwQMMDgwTGD4AABmuBAG53zf2AAAAAElFTkSuQmCC",
3394       "s04i3p01.png", false, 4, 4, "c268bd54d984c22857d450e233766115");
3395   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAQAAAAEAQMAAACTPww9AAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAZQTFRF/wB3//8AmvdDuQAAAA9JREFUeJxj+MAwAQg/AAAMCAMBgre2CgAAAABJRU5ErkJggg==",
3396       "s04n3p01.png", false, 4, 4, "c268bd54d984c22857d450e233766115");
3397   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFAgMAAAGHBv7gAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAlQTFRFAP//dwD//wAAQaSqcwAAABlJREFUeJxjaGBoYFjAACI7gHQAEE9tACIATYMG43AkRkUAAAAASUVORK5CYII=",
3398       "s05i3p02.png", false, 5, 5, "fceb20e261cb29ebb6349bc6c2265beb");
3399   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFAgMAAADwAc52AAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAlQTFRFAP//dwD//wAAQaSqcwAAABRJREFUeJxjWNXAMLWBYSKYXNUAACoHBZCujPRKAAAAAElFTkSuQmCC",
3400       "s05n3p02.png", false, 5, 5, "fceb20e261cb29ebb6349bc6c2265beb");
3401   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGAgMAAAHqpTdNAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAlQTFRFAP8AAHf//wD/o0UOaAAAACJJREFUeJxjaGBoYJgAxA4MLQwrGDwYIhimJjBMSGBYtQAAWccHTMhl7SQAAAAASUVORK5CYII=",
3402       "s06i3p02.png", false, 6, 6, "b5c9900082b8119515e3b00634a379c5");
3403   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGAgMAAACdogfbAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAlQTFRFAP8AAHf//wD/o0UOaAAAABZJREFUeJxjWLWAYWoCwwQwAjJWLQAAOc8GXylw/coAAAAASUVORK5CYII=",
3404       "s06n3p02.png", false, 6, 6, "b5c9900082b8119515e3b00634a379c5");
3405   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHAgMAAAHOO4/WAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAxQTFRF/wB3AP93//8AAAD/G0OznAAAACVJREFUeJxjOMBwgOEBwweGDQyvGf4z/GFIAcI/DFdjGG7MAZIAweMMgVWC+YkAAAAASUVORK5CYII=",
3406       "s07i3p02.png", false, 7, 7, "cefe38d2a35e41b73b6270a398c283e8");
3407   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHAgMAAAC5PL9AAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAxQTFRF/wB3AP93//8AAAD/G0OznAAAABpJREFUeJxj+P+H4WoMw605DDfmgEgg+/8fAHF5CrkeXW0HAAAAAElFTkSuQmCC",
3408       "s07n3p02.png", false, 7, 7, "cefe38d2a35e41b73b6270a398c283e8");
3409   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAgMAAAHOZmaOAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAxQTFRFAP//dwD/d/8A/wAAqrpZHAAAACVJREFUeJxjYAACASB+wGDHoAWk9zDMYVjBoLWCQbeCQf8HUAAAUNcF93DTSq8AAAAASUVORK5CYII=",
3410       "s08i3p02.png", false, 8, 8, "3f0fc2c825d2fad899359508e7f645e1");
3411   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAgMAAAC5YVYYAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAxQTFRFAP//dwD/d/8A/wAAqrpZHAAAABtJREFUeJxjYGBg0FrBoP+DQbcChIAMIJeBAQA9VgU9+UwQEwAAAABJRU5ErkJggg==",
3412       "s08n3p02.png", false, 8, 8, "3f0fc2c825d2fad899359508e7f645e1");
3413   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJAgMAAAHq+N4VAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAxQTFRFAP8AAHf//wD//3cA/1YAZAAAACNJREFUeJxjYEACC4BYC4wYGF4zXAdiBgb7/wwMltEQDGQDAHX/B0YWjJcDAAAAAElFTkSuQmCC",
3414       "s09i3p02.png", false, 9, 9, "5c55b2480d623eae3a3aaac444eb9542");
3415   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJAgMAAACd/+6DAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAAAxQTFRFAP8AAHf//wD//3cA/1YAZAAAAB9JREFUeJxjYAAC+/8MDFarGRgso4FYGkKD+CBxIAAAaWUFw2pDfyMAAAAASUVORK5CYII=",
3416       "s09n3p02.png", false, 9, 9, "5c55b2480d623eae3a3aaac444eb9542");
3417   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAAH2U1dRAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAANhJREFUeJx9kL0OgjAURj9FfuJTuBjXhqkkDvBGujo1casOLOyEgZmpM4kk8Fi29FYpMTbNl8O59+Y2AByC48nw5Ehe4Pr25orpfEeQ6LhPNgLgdmpQm2iWsdVxqA3V9lOyWKajTCEwWpDpx8TO6Oz3zMIoHYgtlWDORlWFqqDKgiAk6OBM6XoqgsgBPj0mC4QWcgUHJZW+QD1F56Yighx0ro82Ow5z4tEyDJ6ocfQFMuz8ER1/BaLs4HforcN6hMRF18KlMIyluP4QbCX0qz0hsN6yWjv/iTeEUtKElO3EIwAAAABJRU5ErkJggg==",
3418       "s32i3p04.png", false, 32, 32, "bbe63d9433641df3fcd2c745fed89a93");
3419   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAHxJREFUeJyV0b0NgCAQBeBXAIlxCRt6WrbyNqB3CSsnYTAPTYzvSIhSXMhHcn8A7ch25FiviA40wDEkVAZ4hh2RQXMa6JLmxZaNPwEdBJO0aB9u3NhzraJvBKuCfwNmXQVBW9YQ5AskC1xW2n4ZMDEU2FlCNrOYae+Pt3ACA2HDSOt6Ji4AAAAASUVORK5CYII=",
3420       "s32n3p04.png", false, 32, 32, "bbe63d9433641df3fcd2c745fed89a93");
3421   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACEAAAAhBAMAAAHSze/KAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAPZJREFUeJxdjzFywjAQRT/JMCjEBdzAkxN4RhdIwQHcuKeiplNLqZKWzrUr+jQ+gA6Vv6sVlnkey5K+Vm8NxBvmNMP7DpHzxLmL/HCHG+Cy8xI6l+M0y2GGYBw1lN0kq5gTOaThawlM434SRrT4UVqEsAvCFSNKmjNejpCz3RWTAUs/WsldVOM0Wug/vfISsPcmaWtFxBqrAkqVAesJ+jOkKQ0E/bMYXalhl1bUWRUbykVooPwtPHG5nPkunPG441Fzx8BnOyz0OBEdjF8ciQ7GAfjm9WsX5W+uWqMMK3r0tUZE5qo8m0OtEd48qlq5vtRXm8Td/wMULdZI1p9klQAAAABJRU5ErkJggg==",
3422       "s33i3p04.png", false, 33, 33, "20708bc9a6ffa8d8ca6e004e1e9aa3ae");
3423   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACEAAAAhBAMAAAClyt9cAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAL5JREFUeJxdzy0SwyAQhuGv0+n0V6Q36HCCzHCBih4gBh8VXVeLjIyNi0bV13CAHKrLDi27vAwrEMADpMaS5wN8Sm+EEHAKpQXD0NMu9bAWWytqMU+YZRMMXWxENzhaO1fqsK5rTONXxIPikbvjRfHIPXGleOQaNlWuM1GUa6H/VC46qV26ForEKRLnVB06SaJwiZKUUNn1D/vsEqZNI0mjP3h4SUrR60G3aBOzalcL5TqyTbmMqVzJqV0R5PoCM2LWk+YxJesAAAAASUVORK5CYII=",
3424       "s33n3p04.png", false, 33, 33, "20708bc9a6ffa8d8ca6e004e1e9aa3ae");
3425   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACIAAAAiBAMAAAG/biZnAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAANJJREFUeJx9jr0KgzAURr9q/elbdJGu4mTAQR+pa6eAW+yQxV06ODs5CxX0sWrURHstDcnH4eTe3ABxBz6d5+74b8S7zcck72D7KvMx4XPaHfC4vVCpeP0OS0W1hAg9EQ0imqZhWElEm/OMm28tTdwQQkPzOrVl1pYpWplpcjQ1ME6aulKTawhbXUnI0dRsZG5hyJVHUr9bX5Hp8tl7UbOgXxJFHaL/NhUCYsBwJl0soO9QA5ddSc00vD90/TOgprpQA9rFXWpQMxAzLzIdh/+g/wDxGv/uWt+IKQAAAABJRU5ErkJggg==",
3426       "s34i3p04.png", false, 34, 34, "0912e0f97224057b298f163739d1365f");
3427   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACIAAAAiBAMAAADIaRbxAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAG1JREFUeJyVz7ENgCAQBdBfIIlb2NDbMpYb0LMEFZMwGKcWJv9HwSsu5CX8uwPOOnKNod0dKtbhSHY0EiwkBYHEglk0OW4yPfwXqHhOTraPG234vCcFYykqKwtUeFZS8Sx2NUjqhFz1LVl+vUgHrMXtiDoroU4AAAAASUVORK5CYII=",
3428       "s34n3p04.png", false, 34, 34, "0912e0f97224057b298f163739d1365f");
3429   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACMAAAAjBAMAAAGb8J78AAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAQRJREFUeJxlkD2uglAUhMf4A1GL93ZAWIHJ2YCFC7Cxt7Kmo7WktLWjprJ/DQu4i3pzzuUAF4fwk5k7+SYAzRN96CFyQsPvEIC80ZcIDf04iYZ5HmOeZaQOYzoxDRY05og7MCePDtQ5Al2770woUEahrrPahBaeluWUqiqmMWqBMS2GtEYGHR4XdK2flLVI3OO0AqE/hrjXuRWb3sVIEfHuRLMifxEGbsauFdl/Dk1NvTsthXeDdytUMP3N9MHjcec90x3vF96JXrjx2t5muuJC2cN1xi9lD9cPcCBjQeSGJXEpEhMYdU1hm5E4wlZGTGAHFj9IYTsd8A1MiVujzokXHXH+B9CK7qGbaRQOAAAAAElFTkSuQmCC",
3430       "s35i3p04.png", false, 35, 35, "b46d9ba87963f526624a6d485ff6465e");
3431   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACMAAAAjBAMAAADs965qAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAMdJREFUeJxl0SEOg0AQheHXtJSmmPYGhBOQcIEKDoDBo9C42spKLA6Nqq/hAHuoPqZhM7P7E0asmOyXBbbeqpec4Kv6YFkWXBfVjL7v+Ks6VBWOla7ENGIyjSi4vdDlaPklraqBc27dhm9FzWTsPfBkMvYG3JmMvZv4QmNGlTXOvFdo5FFkDCoD4N8YRqPhsSbgsdXyTt7oeak3et5BjIZ3EaPhZVwv76h4kuWdN3JMjIwjImMOa0zEaY3Ocb021tsVrJE+pMMPA+LuR86i5UgAAAAASUVORK5CYII=",
3432       "s35n3p04.png", false, 35, 35, "b46d9ba87963f526624a6d485ff6465e");
3433   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACQAAAAkBAMAAAFkKbU9AAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAANlJREFUeJyNkb0KgzAURj/b+tO36CJdxUnBob5Ru3YKuGkHF3dxcHZyDlTQx2piTaJJC4bk43juvUEUiCgIO6/V8d6IVptMSUZx9HhmU0IwJwWe1+aOes7mV9ZzHr6JJfPAzcORbRCMC+Whcq5044bIgQoKXEGhcDn4svoqZRt9mQqyBXWQrpR9lSBHElRf9ZdgLdRVkCSqnaraqnozifXN61G0sT8siaINMGiqhq8rxDjpg7Fv3GUoOPFF72LvoF+/etipav4DtgosYSptELsHdXX2qaZa/jk/GoQXLvsYf8IAAAAASUVORK5CYII=",
3434       "s36i3p04.png", false, 36, 36, "65e57e33b4763a3b0c3f0fa92295406d");
3435   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACQAAAAkBAMAAAATLoWrAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAHdJREFUeJxjYACBwu5llqpHoCQDFiEgxcCCLmTAcARdiIEVXWgBgyq6ENB0DCEsxlsqYDpClSwhBixCbBjGNwDdhe4ILE5F4lBXCBToqEILgEKMqEIMnKoHGNCEgCQWoULCQgYYNjJgsZGBWBvJE8L0EBZvgwMHAABJBMjTkay+AAAAAElFTkSuQmCC",
3436       "s36n3p04.png", false, 36, 36, "65e57e33b4763a3b0c3f0fa92295406d");
3437   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACUAAAAlBAMAAAFAtw2mAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAP5JREFUeJxlkDsSgjAQhv8RHfFR6A0cTsBMLmDhAWjsrajpaFNS0tqlprK3yQFyKDcb8jD5GJLMssu3G2CS0EZDiBYTnY0Bat59DHxuBYG6nihgLBAcmSywm+Sclr9qjkvOKSOIESmxqOPCKNzQOG4Yx/3IDFAICU2TJDAglhUVEzYhYaA/2JFco4tacyEq4YhWGH02brigp0pfG0QQntiQu5S11vUNdzk8dmgx1FaxV1+rTWza19bWS3xTPuj7F70pL7xnvP+Z8aRn90zp8CB4CdxxJXgJXIATiXIvtVJ4C8hb0OVK5ppzyUa1FE5rLb04FN4OuZdG367zplJ6fx0nFJojsT+zAAAAAElFTkSuQmCC",
3438       "s37i3p04.png", false, 37, 37, "f21eff5c07a755577fea69c01459c65f");
3439   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACUAAAAlBAMAAAA3sD0wAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAMVJREFUeJxl0S0Og0AQhuEvoU36J+AGDSfYhAsgegAMHoWuq62sxOJWr6rHcAAO1dkppbMzD9kRmxB4M0D0kp58hUl6I4SAU5A8+r6jI3WoKmRVwmEcMKYGlPSJMnFFS8++lRosyzLH8TfjRnhsajwIj80dBeGxybnV9J4pUPV6+j/TS3e2V3M69ttrUK/RpKmiV6QylcoKLVerXXMnjd4NGrxqjbW212W2F0fbC9vbwPbOF91Lq96t+xXw26+MjUfFHuh8APqFElFWDb0cAAAAAElFTkSuQmCC",
3440       "s37n3p04.png", false, 37, 37, "f21eff5c07a755577fea69c01459c65f");
3441   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACYAAAAmBAMAAAEtFMQLAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAANpJREFUeJylkT8LgkAchp/+WEFfokVapamDhvxGtTYduGmDi7s0NDc1Cwn6sTpF7w7PQEju9/L48N6pCMcCqeZuzeYjOfZT0I6sT1HNYtNkVHcpi5aB2/5xIW/z8TtzKzsDcbCOD5VaEknVY3yw7NrYaoABGucVxmJbmL2zUK0X7zTU6Gl8YWxqupnGlUGsbjYNUzR6ZzSGjFisbjjWbQrtdU2ewi/7JHkGlEOX4zsOwdLZK3z3PNexEjunp17FeYZ995dr/uR24JpvYoIb3euVlyl7x3pCnZd8AfUFRB95/EUWAAAAAElFTkSuQmCC",
3442       "s38i3p04.png", false, 38, 38, "f6237240a70b5844def0406dc8f63bbd");
3443   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACYAAAAmBAMAAABaE/SdAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAGpJREFUeJxjYACBwu5llqpHYCQDNjEgzcCCIWbAcARDjIEVQ2wBgyqGGNAKTDFsdlgqYHGLKrliDNjE2DDtaAC6D8Mt2NyMzBs4MaDL0MUMgGLcaGLAuClgQBcDkmSLYTEPm72DyS3gsAIA8mkrg86sROEAAAAASUVORK5CYII=",
3444       "s38n3p04.png", false, 38, 38, "f6237240a70b5844def0406dc8f63bbd");
3445   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACcAAAAnBAMAAAEJinyQAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAARlJREFUeJxtkDFygzAQRZ/HkwSTFM4NGE7AjC6QIgdw457KtTtaSpVu3VFTuafhADpUVhISCOUxwPC1u/8voHtmM6NUg9ZgDBSimUSbaZRAUWgRjAXlFPmWavdaavypdopKlb6wStM4xTX1PeNQjh4q6gW67qPzMBAL6npTEGA5HcYhFFQ1a8E9FIyU2O20Dy0NSyPqqDzNmqHCzF8uuqwf49ylP06AdYKKE2LGym8eJsQ4OusvR8KEoyJMkCzE/s1ChAnoTYIBx5Tw4nZr5U5oeT547nhwlevtmnDhV3CPlR++BfdYOcOnuGXukih3zxH3nMvOeOOeOh/OmfE0Zc7tuzXfuT9O1nzv7n/lf+b7tQ8uQOpurXn9AQyWNfYM/uLgAAAAAElFTkSuQmCC",
3446       "s39i3p04.png", false, 39, 39, "ceb3b33633c181e13ecee80b153fb602");
3447   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACcAAAAnBAMAAAB+jUwGAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAANVJREFUeJxt0iEOg0AQheFHSJuUGnqDhhOQcIEKDoDBo9A4LBKJxaFX4TEcgEN1ZklDZ2Z/YMQa+DIA3Cga/Bk20QrnHBInWtC2DT2iBkWBuJDlmCfMqgkZvSeTvVHTdatFFY7j2Hn8taOk/Lj6oKf8uOrwovy4Sr3b2p9k1faFvtPa6TBgN+UGftptZLdViv1nL0P2PmSX7ihV7JEXPhj2ttGxYidMV+7mznRlz2OmK/v0YDo0m25o+/kXGjfoDtED9g565dFv7WLlni/tDMeq7AxPli8bpjUVK/+f5gAAAABJRU5ErkJggg==",
3448       "s39n3p04.png", false, 39, 39, "ceb3b33633c181e13ecee80b153fb602");
3449   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACgAAAAoBAMAAAEJ15XIAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAANpJREFUeJytjrEKgzAURa/FWmv7EV2kq2RS6FD/qK5OATd1cHEXB2cn50IL+lnVUBMxr4VCQ97N4ZC8POT+HcexclEQp/3g8GVBnHy4JANgT5kM66zjcx1jIxKLrFfpTFndROLN6aZPmdjgTKLjSUwXyL6gt+MSexCWAei2YVeKjXaBpUQotAoKAWPGTtmu/B1hzViEoPCqEK1EQ2GocGyWNXCfUdYEi0RW7QmJQJfcIiSaALqcltaTuvlJEiP9VZ7GAa21nCYBIUFIHHQJg3huUj3NiGvSHb9pXgoWak5w83t4AAAAAElFTkSuQmCC",
3450       "s40i3p04.png", false, 40, 40, "140f0d2eb778dad4a1871c17767e2d48");
3451   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACgAAAAoBAMAAAB+0KVeAAAABGdBTUEAAYagMeiWXwAAAANzQklUBAQEd/i1owAAACdQTFRFAAAA/wB3AP//AP8AdwD/AHf/d/8A/wD//wAAAP93//8A/3cAAAD/9b8GOwAAAHVJREFUeJzN0LENgDAMRNFDiiwhlqBhiGxFNkifJagyBwWDEagQ/kXoSOHiyVZOp1K1HKnU+Jhi3BBHQCFGjxnRAGVRHms3Xq8LC51/Qurz99iacDg3tDcqpCyHbRLipgBXQk0ed8FHGggpUuCcuOnDYyF3dSfnZ1dwSF0UKQAAAABJRU5ErkJggg==",
3452       "s40n3p04.png", false, 40, 40, "140f0d2eb778dad4a1871c17767e2d48");
3453   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAAJ0Uk5TAA/mLNCpAAAAAmJLR0QAAKqNIzIAAAFISURBVCiRddExT8JAFMBxPoJHWUxcriQuJiaFqpNLWxkdLOVCHJjunSau9GByohwTk8Il+hkcHd0kLrIymLCaOLBq0epdbRRIeNv9pnfvn/temdw6eJktQXJPK7cL8BbRklmsjzNInsJquWRjc/8mhc9B6JZt13aLe6z9rGDEm2W7VvU8d5vzcwUTEXqMcxocMd48VfAqBM8mDI4VvENr2M3eXkMDE1Km4iO7r+BDgxaKkXGnAURv0JZd6uON/FRBDK1eBHIQOAgX9GJzOBO8psA0nIN0UyBdTuS1j228qeELKh0NJ9hCWxoSCCKmwMljtJv+FgJOiLwqGRg1foEyDVbBQv0UIspqRHawgnEKMQBoMNBOdsJHBb0ORvlxBkkERDQtdPh35FiDU5j9ZxgRQf3LxS5DQetL5eaCPiynnFystE2m6+r/AOOSVs9bKk33AAAAAElFTkSuQmCC",
3454       "tbbn0g04.png", false, 32, 32, "d9b53613bd731e66dcfd5be93186c100");
3455   testPngSuiteImage("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",
3456       "tbbn2c16.png", false, 32, 32, "75954a76132c3971509841e973f029cd");
3457   testPngSuiteImage("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",
3458       "tbbn3p08.png", false, 32, 32, "d1f6636d81c74f163bfff1405bf406cf");
3459   testPngSuiteImage("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",
3460       "tbgn2c16.png", false, 32, 32, "75954a76132c3971509841e973f029cd");
3461   testPngSuiteImage("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",
3462       "tbgn3p08.png", false, 32, 32, "d1f6636d81c74f163bfff1405bf406cf");
3463   testPngSuiteImage("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",
3464       "tbrn2c08.png", false, 32, 32, "75954a76132c3971509841e973f029cd");
3465   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAAAAAAGgflrAAAABGdBTUEAAYagMeiWXwAAAAJ0Uk5T///Itd/HAAAAAmJLR0T//xSrMc0AAAS8SURBVEiJY/hPIWCgqQGPH588+fEjWQa8eLF1a11damrUTjf9hB8LBR8JEG3Au3f793d2pqcnTvDZZSaiFaD+Unmr+hy9VwGeE72vbP/zB48Bnz4dOTJ1alFRzrzgSbYLdLP0t2s3q2VqLbc5rnRIglFqq/pLA46ctAULzp//8QPNgO/fT52aNausrLg4bZXHY0NO/SyjbSYXbALsZM1bDAOtZ7tWGFerbdNl1noZ1Z6XV1xcVjZ79pEj797BDThzpr6+rKwUCPzEzc3NmM3m2sSE2qTIBag5zne+6L7dNdAxy07O/IKaWc68UijIypo1C27AnTutrR0dLS3V1ckcLp7u8omvyqLLwaCINeFw2N4gEb9Yb1HfVUk3IaIFBTExQUF798INePWqpaWxsd2zr6+zs76+Ei8oK0tODgkJCPDxefYMbsCPH02FGe5JVypsJtyYPLm/v7m5GgNUAUFlZVZWeDhIs6dnZCRKLHR1ZV4pmdXXPEF20qSpU6dPnzKlvb0GDRQWRnMb3RQpkSjTXeO2p6kJxYBJkzLX5fv2b+zPnThxypTp02fOnD175szu7vr6OiCorS0vT0oKuaR6XbxY4ASPEPd1fek1a1AMmDIl/WMWQ6t4/8YJ8ZMnTy6skqxPnf5r3rw5c/r66uqysqKiwtfrPJOeLpTCc4H9Obe6CvO1aygGLFmSbpoiW3oc6IbCSZNaGPK2JbflGc2dO3/+ggVVVVFRkZF2grIBYod4FaVieUVFCmz//v6NYsC2bWn88empD7tS+ionzKpTL4uLksr7M2fOvHnz55eUREYGfVWYLT2dv8vyioeHlIz+/6IitKR8/HhKXYZNMGf16n6pqkulHaWGkc0FlbNnz507b15eXmSklYxsgLCotrzLEiUuIXdBs7n6aAbcuJEckWHjkZ8T3fsmOr0kqmRWxJv8R7NmgYxITw+fpBwDtP+2+XqxY0KafI5i9sePoxnw6lXi8dSHfsGx9o19SREZnEXXIkILFGbMmDVrzpzERE9X2QBRF8Vz0p/5lHl8eXyVjn/5gmbAnz8JZ5PbwvdHHCxcUcIc9rtwRcjZkhZQdM6aFRVlKSLjzp9hHCS9j1eD10LwUmAwluyc9yhhSsKUUNPMipobgbcLqoLnFzeDktS0aeHh2q8lW7m/OizQ1hY3EpnM49v+HIsBPT3x8ulLA5dlPCr7GvEmb1tQUeHryZOnTu3vDwtTihd14Utxdzd1F5ovxCMkd/QoFgN+/Vqckfw8WTW9KbMnrSLnU+Dt0uqJEydP7uwMDZUxFuIRnGVxVjReJFL++7a0//+xGAACFy7k5qampj3OuJytF7CuVKm/f+LExsbQUEV1fl2eBgEBgdWqnec5///HacD//2/etLWlVaXzZWYGiBcr9Pb291dVhYToN/KJcNdzJxqeeDDh/3+8BoDiY9WqdNP0pX4vi2d3d/f2lpQEB9vaSisLO/lYvNNAV42jWL9yuKg14mD9jY6O7u7c3KAgf39z8/LyX7+wqcVRL7x/v2BBc3NbW0dHenpgYEDAggV//2JXibNm+vfvwIHW1ra2xMSgoO3bcakiULXduzdhQmrqmTP41BCoXL9+ffwYvwqKa2cA4MyW1TM3HhMAAAAASUVORK5CYII=",
3466       "tbwn0g16.png", false, 32, 32, "56ea136a6e299452015ac02a7837e365");
3467   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYagMeiWXwAAAt9QTFRF////gFZWtbW4qEJCn5+fsSAgixUVnZ2dGxtZm5ubAACEmZmZj6ePl5eXlZWVk5OTKSlWkZGRAACbj4+Pi5WLLi6njY2NgAAAi4uLuQAAiYmJDAzVeHV1h4eHAACyhYWFpQAA3gAAgYGBf39/AACefX19AADJe3t7eXl5NzdWd3d3dXV1c3NzSKlIjgAAAgJkAABiVolWKCh8U4tTiYmPZ2dnZWVlXW1dE+UThiYmby0tRJFEYWFhO507RIlEPZM9AACkAPMAAPEAWVlZV1dXVVVVU1NTNIU0UVFRJJckT09POjpBEBC6sg8PAMcAAMUA/Pz8AMMABASXAMEALXct+vr6AL8AAABoAL0A2tTUEBB7Ca0J+Pj4ALkAALcAnJyh9vb2DKEMALMAALEAEJEQAKsA8vLyAKkAAKcA7u7u7OzsAJcA6urqAABrAI0AAIsAAIkAAIcAMTExGRkqBwdAEhKuCQnu09bTzMzMkwAAoyoqxsbGxMTEzAAA0woKgWtreD4+AwNtAACfCgpWRkZIQUFNc11dUQcHqKio7e3voKCgnp6enJycAAC5mpqasgAAmJiY6wAAlpaWngAAlJSUExMckpKSkJCQjo6OAACRioqKiIiIdqJ2hYiFhoaGhISEeA8PgoKCfoJ+fn5+fHx8enp6SsBKdnZ2dHR0cnJycHBwmAAAbm5uanBqemZmampqhAAARKJES5ZLYWRhYmJiAPQAOJg4XFxcWlpaAOYAAgJdQnhCVlZWAADwLpQuR2hHMTFgANgAUlJSUFBQAM4AIZghFBRtAMgATExM/f39AMYAAACdb2tr6g4OSEhIALwANGY0AgL1U1NgALAAAK4AtwAAAKQA7+/vAKIAj09PlTQ0AJgAAJYAAJIA5+fnAIwA4+PjAIAAkgYGAQFvZFZZAABkTk5rz8/P3d3gAAB7ycnJFhZBISFZV1dZRER4v7+/693dLS1UCgpgAAD/v319DyW3rQAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAACiklEQVQ4jWNgoDJ48CoNj+w9psVmTyyZv3zAKpv5Xsq0rYFNb4P4htVVXyIDUGXTavhWnmmwrJxcKb7Aqr29fcOjdV3PY2CyMa/6luu0WT6arNBfWyupwGa5QHy13pM1Oss5azLBCiqUl2tr35Lsv+p76yarouLEiYq1kuJntIFgfR9YwQv52fPVGX1Zb8poaWnVM9edPVtXxQhkrtp+6D1YQc58pbkzpJQ1UMHyLa6HT9yDuGGR5zVbEX7h+eowsHSpxnqXwyfOOUNdOSvplOOyaXy8U2SXQMHK7UZBUQItC6EKpkVHbLUQnMLLzcktobx4sarWlks+ajPDwwU6oAqmJCbt3DqHX2SjLk93z4zF63e8ld7btKvEgKMcqqDjaOrxrcum6Z5P38fO0rV0h7PoZ7VdxVObNWHBybTvxpWdTiIbj9/e1tPNssL52cW9jd7nXgushAVltXty3hHHTbZ+t+052bvXAA1weNMa1TQzHqYgcnfyw1inFNtT2fZ9nOymb8v2Nh4IUnn5qRqmIGf3lcLEgxmegXfsJ/T12Lz73Mvx+mVuLkcCTEHA/vQ7IcH+d4PvbuLl7tshepHrY7H+Y6FniNhee+3a/sSD+WF5m/h4J7mU7g1vLToml2uCUCB24/IFu+PZ5+9b8/MJ7/Hp1W854HC6uRqhIJTHfbNZ9JXYfGNBfinX0tOfDgTJcTChJKnna8z2JcUVGAoLKrlGcelzzTz2HC1JZs0zv5xUYCwmvNT1Y+NTA6MXDOggoOPo5UJDCbEVbt7FJe86MeSBoHxbyKLZEmsOeRVphWKTZ2C43jV/3mxTj8NdJ7HLA8F7+Xk2h5hwSgPBi+lmFfjkGRgSHuCXxwQADa7/kZ2V28AAAAAASUVORK5CYII=",
3468       "tbwn3p08.png", false, 32, 32, "d1f6636d81c74f163bfff1405bf406cf");
3469   testPngSuiteImage("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",
3470       "tbyn3p08.png", false, 32, 32, "d1f6636d81c74f163bfff1405bf406cf");
3471   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAgMAAAAOFJJnAAAADFBMVEUAAP8AAP8AAP8AAP+1n0POAAAAA3RSTlMAVaoLuSc5AAAAFElEQVR4XmNkAIJQIB4sjFWDiwEAKxcVYRYzLkEAAAAASUVORK5CYII=",
3472       "tm3n3p02.png", false, 32, 32, "82e044043a1f2c91533b2fea5e271daa");
3473   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAAABGdBTUEAAYagMeiWXwAAAoZJREFUOI1jqCcAGEhU8PjkRzwKXmytS41yS1z4EKuCd/s70xN9zbQ0VDT0AyZe+YOq4NORqUU5wXZ6Bjrq2rbKEtIaBjkLzv+AKfh+alZZcZqnoYGxqY2dhaGNq7G6rnZUXnHZ7CPvwArO1JeVlvqZm5nbhKYEOLl4uDrZWajllAJB1iywgjutHS3VyS7uSWXl5eVFieFBft5+yUBmQUzQXrCCVy2N7X2d9ZWooCw5JMDnGVjBj6aMpIoJk/ubq2GgqqoyKzzAxzMS6ouuzJK+/klTp09pr4GCwmhjEQldtyaogkmZ+f39E6dMnzl7Znd9XV1teVKIqrggD4/+GqiCKemZLf0TJk+uqp8+b05fXVZUuK60EC8Ht8o1qIIl6Sml/f2TmvOS8+bOX1AVFWknK8YrxSti9xuqYFtafGpX34S6sqi8OfPml0QGK0jzW3lIGRTBgvp4SkZwdV9VaWlkwey58/IirWSFtV2UhATnwhTcSM7wyOmNLimJyJ81e256uLK0gLm4EJ/YcZiCV4mpfrGNSRlFEQUzZs1J9JQVVZLh4+FR/gJT8CchOTyisDi8MKRk+sxZUZYy/MYyvLxCgYjozktICM2sCSwILp46fVq4jiSPg7a4CE87QkFPfHpgRllEXlDh5Kn9YUqifO6mQkJCRxEKfi1OTk7PTMsJLJ04uTNURkjQUlREYRtKkruQm5qWkR1Q2j+xMVSRn0dAQPUcWpp805aWnhlQ3NtfFaLPx81t+AAj0f5ZlZ7uX9zdWxJsKy3s8xZbsr9SFFHf0Z0b5G9e/gt7vni/oLmtIz0wYMFfbPkCBP4daG1LDNqOLISe9e5NSD1Tj09B/dfH9fgVYAAA90bMUdlj1V0AAAAASUVORK5CYII=",
3474       "tp0n0g08.png", false, 32, 32, "38deadbdfb7b0ff5a2b4cad35e866b39");
3475   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAYagMeiWXwAABfFJREFUSInNlgtMk1cUx/8fFBrMhxpQlAYMhpEgtTAjiWADqBgQxFAppZRBIiLg6GDI04mFoZRXKZT3+yFBnQynzgFzG8NlIoMwwWUhZgFMNHNOEQaDaXxtpyVbRiyImSY7ab40X3vP79xzz/mfi4w3bPgfAW7fvt3X1zc1NfWaAXfv3m1vb09PT4+MjIwLCEh3dDzl6dmr0dwfHf1PgImJie7u7ry8vOjoaHlY2BFX13wzMzWgBFKBLKCGYZoFgm6FYnRo6OnTp0sFTE9PX7lypby8PCEh4X25PHXnzpx168oZphEoBj4EElg2XCAQL18uAmQ6Xomx8ZGoqKampsHBwUePHukHPHz4sL+/v6amJiUlJTEx8WhYWI6jYymX2wCcAc4DfcAgcAloZpgCS0ulg0OGuXkmUAEUAXKxOC4ujhbS8traWgqREjAPMDAwQE/6OVlnFU5OnwOfAR3AWZYt27q1RCS6ZGs7bGBwC5gEfgF+0iG/ABQMQ3tN/pfFxMRQrPMAIyMjSqUyNzc3KysrLS1NGRjYaW5+xtpa7e9/ODk59W/LlMtbt28ftrEZX7nyV5YdMjM7aW+fFhz8zx/i4+NDQ0MDAgK6urrmAe7du0euMzMzlbnKwsJCOlt6+cGrGO0+IiIiMDBQJBL5+fnduXNnHkB7OFkZdpV2nJMc1xZXVZmqtLS0qKjo+PHjaQvbEZ2Rd8qJVCqdc+3j4yOTyfRUUX5+PnORwVVgGrIOWUlJCdVSZWVlWVlZTk7O0QXs0KFDISH77O2VHE4pyx62tw/28vI9duyYHgB5ZD9m0QXMwGbUpri4mFwToLq6mgqDniqViv6WrjOFQkEZ379/v1i8z8zsa2CAyhV4F4h2cJC0tbXpAZA7ixMW2tK5pWWkNKdQltSVaq8GL6/TXoUNhQ0NDXV1dXRCBKCchISESKUha9d+D/wGNBkY7GMYNyDc2lo2PDysB9DS0rK+aj1age+0AGG/kPbk2+aLr7S94FTjVF9f39jYSA1FeSfvlOhNm04AfwJXDQ3fsbR8i2VXs6xEKBQ/efJED6Cjo4NfxEczVT5wH9wH3LzyPM/Tntoeq4ZLuQuFT5sgRlJSEnkXiaKNjGYpfEPDeBcXr127dllYuPL5EpIAPZ1M1tvb65ztjAsAKc4PwO/wq/UTNgjRC1TBrcyNToI2QQxqWgLw+Wd14Z+ys5N5evpbWKQDjQxTWFd3Qj/gxo0b7gp3LSANoD6ewhrVGmGdUFtXlXArdaPmnGOQ/EmlMhOTCQqfw5Fv3hzC5WoAkpWjpqZhFKh+APWad5K3Nj9KmFSZYAQ4DdsqW3yrVRyPEo+qqipiUKLCw8N37MjQhX+JxwuzsPDRBSWnj5VV0MzMjH4ASa7oPZFW28ohSBXgG6AHTCmj/aLB7uLdcyVLDDphPr8F+APIdnISW1q+bWAQASQCtXv2xGfMt3lyfTDxIGhhC9wj3VedXIUfARXQDRTCV+M713cVFRXUtDxeOzAGHPTw2M3n81k2FrhIO8jOLlkMUFBQYNRgROrsHOW8TbkN/drsa8u0AD6FPtQWxCD9CAoKWrGik/JjaBjl7e3t5HQA2uKrNzEJ7unpWQzw+PFjzXmNs9I5/EB4REyE8TljfKIbAiqI1WLqbWKQDkokkmXLPiKPXG6Es3Moh1MLXODx9rS3f5nxgukZmUNDQ7GxsTSBBUUCfKqbCXmQqCQUOzFIcQmwejUVZRbDRDIMTc9iK6u4a9eGXnSlH0A2Pj6enZ0dHB+Mc7rc5kKcJ1ar1cSgNiZN3rjRx8CAyoaSE7FhQ9LNmz/r9bMgIENXVK2trVrxoIGZDWmOlMSOGNTGYrHYzc2Nx7M1NfX09k548GByISeLAebs+vB1l1oXqlpFpoLmHTEoezSw/P39t2zZQoJKx7a4h5ffiyYnJ0ngaPJQ0ohBbbx3716aLfTy2bNnL12+pJvd8+fPL1++TEObGNTGtIPOzs6lLFwqYM7GxsY0Gg1V19wV5PUDyGZnZ+mG+kpL3vjt+i9V6lTMZgDHHwAAAABJRU5ErkJggg==",
3476       "tp0n2c08.png", false, 32, 32, "c37c05b6929096c1736f91dccbe93d15");
3477   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYagMeiWXwAAAt9QTFRFFBRtgFZWtbW4qEJCn5+fsSAgixUVnZ2dGxtZm5ubAACEmZmZj6ePl5eXlZWVk5OTKSlWkZGRAACbj4+Pi5WLLi6njY2NgAAAi4uLuQAAiYmJDAzVeHV1h4eHAACyhYWFpQAA3gAAgYGBf39/AACefX19AADJe3t7eXl5NzdWd3d3dXV1c3NzSKlIjgAAAgJkAABiVolWKCh8U4tTiYmPZ2dnZWVlXW1dE+UThiYmby0tRJFEYWFhO507RIlEPZM9AACkAPMAAPEAWVlZV1dXVVVVU1NTNIU0UVFRJJckT09POjpBEBC6sg8PAMcAAMUA/Pz8AMMABASXAMEALXct+vr6AL8AAABoAL0A2tTUEBB7Ca0J+Pj4ALkAALcAnJyh9vb2DKEMALMAALEAEJEQAKsA8vLyAKkAAKcA7u7u7OzsAJcA6urqAABrAI0AAIsAAIkAAIcAMTExGRkqBwdAEhKuCQnu09bTzMzMkwAAoyoqxsbGxMTEzAAA0woKgWtreD4+AwNtAACfCgpWRkZIQUFNc11dUQcHqKio7e3voKCgnp6enJycAAC5mpqasgAAmJiY6wAAlpaWngAAlJSUExMckpKSkJCQjo6OAACRioqKiIiIdqJ2hYiFhoaGhISEeA8PgoKCfoJ+fn5+fHx8enp6SsBKdnZ2dHR0cnJycHBwmAAAbm5uanBqemZmampqhAAARKJES5ZLYWRhYmJiAPQAOJg4XFxcWlpaAOYAAgJdQnhCVlZWAADwLpQuR2hHMTFgANgAUlJSUFBQAM4AIZgh////AMgATExM/f39AMYAAACdb2tr6g4OSEhIALwANGY0AgL1U1NgALAAAK4AtwAAAKQA7+/vAKIAj09PlTQ0AJgAAJYAAJIA5+fnAIwA4+PjAIAAkgYGAQFvZFZZAABkTk5rz8/P3d3gAAB7ycnJFhZBISFZV1dZRER4v7+/693dLS1UCgpgAAD/v319RGIGqgAAApBJREFUOI1jUCYAGEhU8OBVGh4F95gWmz2xZP7yAauCzPdSpm0NbHobxDesrvoSGYCqIK2Gb+WZBsvKyZXiC6za29s3PFrX9TwGpiDmVd9ynTbLR5MV+mtrJRXYLBeIr9Z7skZnOWdNJlhBhfJybe1bkv1XfW/dZFVUnDhRsVZS/Iw2EKzvAyt4IT97vjqjL+tNGS0trXrmurNn66oYgcxV2w+9ByvIma80d4aUsgYqWL7F9fCJexA3LPK8ZivCLzxfHQaWLtVY73L4xDlnqC9mJZ1yXDaNj3eK7BIoWLndKChKoGUhVMG06IitFoJTeLk5uSWUFy9W1dpyyUdtZni4QAdUwZTEpJ1b5/CLbNTl6e6ZsXj9jrfSe5t2lRhwlEMVdBxNPb512TTd8+n72Fm6lu5wFv2stqt4arNmAFQB074bV3Y6iWw8fntbTzfLCudnF/c2ep97LbASFtTV7sl5Rxw32frdtudk714DNMDhTWtU08x4mILI3ckPY51SbE9l2/dxspu+LdvbeCBI5eWnapiCnN1XChMPZngG3rGf0Ndj8+5zL8frl7m5HAkwBQH70++EBPvfDb67iZe7b4foRa6PxfqPhZ4honvttWv7Ew/mh+Vt4uOd5FK6N7y1iEEu1wShQOzG5Qt2x7PP37fm5xPe49Or33LA4XRzNUJBKI/7ZrPoK7H5xoL8Uq6lpz8dCJLjYEJJcs/XmO1LiiswFBZUco3i0ueayfAcLU1mzTO/nFRgLCa81PVj41MDoxcYiTag4+jlQkMJsRVu3sUl7zqxJfvybSGLZkusOeRVpBWKPV9c75o/b7apx+Guk9jyBQgcey8/z+YQE7IQetZ7Md2sQhmfAuWEB8r4FWAAANxEPMkO1rmYAAAAAElFTkSuQmCC",
3478       "tp0n3p08.png", false, 32, 32, "985ccf415de9754ff21296de6cf69a38");
3479   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYagMeiWXwAAAt9QTFRF////gFZWtbW4qEJCn5+fsSAgixUVnZ2dGxtZm5ubAACEmZmZj6ePl5eXlZWVk5OTKSlWkZGRAACbj4+Pi5WLLi6njY2NgAAAi4uLuQAAiYmJDAzVeHV1h4eHAACyhYWFpQAA3gAAgYGBf39/AACefX19AADJe3t7eXl5NzdWd3d3dXV1c3NzSKlIjgAAAgJkAABiVolWKCh8U4tTiYmPZ2dnZWVlXW1dE+UThiYmby0tRJFEYWFhO507RIlEPZM9AACkAPMAAPEAWVlZV1dXVVVVU1NTNIU0UVFRJJckT09POjpBEBC6sg8PAMcAAMUA/Pz8AMMABASXAMEALXct+vr6AL8AAABoAL0A2tTUEBB7Ca0J+Pj4ALkAALcAnJyh9vb2DKEMALMAALEAEJEQAKsA8vLyAKkAAKcA7u7u7OzsAJcA6urqAABrAI0AAIsAAIkAAIcAMTExGRkqBwdAEhKuCQnu09bTzMzMkwAAoyoqxsbGxMTEzAAA0woKgWtreD4+AwNtAACfCgpWRkZIQUFNc11dUQcHqKio7e3voKCgnp6enJycAAC5mpqasgAAmJiY6wAAlpaWngAAlJSUExMckpKSkJCQjo6OAACRioqKiIiIdqJ2hYiFhoaGhISEeA8PgoKCfoJ+fn5+fHx8enp6SsBKdnZ2dHR0cnJycHBwmAAAbm5uanBqemZmampqhAAARKJES5ZLYWRhYmJiAPQAOJg4XFxcWlpaAOYAAgJdQnhCVlZWAADwLpQuR2hHMTFgANgAUlJSUFBQAM4AIZghFBRtAMgATExM/f39AMYAAACdb2tr6g4OSEhIALwANGY0AgL1U1NgALAAAK4AtwAAAKQA7+/vAKIAj09PlTQ0AJgAAJYAAJIA5+fnAIwA4+PjAIAAkgYGAQFvZFZZAABkTk5rz8/P3d3gAAB7ycnJFhZBISFZV1dZRER4v7+/693dLS1UCgpgAAD/v319DyW3rQAAAAF0Uk5TAEDm2GYAAAKKSURBVDiNY2CgMnjwKg2P7D2mxWZPLJm/fMAqm/leyrStgU1vg/iG1VVfIgNQZdNq+FaeabCsnFwpvsCqvb19w6N1Xc9jYLIxr/qW67RZPpqs0F9bK6nAZrlAfLXekzU6yzlrMsEKKpSXa2vfkuy/6nvrJqui4sSJirWS4me0gWB9H1jBC/nZ89UZfVlvymhpadUz1509W1fFCGSu2n7oPVhBznyluTOklDVQwfItrodP3IO4YZHnNVsRfuH56jCwdKnGepfDJ845Q105K+mU47JpfLxTZJdAwcrtRkFRAi0LoQqmRUdstRCcwsvNyS2hvHixqtaWSz5qM8PDBTqgCqYkJu3cOodfZKMuT3fPjMXrd7yV3tu0q8SAoxyqoONo6vGty6bpnk/fx87StXSHs+hntV3FU5s1YcHJtO/GlZ1OIhuP397W082ywvnZxb2N3udeC6yEBWW1e3LeEcdNtn637TnZu9cADXB40xrVNDMepiByd/LDWKcU21PZ9n2c7KZvy/Y2HghSefmpGqYgZ/eVwsSDGZ6Bd+wn9PXYvPvcy/H6ZW4uRwJMQcD+9Dshwf53g+9u4uXu2yF6ketjsf5joWeI2F577dr+xIP5YXmb+HgnuZTuDW8tOiaXa4JQIHbj8gW749nn71vz8wnv8enVbzngcLq5GqEglMd9s1n0ldh8Y0F+KdfS058OBMlxMKEkqedrzPYlxRUYCgsquUZx6XPNPPYcLUlmzTO/nFRgLCa81PVj41MDoxcM6CCg4+jlQkMJsRVu3sUl7zox5IGgfFvIotkSaw55FWmFYpNnYLjeNX/ebFOPw10nscsDwXv5eTaHmHBKA8GL6WYV+OQZGBIe4JfHBAANrv+RnZXbwAAAAABJRU5ErkJggg==",
3480       "tp1n3p08.png", false, 32, 32, "d1f6636d81c74f163bfff1405bf406cf");
3481   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAEAAADurUJNAAAABGdBTUEAAYagMeiWXwAAAEFJREFUeJxjZGAkABQIyLMMBQWMDwgp+PcfP2B5MBwUMMoRkGdkonlcDAYFjI/wyv7/z/iH5nExGBQwyuCVZWQEAFDl/nE14thZAAAAAElFTkSuQmCC",
3482       "xc1n0g08.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3483   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAkAAAArGWqiAAAABGdBTUEAAYagMeiWXwAAAEhJREFUeJzt1cEJADAMAkCF7JH9t3ITO0Qr9KH4zuErtA0EO4AKFPgcoO3kfUx4QIECD0qHH8KEBxQo8KB0OCOpQIG7cHejwAGCsfleD0DPSwAAAABJRU5ErkJggg==",
3484       "xc9n2c08.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3485   testPngSuiteImage("iVBORw0NGg0AAAANSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAEhJREFUeJxjYGAQFFRSMjZ2cQkNTUsrL2cgQwCV29FBjgAqd+ZMcgRQuatWkSOAyt29mxwBVO6ZM+QIoHLv3iVHAJX77h0ZAgAfFO4B6v9B+gAAAABJRU5ErkJggg==",
3486       "xcrn0g04.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3487   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQAAAABbAUdZAAAABGdBTUEAAYagMeiWXwAAAFtJREFUeJwtzLEJAzAMBdHr0gSySiALejRvkBU8gsGNCmFFB1Hx4IovqurSpIRszqklUwbnUzRXEuIRsiG/SyY9G0JzJSVei9qynm9qyjBpLp0pYW7pbzBl8L8fEIdJL0NTVU0AAAAASUVORK5CYII=",
3488       "xcsn0g01.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3489   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAAIAAADMaKZiAAAABGdBTUEAAYagMeiWXwAAAEhJREFUeJzt1cEJADAMAkCF7JH9t3ITO0Qr9KH4zuErtA0EO4AKFPgcoO3kfUx4QIECD0qHH8KEBxQo8KB0OCOpQIG7cHejwAGCsfleD0DPSwAAAABJRU5ErkJggg==",
3490       "xd0n2c08.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3491   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAwIAAACLyNyyAAAABGdBTUEAAYagMeiWXwAAAEhJREFUeJzt1cEJADAMAkCF7JH9t3ITO0Qr9KH4zuErtA0EO4AKFPgcoO3kfUx4QIECD0qHH8KEBxQo8KB0OCOpQIG7cHejwAGCsfleD0DPSwAAAABJRU5ErkJggg==",
3492       "xd3n2c08.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3493   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgYwIAAAAS+qv/AAAABGdBTUEAAYagMeiWXwAAAEhJREFUeJzt1cEJADAMAkCF7JH9t3ITO0Qr9KH4zuErtA0EO4AKFPgcoO3kfUx4QIECD0qHH8KEBxQo8KB0OCOpQIG7cHejwAGCsfleD0DPSwAAAABJRU5ErkJggg==",
3494       "xd9n2c08.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3495   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQAAAABbAUdZAAAABGdBTUEAAYagMeiWXwAAAABJRU5ErkJggg==",
3496       "xdtn0g01.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3497   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABDU1VNAAAABGdBTUEAAYagMeiWXwAAAEFJREFUeJxjZGAkABQIyLMMBQWMDwgp+PcfP2B5MBwUMMoRkGdkonlcDAYFjI/wyv7/z/iH5nExGBQwyuCVZWQEAFDl/nE14thZAAAAAElFTkSuQmCC",
3498       "xhdn0g08.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3499   testPngSuiteImage("iVBORwoKGgoAAAAKSUhEUgAAACAAAAAgBAAAAACT4cgpAAAABGdBTUEAAYagMeiWXwAAAEhJREFUeJxjYGAQFFRSMjZ2cQkKTUsrL2cgQwCV29FBjgAqd+ZMcgRQuatWkSOAyt29mxwBVO6ZM+QIoHLv3iVHAJX77h0ZAgAfFO4B6v9B+gAAAABJRU5ErkJggg==",
3500       "xlfn0g04.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3501   testPngSuiteImage("CVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQAAAABbAUdZAAAABGdBTUEAAYagMeiWXwAAAFtJREFUeJwtzLEJAzAMBdHr0gSySiALejRvkBU8gsGNCmFFB1Hx4IovqurSpIRszqklUwbnUzRXEuIRsiG/SyY9G0JzJSVei9qynm9qyjBpLp0pYW7pbzBl8L8fEIdJL9AvFMkAAAAASUVORK5CYII=",
3502       "xs1n0g01.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3503   testPngSuiteImage("iVFORw0KGgoAAAANSUhEUgAAACAAAAAgAQAAAABbAUdZAAAABGdBTUEAAYagMeiWXwAAAFtJREFUeJwtzLEJAzAMBdHr0gSySiALejRvkBU8gsGNCmFFB1Hx4IovqurSpIRszqklUwbnUzRXEuIRsiG/SyY9G0JzJSVei9qynm9qyjBpLp0pYW7pbzBl8L8fEIdJL9AvFMkAAAAASUVORK5CYII=",
3504       "xs2n0g01.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3505   testPngSuiteImage("iVBOZw0KGgoAAAANSUhEUgAAACAAAAAgAQAAAABbAUdZAAAABGdBTUEAAYagMeiWXwAAAFtJREFUeJwtzLEJAzAMBdHr0gSySiALejRvkBU8gsGNCmFFB1Hx4IovqurSpIRszqklUwbnUzRXEuIRsiG/SyY9G0JzJSVei9qynm9qyjBpLp0pYW7pbzBl8L8fEIdJL9AvFMkAAAAASUVORK5CYII=",
3506       "xs4n0g01.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3507   testPngSuiteImage("iVBORw0KIAoAAAANSUhEUgAAACAAAAAgAQAAAABbAUdZAAAABGdBTUEAAYagMeiWXwAAAFtJREFUeJwtzLEJAzAMBdHr0gSySiALejRvkBU8gsGNCmFFB1Hx4IovqurSpIRszqklUwbnUzRXEuIRsiG/SyY9G0JzJSVei9qynm9qyjBpLp0pYW7pbzBl8L8fEIdJL9AvFMkAAAAASUVORK5CYII=",
3508       "xs7n0g01.png", true, 32, 32, "d41d8cd98f00b204e9800998ecf8427e");
3509   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAMK0lEQVR42gEgDN/zAf//APgAAPgAAPcAAPgAAPgAAPgAAPcAAPgAAPgAAPgAAPgAAPcAAPgAAPgAAPgAAPcAAPgAAPgAAPgAAPcAAPgAAPgAAPgAAPgAAPcAAPgAAPgAAPgAAPcAAPgAAPgAAAQA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIBAD3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAACQQA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAkAAAgEAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAJAAAIAAAIBAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAACQAACAAACAAACAQA9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAkAAAgAAAgAAAgAAAkEAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIBAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAACQAACAAACAAACAAACQAACAAACAQA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgEAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIBAD3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQQA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgEAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIAAAJAAAIAAAIBAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQAACAAACAAACAQA9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkEAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIBAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQAACAAACAAACAAACQAACAAACAQA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgEAPcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJBAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACQAACAQA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgEAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIBAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAQA9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkEAPgAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIAAAJAAAIBAD4AAAAAAAAAAAAAAAAAAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQAACAAACAQA+AAAAAAAAAAAAAAAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgAAAgAAAgEAPcAAAAAAAAAAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAIAAAJAAAIAAAIAAAIAAAJBAD4AAAAAAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACQAACAAACAAACAAACAAACQAACAAACAAACAAACQAACAQA+AAAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAgAAAkAAAgAAAgAAAgAAAkAAAgAAAhVk05uHxPwlQAAAABJRU5ErkJggg==",
3510       "z00n2c08.png", false, 32, 32, "6284c288d49534c897da4e50a9d05002");
3511   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAr0lEQVR4XrXR3Q5AMAwF4Epc8P4Py91sIgxb15/TRUSC76Q9U0q0U7m28/5/Zl7Vv/Q+mwsZeJbQgIUoB+Q5Q07RidagCS79nADfwaNHBLx0eAdfHdtBQweuqK2jAro6JIDT/SUPdGfJY92zIpFuDpDqtg4UuqEDna5dkVpXBVh0eQdGXdiBXZesyKUPA7w6HwDQmZIxeq9kmN5cEVL/B4D1Twd4ve4gRL9XFKXngANVk05u39tDGQAAAABJRU5ErkJggg==",
3512       "z03n2c08.png", false, 32, 32, "6284c288d49534c897da4e50a9d05002");
3513   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAp0lEQVR4nLXRSw6AIBAD0JqwwPsfFna4MX4QYT4dVySS19BuraECFSg4D9158ktyLaEi8suhARnICSVQB/agF5x6UEW3HhHw0ukb9Dp3g4FOrGisswJ+dUrATPePvNCdI691T0Ui3Rwg1W0bKHTDBjpdW5FaVwVYdPkGRl24gV2XVOTSlwFefR5A0Ccjc/S/kWn6sCKm/g0g690GfP25QYh+VRSlA/kAVZNObjFSwSwAAAAASUVORK5CYII=",
3514       "z06n2c08.png", false, 32, 32, "6284c288d49534c897da4e50a9d05002");
3515   testPngSuiteImage("iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAp0lEQVR42rXRSw6AIBAD0JqwwPsfFna4MX4QYT4dVySS19BuraECFSg4D9158ktyLaEi8suhARnICSVQB/agF5x6UEW3HhHw0ukb9Dp3g4FOrGisswJ+dUrATPePvNCdI691T0Ui3Rwg1W0bKHTDBjpdW5FaVwVYdPkGRl24gV2XVOTSlwFefR5A0Ccjc/S/kWn6sCKm/g0g690GfP25QYh+VRSlA/kAVZNObtYRvvUAAAAASUVORK5CYII=",
3516       "z09n2c08.png", false, 32, 32, "6284c288d49534c897da4e50a9d05002");
3517 }
3518 
3519 
testErrorImages()3520 void testErrorImages() {
3521   std::cout << "testErrorImages" << std::endl;
3522   // Image with color type palette but missing PLTE chunk
3523   testBase64Image("iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAgMAAAAhHED1AAAAU0lEQVR4Ae3MwQAAAAxFoXnM3/NDvGsBdB8JBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUAgEEQDHGPAW1eyhK0AAAAASUVORK5CYII=", true, 256, 256, "");
3524 }
3525 
3526 // defined in lodepng.cpp
3527 unsigned lode_png_test_bitreader(const unsigned char* data, size_t size, size_t numsteps, const size_t* steps, unsigned* result);
3528 
testBitReaderCase(const std::string & bits,const std::vector<size_t> & steps,bool expect_error,bool silent=false)3529 void testBitReaderCase(const std::string& bits, const std::vector<size_t>& steps, bool expect_error, bool silent = false) {
3530   if(!silent) std::cout << "testBitReaderCase: " << bits << ", #steps: " << steps.size() << std::endl;
3531   std::vector<unsigned char> data;
3532   std::vector<bool> bits0;
3533   size_t bitcount = 0;
3534   for(size_t i = 0; i < bits.size(); i++) {
3535     char c = bits[i];
3536     if(c != '0' && c != '1') continue;
3537     if((bitcount & 7) == 0) data.push_back(0);
3538     int bit = (c == '1');
3539     data.back() |= (bit << (bitcount & 7));
3540     bits0.push_back(bit);
3541     bitcount++;
3542   }
3543   std::vector<unsigned> result(steps.size());
3544   unsigned ok = lode_png_test_bitreader(data.data(), data.size(), steps.size(), steps.data(), result.data());
3545   if(expect_error) {
3546     assertEquals(0, ok, "expected it would give an error");
3547     return;
3548   }
3549   assertEquals(1, ok, "expected there would be no error");
3550 
3551   std::vector<bool> bits1;
3552   for(size_t i = 0; i < steps.size(); i++) {
3553     size_t step = steps[i];
3554     size_t value = result[i];
3555     for(size_t j = 0; j < step; j++) {
3556       bits1.push_back((value >> j) & 1);
3557     }
3558   }
3559   bits0.resize(bits1.size()); // only test those bits that were actually read for the test
3560 
3561   assertEquals(bits0, bits1);
3562 }
3563 
3564 // This is still using C++98 for lodepng for compatibility, even though I'd love to use C++11 vector initializer lists here.
3565 // TODO: use modern C++ at least for the unit test
3566 #define V(arr) std::vector<size_t>(arr, arr + sizeof(arr) / sizeof(*arr))
3567 
testBitReader()3568 void testBitReader() {
3569   std::string zeros = "0000000000000000000000000000000000000000000000000000000000000000";
3570   testBitReaderCase("", std::vector<size_t>(0), false);
3571   { size_t arr[] = {1}; testBitReaderCase("0", V(arr), false); }
3572   { size_t arr[] = {1}; testBitReaderCase("1", V(arr), false); }
3573   { size_t arr[] = {2}; testBitReaderCase("00", V(arr), false); }
3574   { size_t arr[] = {2}; testBitReaderCase("01", V(arr), false); }
3575   { size_t arr[] = {2}; testBitReaderCase("10", V(arr), false); }
3576   { size_t arr[] = {2}; testBitReaderCase("11", V(arr), false); }
3577   { size_t arr[] = {3}; testBitReaderCase("111", V(arr), false); }
3578   { size_t arr[] = {4}; testBitReaderCase("1111", V(arr), false); }
3579   { size_t arr[] = {8}; testBitReaderCase("11111111", V(arr), false); }
3580   { size_t arr[] = {9}; testBitReaderCase("111111111", V(arr), false); }
3581   { size_t arr[] = {9}; testBitReaderCase("11111111", V(arr), true); }
3582   { size_t arr[] = {16}; testBitReaderCase("1111111111111111", V(arr), false); }
3583   { size_t arr[] = {17}; testBitReaderCase("11111111111111111", V(arr), false); }
3584   { size_t arr[] = {17}; testBitReaderCase("1111111111111111", V(arr), true); }
3585   { size_t arr[] = {24}; testBitReaderCase("111111111111111111111111", V(arr), false); }
3586   { size_t arr[] = {25}; testBitReaderCase("1111111111111111111111111", V(arr), false); }
3587   { size_t arr[] = {25}; testBitReaderCase("111111111111111111111111", V(arr), true); }
3588   { size_t arr[] = {31}; testBitReaderCase("1111111111111111111111111111111", V(arr), false); }
3589   { size_t arr[] = {1, 31}; testBitReaderCase("11111111111111111111111111111111", V(arr), false); }
3590   { size_t arr[] = {31}; testBitReaderCase("111111111111111111111111", V(arr), true); }
3591   { size_t arr[] = {16, 16}; testBitReaderCase("11111111111111111111111111111111", V(arr), false); }
3592   { size_t arr[] = {1}; testBitReaderCase("0" + zeros, V(arr), false); }
3593   { size_t arr[] = {1}; testBitReaderCase("1" + zeros, V(arr), false); }
3594   { size_t arr[] = {2}; testBitReaderCase("00" + zeros, V(arr), false); }
3595   { size_t arr[] = {2}; testBitReaderCase("01" + zeros, V(arr), false); }
3596   { size_t arr[] = {2}; testBitReaderCase("10" + zeros, V(arr), false); }
3597   { size_t arr[] = {2}; testBitReaderCase("11" + zeros, V(arr), false); }
3598   { size_t arr[] = {3}; testBitReaderCase("111" + zeros, V(arr), false); }
3599   { size_t arr[] = {4}; testBitReaderCase("1111" + zeros, V(arr), false); }
3600   { size_t arr[] = {8}; testBitReaderCase("11111111" + zeros, V(arr), false); }
3601   { size_t arr[] = {9}; testBitReaderCase("111111111" + zeros, V(arr), false); }
3602   { size_t arr[] = {16}; testBitReaderCase("1111111111111111" + zeros, V(arr), false); }
3603   { size_t arr[] = {17}; testBitReaderCase("11111111111111111" + zeros, V(arr), false); }
3604   { size_t arr[] = {24}; testBitReaderCase("111111111111111111111111" + zeros, V(arr), false); }
3605   { size_t arr[] = {25}; testBitReaderCase("1111111111111111111111111" + zeros, V(arr), false); }
3606   { size_t arr[] = {31}; testBitReaderCase("1111111111111111111111111111111" + zeros, V(arr), false); }
3607   { size_t arr[] = {16, 16}; testBitReaderCase("11111111111111111111111111111111" + zeros, V(arr), false); }
3608 
3609   // 128 arbitrary bits
3610   std::string test = "10101011110000101110010010000101000100100000111000010010010010010010111100000100100100100000001010111111110001111010101011011001";
3611   for(size_t i = 0; i < 32; i++) {
3612     std::cout << "testBitReader loop " << i << std::endl;
3613     { size_t arr[] = {i}; testBitReaderCase(test, V(arr), false, true); }
3614     { size_t arr[] = {i, i}; testBitReaderCase(test, V(arr), false, true); }
3615     { size_t arr[] = {i, i, i}; testBitReaderCase(test, V(arr), false, true); }
3616     { size_t arr[] = {i, i, i, i}; testBitReaderCase(test, V(arr), false, true); }
3617     { size_t arr[] = {1, i, i, i, i}; testBitReaderCase(test, V(arr), false, true); }
3618     { size_t arr[] = {2, i, i, i, i}; testBitReaderCase(test, V(arr), false, true); }
3619     { size_t arr[] = {3, i, i, i, i}; testBitReaderCase(test, V(arr), false, true); }
3620     { size_t arr[] = {31, 31, 31, i}; testBitReaderCase(test, V(arr), false, true); }
3621     { size_t arr[] = {i, i, i, i, i, i, i, i}; testBitReaderCase(test + test, V(arr), false, true); }
3622     for(size_t j = 0; j < 32; j++) {
3623       { size_t arr[] = {i, j}; testBitReaderCase(test, V(arr), false, true); }
3624       { size_t arr[] = {i, j, i, j}; testBitReaderCase(test, V(arr), false, true); }
3625       { size_t arr[] = {i, i, j, j}; testBitReaderCase(test, V(arr), false, true); }
3626       { size_t arr[] = {31, 31, i, j}; testBitReaderCase(test, V(arr), false, true); }
3627     }
3628   }
3629   { size_t arr[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; testBitReaderCase(test, V(arr), false); }
3630   { size_t arr[] = {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}; testBitReaderCase(test, V(arr), false); }
3631   { size_t arr[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,31,1,1,1,1,1,1,1,1,1,1,1}; testBitReaderCase(test, V(arr), false); }
3632   { size_t arr[] = {16,1,2,4,7,3,6,28,28,31,1,17,12,1,3,8,3,3,14,21,25,24,1,8,7}; testBitReaderCase(test + test + test, V(arr), false); }
3633   { size_t arr[] = {5,7,17,15,6,8,4,5,3,11,1,4,4,8,6,4,5,1,6,5,13,8,18,1,1,8,7,2}; testBitReaderCase(test + test + test, V(arr), false); }
3634 
3635 }
3636 
doMain()3637 void doMain() {
3638   //PNG
3639   testPngSuite();
3640   testErrorImages();
3641   testPNGCodec();
3642   testPaletteFilterTypesZero();
3643   testComplexPNG();
3644   testInspectChunk();
3645   testPredefinedFilters();
3646   testFuzzing();
3647   testEncoderErrors();
3648   testPaletteToPaletteDecode();
3649   testPaletteToPaletteDecode2();
3650   testColorProfile();
3651   testBkgdChunk();
3652   testBkgdChunk2();
3653 
3654   //Colors
3655 #ifndef DISABLE_SLOW
3656   testFewColors();
3657 #endif // DISABLE_SLOW
3658   testColorKeyConvert();
3659   testColorConvert();
3660   testColorConvert2();
3661   testPaletteToPaletteConvert();
3662   testRGBToPaletteConvert();
3663   test16bitColorEndianness();
3664   testAutoColorModels();
3665   testNoAutoConvert();
3666   testChrmToSrgb();
3667   testXYZ();
3668   testICC();
3669   testICCGray();
3670 
3671   //Zlib
3672   testCompressZlib();
3673   testHuffmanCodeLengths();
3674   testCustomZlibCompress();
3675   testCustomZlibCompress2();
3676   testCustomDeflate();
3677   testCustomZlibDecompress();
3678   testCustomInflate();
3679   testBitReader();
3680   // TODO: add test for huffman code with exactly 0 and 1 symbols present
3681 
3682   //lodepng_util
3683   testChunkUtil();
3684   testGetFilterTypes();
3685 
3686   std::cout << "\ntest successful" << std::endl;
3687 }
3688 
main()3689 int main() {
3690   try {
3691     doMain();
3692   }
3693   catch(...) {
3694     std::cout << std::endl;
3695     std::cout << "caught error!" << std::endl;
3696     std::cout << "*** TEST FAILED ***" << std::endl;
3697   }
3698 
3699   return 0;
3700 }
3701