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