Added saving support to TGA image handler.
[wxWidgets.git] / tests / image / image.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/image/image.cpp
3 // Purpose: Test wxImage
4 // Author: Francesco Montorsi
5 // Created: 2009-05-31
6 // RCS-ID: $Id$
7 // Copyright: (c) 2009 Francesco Montorsi
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ----------------------------------------------------------------------------
12 // headers
13 // ----------------------------------------------------------------------------
14
15 #include "testprec.h"
16
17 #if wxUSE_IMAGE
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #endif // WX_PRECOMP
25
26 #include "wx/image.h"
27 #include "wx/url.h"
28 #include "wx/log.h"
29 #include "wx/mstream.h"
30 #include "wx/zstream.h"
31 #include "wx/wfstream.h"
32
33 struct testData {
34 const char* file;
35 wxBitmapType type;
36 unsigned bitDepth;
37 } g_testfiles[] =
38 {
39 { "horse.ico", wxBITMAP_TYPE_ICO, 4 },
40 { "horse.xpm", wxBITMAP_TYPE_XPM, 8 },
41 { "horse.png", wxBITMAP_TYPE_PNG, 24 },
42 { "horse.ani", wxBITMAP_TYPE_ANI, 24 },
43 { "horse.bmp", wxBITMAP_TYPE_BMP, 8 },
44 { "horse.cur", wxBITMAP_TYPE_CUR, 1 },
45 { "horse.gif", wxBITMAP_TYPE_GIF, 8 },
46 { "horse.jpg", wxBITMAP_TYPE_JPEG, 24 },
47 { "horse.pcx", wxBITMAP_TYPE_PCX, 8 },
48 { "horse.pnm", wxBITMAP_TYPE_PNM, 24 },
49 { "horse.tga", wxBITMAP_TYPE_TGA, 8 },
50 { "horse.tif", wxBITMAP_TYPE_TIF, 8 }
51 };
52
53
54 // ----------------------------------------------------------------------------
55 // test class
56 // ----------------------------------------------------------------------------
57
58 class ImageTestCase : public CppUnit::TestCase
59 {
60 public:
61 ImageTestCase();
62 ~ImageTestCase();
63
64 private:
65 CPPUNIT_TEST_SUITE( ImageTestCase );
66 CPPUNIT_TEST( LoadFromSocketStream );
67 CPPUNIT_TEST( LoadFromZipStream );
68 CPPUNIT_TEST( LoadFromFile );
69 CPPUNIT_TEST( SizeImage );
70 CPPUNIT_TEST( CompareLoadedImage );
71 CPPUNIT_TEST( CompareSavedImage );
72 CPPUNIT_TEST_SUITE_END();
73
74 void LoadFromSocketStream();
75 void LoadFromZipStream();
76 void LoadFromFile();
77 void SizeImage();
78 void CompareLoadedImage();
79 void CompareSavedImage();
80
81 DECLARE_NO_COPY_CLASS(ImageTestCase)
82 };
83
84 CPPUNIT_TEST_SUITE_REGISTRATION( ImageTestCase );
85 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ImageTestCase, "ImageTestCase" );
86
87 ImageTestCase::ImageTestCase()
88 {
89 wxSocketBase::Initialize();
90
91 // the formats we're going to test:
92 wxImage::AddHandler(new wxICOHandler);
93 wxImage::AddHandler(new wxXPMHandler);
94 wxImage::AddHandler(new wxPNGHandler);
95 wxImage::AddHandler(new wxANIHandler);
96 wxImage::AddHandler(new wxBMPHandler);
97 wxImage::AddHandler(new wxCURHandler);
98 wxImage::AddHandler(new wxGIFHandler);
99 wxImage::AddHandler(new wxJPEGHandler);
100 wxImage::AddHandler(new wxPCXHandler);
101 wxImage::AddHandler(new wxPNMHandler);
102 wxImage::AddHandler(new wxTGAHandler);
103 wxImage::AddHandler(new wxTIFFHandler);
104 }
105
106 ImageTestCase::~ImageTestCase()
107 {
108 wxSocketBase::Shutdown();
109 }
110
111 void ImageTestCase::LoadFromFile()
112 {
113 wxImage img;
114 for (unsigned int i=0; i<WXSIZEOF(g_testfiles); i++)
115 CPPUNIT_ASSERT(img.LoadFile(g_testfiles[i].file));
116 }
117
118 void ImageTestCase::LoadFromSocketStream()
119 {
120 if (!IsNetworkAvailable()) // implemented in test.cpp
121 {
122 wxLogWarning("No network connectivity; skipping the "
123 "ImageTestCase::LoadFromSocketStream test unit.");
124 return;
125 }
126
127 struct {
128 const char* url;
129 wxBitmapType type;
130 } testData[] =
131 {
132 { "http://www.wxwidgets.org/logo9.jpg", wxBITMAP_TYPE_JPEG },
133 { "http://www.wxwidgets.org/favicon.ico", wxBITMAP_TYPE_ICO }
134 };
135
136 for (unsigned int i=0; i<WXSIZEOF(testData); i++)
137 {
138 wxURL url(testData[i].url);
139 WX_ASSERT_EQUAL_MESSAGE
140 (
141 ("Constructing URL \"%s\" failed.", testData[i].url),
142 wxURL_NOERR,
143 url.GetError()
144 );
145
146 wxInputStream *in_stream = url.GetInputStream();
147 WX_ASSERT_MESSAGE
148 (
149 ("Opening URL \"%s\" failed.", testData[i].url),
150 in_stream && in_stream->IsOk()
151 );
152
153 wxImage img;
154
155 // NOTE: it's important to inform wxImage about the type of the image being
156 // loaded otherwise it will try to autodetect the format, but that
157 // requires a seekable stream!
158 WX_ASSERT_MESSAGE
159 (
160 ("Loading image from \"%s\" failed.", testData[i].url),
161 img.LoadFile(*in_stream, testData[i].type)
162 );
163
164 delete in_stream;
165 }
166 }
167
168 void ImageTestCase::LoadFromZipStream()
169 {
170 for (unsigned int i=0; i<WXSIZEOF(g_testfiles); i++)
171 {
172 switch (g_testfiles[i].type)
173 {
174 case wxBITMAP_TYPE_XPM:
175 case wxBITMAP_TYPE_GIF:
176 case wxBITMAP_TYPE_PCX:
177 case wxBITMAP_TYPE_TGA:
178 case wxBITMAP_TYPE_TIF:
179 continue; // skip testing those wxImageHandlers which cannot
180 // load data from non-seekable streams
181
182 default:
183 ; // proceed
184 }
185
186 // compress the test file on the fly:
187 wxMemoryOutputStream memOut;
188 {
189 wxFileInputStream file(g_testfiles[i].file);
190 CPPUNIT_ASSERT(file.IsOk());
191
192 wxZlibOutputStream compressFilter(memOut, 5, wxZLIB_GZIP);
193 CPPUNIT_ASSERT(compressFilter.IsOk());
194
195 file.Read(compressFilter);
196 CPPUNIT_ASSERT(file.GetLastError() == wxSTREAM_EOF);
197 }
198
199 // now fetch the compressed memory to wxImage, decompressing it on the fly; this
200 // allows us to test loading images from non-seekable streams other than socket streams
201 wxMemoryInputStream memIn(memOut);
202 CPPUNIT_ASSERT(memIn.IsOk());
203 wxZlibInputStream decompressFilter(memIn, wxZLIB_GZIP);
204 CPPUNIT_ASSERT(decompressFilter.IsOk());
205
206 wxImage img;
207
208 // NOTE: it's important to inform wxImage about the type of the image being
209 // loaded otherwise it will try to autodetect the format, but that
210 // requires a seekable stream!
211 WX_ASSERT_MESSAGE(("Could not load file type '%d' after it was zipped", g_testfiles[i].type),
212 img.LoadFile(decompressFilter, g_testfiles[i].type));
213 }
214 }
215
216 void ImageTestCase::SizeImage()
217 {
218 // Test the wxImage::Size() function which takes a rectangle from source and
219 // places it in a new image at a given position. This test checks, if the
220 // correct areas are chosen, and clipping is done correctly.
221
222 // our test image:
223 static const char * xpm_orig[] = {
224 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
225 " .....",
226 " ++++@@@@.",
227 " +... @.",
228 " +.@@++ @.",
229 " +.@ .+ @.",
230 ".@ +. @.+ ",
231 ".@ ++@@.+ ",
232 ".@ ...+ ",
233 ".@@@@++++ ",
234 "..... "
235 };
236 // the expected results for all tests:
237 static const char * xpm_l_t[] = {
238 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
239 "... @.BB",
240 ".@@++ @.BB",
241 ".@ .+ @.BB",
242 " +. @.+ BB",
243 " ++@@.+ BB",
244 " ...+ BB",
245 "@@@++++ BB",
246 "... BB",
247 "BBBBBBBBBB",
248 "BBBBBBBBBB"
249 };
250 static const char * xpm_t[] = {
251 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
252 " +... @.",
253 " +.@@++ @.",
254 " +.@ .+ @.",
255 ".@ +. @.+ ",
256 ".@ ++@@.+ ",
257 ".@ ...+ ",
258 ".@@@@++++ ",
259 "..... ",
260 "BBBBBBBBBB",
261 "BBBBBBBBBB"
262 };
263 static const char * xpm_r_t[] = {
264 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
265 "BB +... ",
266 "BB +.@@++ ",
267 "BB +.@ .+ ",
268 "BB.@ +. @.",
269 "BB.@ ++@@.",
270 "BB.@ ...",
271 "BB.@@@@+++",
272 "BB..... ",
273 "BBBBBBBBBB",
274 "BBBBBBBBBB"
275 };
276 static const char * xpm_l[] = {
277 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
278 " .....BB",
279 "+++@@@@.BB",
280 "... @.BB",
281 ".@@++ @.BB",
282 ".@ .+ @.BB",
283 " +. @.+ BB",
284 " ++@@.+ BB",
285 " ...+ BB",
286 "@@@++++ BB",
287 "... BB"
288 };
289 static const char * xpm_r[] = {
290 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
291 "BB ...",
292 "BB ++++@@@",
293 "BB +... ",
294 "BB +.@@++ ",
295 "BB +.@ .+ ",
296 "BB.@ +. @.",
297 "BB.@ ++@@.",
298 "BB.@ ...",
299 "BB.@@@@+++",
300 "BB..... "
301 };
302 static const char * xpm_l_b[] = {
303 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
304 "BBBBBBBBBB",
305 "BBBBBBBBBB",
306 " .....BB",
307 "+++@@@@.BB",
308 "... @.BB",
309 ".@@++ @.BB",
310 ".@ .+ @.BB",
311 " +. @.+ BB",
312 " ++@@.+ BB",
313 " ...+ BB"
314 };
315 static const char * xpm_b[] = {
316 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
317 "BBBBBBBBBB",
318 "BBBBBBBBBB",
319 " .....",
320 " ++++@@@@.",
321 " +... @.",
322 " +.@@++ @.",
323 " +.@ .+ @.",
324 ".@ +. @.+ ",
325 ".@ ++@@.+ ",
326 ".@ ...+ "
327 };
328 static const char * xpm_r_b[] = {
329 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
330 "BBBBBBBBBB",
331 "BBBBBBBBBB",
332 "BB ...",
333 "BB ++++@@@",
334 "BB +... ",
335 "BB +.@@++ ",
336 "BB +.@ .+ ",
337 "BB.@ +. @.",
338 "BB.@ ++@@.",
339 "BB.@ ..."
340 };
341 static const char * xpm_sm[] = {
342 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
343 " .....",
344 " ++++@@@",
345 " +... ",
346 " +.@@++ ",
347 " +.@ .+ ",
348 ".@ +. @.",
349 ".@ ++@@.",
350 ".@ ..."
351 };
352 static const char * xpm_gt[] = {
353 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
354 " .....BB",
355 " ++++@@@@.BB",
356 " +... @.BB",
357 " +.@@++ @.BB",
358 " +.@ .+ @.BB",
359 ".@ +. @.+ BB",
360 ".@ ++@@.+ BB",
361 ".@ ...+ BB",
362 ".@@@@++++ BB",
363 "..... BB",
364 "BBBBBBBBBBBB",
365 "BBBBBBBBBBBB"
366 };
367 static const char * xpm_gt_l_t[] = {
368 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
369 "... @.BBBB",
370 ".@@++ @.BBBB",
371 ".@ .+ @.BBBB",
372 " +. @.+ BBBB",
373 " ++@@.+ BBBB",
374 " ...+ BBBB",
375 "@@@++++ BBBB",
376 "... BBBB",
377 "BBBBBBBBBBBB",
378 "BBBBBBBBBBBB",
379 "BBBBBBBBBBBB",
380 "BBBBBBBBBBBB"
381 };
382 static const char * xpm_gt_l[] = {
383 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
384 " .....BBBB",
385 "+++@@@@.BBBB",
386 "... @.BBBB",
387 ".@@++ @.BBBB",
388 ".@ .+ @.BBBB",
389 " +. @.+ BBBB",
390 " ++@@.+ BBBB",
391 " ...+ BBBB",
392 "@@@++++ BBBB",
393 "... BBBB",
394 "BBBBBBBBBBBB",
395 "BBBBBBBBBBBB"
396 };
397 static const char * xpm_gt_l_b[] = {
398 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
399 "BBBBBBBBBBBB",
400 "BBBBBBBBBBBB",
401 " .....BBBB",
402 "+++@@@@.BBBB",
403 "... @.BBBB",
404 ".@@++ @.BBBB",
405 ".@ .+ @.BBBB",
406 " +. @.+ BBBB",
407 " ++@@.+ BBBB",
408 " ...+ BBBB",
409 "@@@++++ BBBB",
410 "... BBBB"
411 };
412 static const char * xpm_gt_l_bb[] = {
413 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
414 "BBBBBBBBBBBB",
415 "BBBBBBBBBBBB",
416 "BBBBBBBBBBBB",
417 "BBBBBBBBBBBB",
418 " .....BBBB",
419 "+++@@@@.BBBB",
420 "... @.BBBB",
421 ".@@++ @.BBBB",
422 ".@ .+ @.BBBB",
423 " +. @.+ BBBB",
424 " ++@@.+ BBBB",
425 " ...+ BBBB"
426 };
427 static const char * xpm_gt_t[] = {
428 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
429 " +... @.BB",
430 " +.@@++ @.BB",
431 " +.@ .+ @.BB",
432 ".@ +. @.+ BB",
433 ".@ ++@@.+ BB",
434 ".@ ...+ BB",
435 ".@@@@++++ BB",
436 "..... BB",
437 "BBBBBBBBBBBB",
438 "BBBBBBBBBBBB",
439 "BBBBBBBBBBBB",
440 "BBBBBBBBBBBB"
441 };
442 static const char * xpm_gt_b[] = {
443 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
444 "BBBBBBBBBBBB",
445 "BBBBBBBBBBBB",
446 " .....BB",
447 " ++++@@@@.BB",
448 " +... @.BB",
449 " +.@@++ @.BB",
450 " +.@ .+ @.BB",
451 ".@ +. @.+ BB",
452 ".@ ++@@.+ BB",
453 ".@ ...+ BB",
454 ".@@@@++++ BB",
455 "..... BB"
456 };
457 static const char * xpm_gt_bb[] = {
458 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
459 "BBBBBBBBBBBB",
460 "BBBBBBBBBBBB",
461 "BBBBBBBBBBBB",
462 "BBBBBBBBBBBB",
463 " .....BB",
464 " ++++@@@@.BB",
465 " +... @.BB",
466 " +.@@++ @.BB",
467 " +.@ .+ @.BB",
468 ".@ +. @.+ BB",
469 ".@ ++@@.+ BB",
470 ".@ ...+ BB"
471 };
472 static const char * xpm_gt_r_t[] = {
473 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
474 "BB +... @.",
475 "BB +.@@++ @.",
476 "BB +.@ .+ @.",
477 "BB.@ +. @.+ ",
478 "BB.@ ++@@.+ ",
479 "BB.@ ...+ ",
480 "BB.@@@@++++ ",
481 "BB..... ",
482 "BBBBBBBBBBBB",
483 "BBBBBBBBBBBB",
484 "BBBBBBBBBBBB",
485 "BBBBBBBBBBBB"
486 };
487 static const char * xpm_gt_r[] = {
488 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
489 "BB .....",
490 "BB ++++@@@@.",
491 "BB +... @.",
492 "BB +.@@++ @.",
493 "BB +.@ .+ @.",
494 "BB.@ +. @.+ ",
495 "BB.@ ++@@.+ ",
496 "BB.@ ...+ ",
497 "BB.@@@@++++ ",
498 "BB..... ",
499 "BBBBBBBBBBBB",
500 "BBBBBBBBBBBB"
501 };
502 static const char * xpm_gt_r_b[] = {
503 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
504 "BBBBBBBBBBBB",
505 "BBBBBBBBBBBB",
506 "BB .....",
507 "BB ++++@@@@.",
508 "BB +... @.",
509 "BB +.@@++ @.",
510 "BB +.@ .+ @.",
511 "BB.@ +. @.+ ",
512 "BB.@ ++@@.+ ",
513 "BB.@ ...+ ",
514 "BB.@@@@++++ ",
515 "BB..... "
516 };
517 static const char * xpm_gt_r_bb[] = {
518 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
519 "BBBBBBBBBBBB",
520 "BBBBBBBBBBBB",
521 "BBBBBBBBBBBB",
522 "BBBBBBBBBBBB",
523 "BB .....",
524 "BB ++++@@@@.",
525 "BB +... @.",
526 "BB +.@@++ @.",
527 "BB +.@ .+ @.",
528 "BB.@ +. @.+ ",
529 "BB.@ ++@@.+ ",
530 "BB.@ ...+ "
531 };
532 static const char * xpm_gt_rr_t[] = {
533 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
534 "BBBB +... ",
535 "BBBB +.@@++ ",
536 "BBBB +.@ .+ ",
537 "BBBB.@ +. @.",
538 "BBBB.@ ++@@.",
539 "BBBB.@ ...",
540 "BBBB.@@@@+++",
541 "BBBB..... ",
542 "BBBBBBBBBBBB",
543 "BBBBBBBBBBBB",
544 "BBBBBBBBBBBB",
545 "BBBBBBBBBBBB"
546 };
547 static const char * xpm_gt_rr[] = {
548 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
549 "BBBB ...",
550 "BBBB ++++@@@",
551 "BBBB +... ",
552 "BBBB +.@@++ ",
553 "BBBB +.@ .+ ",
554 "BBBB.@ +. @.",
555 "BBBB.@ ++@@.",
556 "BBBB.@ ...",
557 "BBBB.@@@@+++",
558 "BBBB..... ",
559 "BBBBBBBBBBBB",
560 "BBBBBBBBBBBB"
561 };
562 static const char * xpm_gt_rr_b[] = {
563 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
564 "BBBBBBBBBBBB",
565 "BBBBBBBBBBBB",
566 "BBBB ...",
567 "BBBB ++++@@@",
568 "BBBB +... ",
569 "BBBB +.@@++ ",
570 "BBBB +.@ .+ ",
571 "BBBB.@ +. @.",
572 "BBBB.@ ++@@.",
573 "BBBB.@ ...",
574 "BBBB.@@@@+++",
575 "BBBB..... "
576 };
577 static const char * xpm_gt_rr_bb[] = {
578 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
579 "BBBBBBBBBBBB",
580 "BBBBBBBBBBBB",
581 "BBBBBBBBBBBB",
582 "BBBBBBBBBBBB",
583 "BBBB ...",
584 "BBBB ++++@@@",
585 "BBBB +... ",
586 "BBBB +.@@++ ",
587 "BBBB +.@ .+ ",
588 "BBBB.@ +. @.",
589 "BBBB.@ ++@@.",
590 "BBBB.@ ..."
591 };
592 static const char * xpm_sm_ll_tt[] = {
593 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
594 " .+ @.BB",
595 ". @.+ BB",
596 "+@@.+ BB",
597 " ...+ BB",
598 "@++++ BB",
599 ". BB",
600 "BBBBBBBB",
601 "BBBBBBBB"
602 };
603 static const char * xpm_sm_ll_t[] = {
604 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
605 ". @.BB",
606 "@++ @.BB",
607 " .+ @.BB",
608 ". @.+ BB",
609 "+@@.+ BB",
610 " ...+ BB",
611 "@++++ BB",
612 ". BB"
613 };
614 static const char * xpm_sm_ll[] = {
615 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
616 " .....BB",
617 "+@@@@.BB",
618 ". @.BB",
619 "@++ @.BB",
620 " .+ @.BB",
621 ". @.+ BB",
622 "+@@.+ BB",
623 " ...+ BB"
624 };
625 static const char * xpm_sm_ll_b[] = {
626 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
627 "BBBBBBBB",
628 "BBBBBBBB",
629 " .....BB",
630 "+@@@@.BB",
631 ". @.BB",
632 "@++ @.BB",
633 " .+ @.BB",
634 ". @.+ BB"
635 };
636 static const char * xpm_sm_l_tt[] = {
637 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
638 ".@ .+ @.",
639 " +. @.+ ",
640 " ++@@.+ ",
641 " ...+ ",
642 "@@@++++ ",
643 "... ",
644 "BBBBBBBB",
645 "BBBBBBBB"
646 };
647 static const char * xpm_sm_l_t[] = {
648 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
649 "... @.",
650 ".@@++ @.",
651 ".@ .+ @.",
652 " +. @.+ ",
653 " ++@@.+ ",
654 " ...+ ",
655 "@@@++++ ",
656 "... "
657 };
658 static const char * xpm_sm_l[] = {
659 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
660 " .....",
661 "+++@@@@.",
662 "... @.",
663 ".@@++ @.",
664 ".@ .+ @.",
665 " +. @.+ ",
666 " ++@@.+ ",
667 " ...+ "
668 };
669 static const char * xpm_sm_l_b[] = {
670 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
671 "BBBBBBBB",
672 "BBBBBBBB",
673 " .....",
674 "+++@@@@.",
675 "... @.",
676 ".@@++ @.",
677 ".@ .+ @.",
678 " +. @.+ "
679 };
680 static const char * xpm_sm_tt[] = {
681 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
682 " +.@ .+ ",
683 ".@ +. @.",
684 ".@ ++@@.",
685 ".@ ...",
686 ".@@@@+++",
687 "..... ",
688 "BBBBBBBB",
689 "BBBBBBBB"
690 };
691 static const char * xpm_sm_t[] = {
692 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
693 " +... ",
694 " +.@@++ ",
695 " +.@ .+ ",
696 ".@ +. @.",
697 ".@ ++@@.",
698 ".@ ...",
699 ".@@@@+++",
700 "..... "
701 };
702 static const char * xpm_sm_b[] = {
703 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
704 "BBBBBBBB",
705 "BBBBBBBB",
706 " ...",
707 " ++++@@@",
708 " +... ",
709 " +.@@++ ",
710 " +.@ .+ ",
711 ".@ +. @."
712 };
713 static const char * xpm_sm_r_tt[] = {
714 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
715 "BB +.@ .",
716 "BB.@ +. ",
717 "BB.@ ++@",
718 "BB.@ .",
719 "BB.@@@@+",
720 "BB..... ",
721 "BBBBBBBB",
722 "BBBBBBBB"
723 };
724 static const char * xpm_sm_r_t[] = {
725 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
726 "BB +... ",
727 "BB +.@@+",
728 "BB +.@ .",
729 "BB.@ +. ",
730 "BB.@ ++@",
731 "BB.@ .",
732 "BB.@@@@+",
733 "BB..... "
734 };
735 static const char * xpm_sm_r[] = {
736 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
737 "BB .",
738 "BB ++++@",
739 "BB +... ",
740 "BB +.@@+",
741 "BB +.@ .",
742 "BB.@ +. ",
743 "BB.@ ++@",
744 "BB.@ ."
745 };
746 static const char * xpm_sm_r_b[] = {
747 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
748 "BBBBBBBB",
749 "BBBBBBBB",
750 "BB .",
751 "BB ++++@",
752 "BB +... ",
753 "BB +.@@+",
754 "BB +.@ .",
755 "BB.@ +. "
756 };
757
758 // this table defines all tests
759 struct SizeTestData
760 {
761 int w, h, dx, dy; // first parameters for Size()
762 const char **ref_xpm; // expected result
763 } sizeTestData[] =
764 {
765 { 10, 10, 0, 0, xpm_orig}, // same size, same position
766 { 12, 12, 0, 0, xpm_gt}, // target larger, same position
767 { 8, 8, 0, 0, xpm_sm}, // target smaller, same position
768 { 10, 10, -2, -2, xpm_l_t}, // same size, move left up
769 { 10, 10, -2, 0, xpm_l}, // same size, move left
770 { 10, 10, -2, 2, xpm_l_b}, // same size, move left down
771 { 10, 10, 0, -2, xpm_t}, // same size, move up
772 { 10, 10, 0, 2, xpm_b}, // same size, move down
773 { 10, 10, 2, -2, xpm_r_t}, // same size, move right up
774 { 10, 10, 2, 0, xpm_r}, // same size, move right
775 { 10, 10, 2, 2, xpm_r_b}, // same size, move right down
776 { 12, 12, -2, -2, xpm_gt_l_t}, // target larger, move left up
777 { 12, 12, -2, 0, xpm_gt_l}, // target larger, move left
778 { 12, 12, -2, 2, xpm_gt_l_b}, // target larger, move left down
779 { 12, 12, -2, 4, xpm_gt_l_bb}, // target larger, move left down
780 { 12, 12, 0, -2, xpm_gt_t}, // target larger, move up
781 { 12, 12, 0, 2, xpm_gt_b}, // target larger, move down
782 { 12, 12, 0, 4, xpm_gt_bb}, // target larger, move down
783 { 12, 12, 2, -2, xpm_gt_r_t}, // target larger, move right up
784 { 12, 12, 2, 0, xpm_gt_r}, // target larger, move right
785 { 12, 12, 2, 2, xpm_gt_r_b}, // target larger, move right down
786 { 12, 12, 2, 4, xpm_gt_r_bb}, // target larger, move right down
787 { 12, 12, 4, -2, xpm_gt_rr_t}, // target larger, move right up
788 { 12, 12, 4, 0, xpm_gt_rr}, // target larger, move right
789 { 12, 12, 4, 2, xpm_gt_rr_b}, // target larger, move right down
790 { 12, 12, 4, 4, xpm_gt_rr_bb}, // target larger, move right down
791 { 8, 8, -4, -4, xpm_sm_ll_tt}, // target smaller, move left up
792 { 8, 8, -4, -2, xpm_sm_ll_t}, // target smaller, move left up
793 { 8, 8, -4, 0, xpm_sm_ll}, // target smaller, move left
794 { 8, 8, -4, 2, xpm_sm_ll_b}, // target smaller, move left down
795 { 8, 8, -2, -4, xpm_sm_l_tt}, // target smaller, move left up
796 { 8, 8, -2, -2, xpm_sm_l_t}, // target smaller, move left up
797 { 8, 8, -2, 0, xpm_sm_l}, // target smaller, move left
798 { 8, 8, -2, 2, xpm_sm_l_b}, // target smaller, move left down
799 { 8, 8, 0, -4, xpm_sm_tt}, // target smaller, move up
800 { 8, 8, 0, -2, xpm_sm_t}, // target smaller, move up
801 { 8, 8, 0, 2, xpm_sm_b}, // target smaller, move down
802 { 8, 8, 2, -4, xpm_sm_r_tt}, // target smaller, move right up
803 { 8, 8, 2, -2, xpm_sm_r_t}, // target smaller, move right up
804 { 8, 8, 2, 0, xpm_sm_r}, // target smaller, move right
805 { 8, 8, 2, 2, xpm_sm_r_b}, // target smaller, move right down
806 };
807
808 const wxImage src_img(xpm_orig);
809 for ( unsigned i = 0; i < WXSIZEOF(sizeTestData); i++ )
810 {
811 SizeTestData& st = sizeTestData[i];
812 wxImage
813 actual(src_img.Size(wxSize(st.w, st.h), wxPoint(st.dx, st.dy), 0, 0, 0)),
814 expected(st.ref_xpm);
815
816 // to check results with an image viewer uncomment this:
817 //actual.SaveFile(wxString::Format("imagetest-%02d-actual.png", i), wxBITMAP_TYPE_PNG);
818 //expected.SaveFile(wxString::Format("imagetest-%02d-exp.png", i), wxBITMAP_TYPE_PNG);
819
820 CPPUNIT_ASSERT_EQUAL( actual.GetSize().x, expected.GetSize().x );
821 CPPUNIT_ASSERT_EQUAL( actual.GetSize().y, expected.GetSize().y );
822
823 const unsigned data_len = 3 * expected.GetHeight() * expected.GetWidth();
824
825 WX_ASSERT_MESSAGE
826 (
827 ("Resize test #%u: (%d, %d), (%d, %d)", i, st.w, st.h, st.dx, st.dy),
828 memcmp(actual.GetData(), expected.GetData(), data_len) == 0
829 );
830 }
831 }
832
833 void ImageTestCase::CompareLoadedImage()
834 {
835 wxImage expected8("horse.xpm");
836 CPPUNIT_ASSERT( expected8.IsOk() );
837
838 wxImage expected24("horse.png");
839 CPPUNIT_ASSERT( expected24.IsOk() );
840
841 const size_t dataLen = expected8.GetWidth() * expected8.GetHeight() * 3;
842
843 for (size_t i=0; i<WXSIZEOF(g_testfiles); i++)
844 {
845 if ( !(g_testfiles[i].bitDepth == 8 || g_testfiles[i].bitDepth == 24)
846 || g_testfiles[i].type == wxBITMAP_TYPE_JPEG /*skip lossy JPEG*/)
847 {
848 continue;
849 }
850
851 wxImage actual(g_testfiles[i].file);
852
853 if ( actual.GetSize() != expected8.GetSize() )
854 {
855 continue;
856 }
857
858
859 WX_ASSERT_MESSAGE
860 (
861 ("Compare test '%s' for loading failed", g_testfiles[i].file),
862
863 memcmp(actual.GetData(),
864 (g_testfiles[i].bitDepth == 8)
865 ? expected8.GetData()
866 : expected24.GetData(),
867 dataLen) == 0
868 );
869 }
870
871 }
872
873 static
874 void CompareImage(const wxImageHandler& handler, const wxImage& expected)
875 {
876 bool testAlpha = expected.HasAlpha();
877 wxBitmapType type = handler.GetType();
878 if (testAlpha
879 && !(type == wxBITMAP_TYPE_PNG || type == wxBITMAP_TYPE_TGA) )
880 {
881 // don't test images with alpha if this handler doesn't support alpha
882 return;
883 }
884
885 if (type == wxBITMAP_TYPE_JPEG /* skip lossy JPEG */
886 || type == wxBITMAP_TYPE_TIF)
887 {
888 /*
889 TIFF is skipped because the memory stream can't be loaded. Libtiff
890 looks for a TIFF directory at offset 120008 while the memory
891 stream size is only 120008 bytes (when saving as a file
892 the file size is 120280 bytes).
893 */
894 return;
895 }
896
897 wxMemoryOutputStream memOut;
898 if ( !expected.SaveFile(memOut, type) )
899 {
900 // Unfortunately we can't know if the handler just doesn't support
901 // saving images, or if it failed to save.
902 return;
903 }
904
905 wxMemoryInputStream memIn(memOut);
906 CPPUNIT_ASSERT(memIn.IsOk());
907
908 wxImage actual(memIn);
909 CPPUNIT_ASSERT(actual.IsOk());
910
911 CPPUNIT_ASSERT( actual.GetSize() == expected.GetSize() );
912
913 WX_ASSERT_MESSAGE
914 (
915 ("Compare test '%s' for saving failed", handler.GetExtension()),
916
917 memcmp(actual.GetData(), expected.GetData(),
918 expected.GetWidth() * expected.GetHeight() * 3) == 0
919 );
920
921 if (!testAlpha)
922 {
923 return;
924 }
925
926
927 CPPUNIT_ASSERT( actual.HasAlpha() );
928
929 WX_ASSERT_MESSAGE
930 (
931 ("Compare alpha test '%s' for saving failed", handler.GetExtension()),
932
933 memcmp(actual.GetAlpha(), expected.GetAlpha(),
934 expected.GetWidth() * expected.GetHeight()) == 0
935 );
936 }
937
938 void ImageTestCase::CompareSavedImage()
939 {
940 wxImage expected24("horse.png");
941 CPPUNIT_ASSERT( expected24.IsOk() );
942 CPPUNIT_ASSERT( !expected24.HasAlpha() );
943
944 // Create an image with alpha based on the loaded image
945 wxImage expected32(expected24);
946 expected32.SetAlpha();
947
948 int width = expected32.GetWidth();
949 int height = expected32.GetHeight();
950 for (int y = 0; y < height; ++y)
951 {
952 for (int x = 0; x < width; ++x)
953 {
954 expected32.SetAlpha(x, y, (x*y) & wxIMAGE_ALPHA_OPAQUE);
955 }
956 }
957
958 const wxList& list = wxImage::GetHandlers();
959 for ( wxList::compatibility_iterator node = list.GetFirst();
960 node; node = node->GetNext() )
961 {
962 wxImageHandler *handler = (wxImageHandler *) node->GetData();
963
964 CompareImage(*handler, expected24);
965 CompareImage(*handler, expected32);
966 }
967 }
968
969 #endif //wxUSE_IMAGE
970
971
972 /*
973 TODO: add lots of more tests to wxImage functions
974 */