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