1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/image/image.cpp
3 // Purpose: Test wxImage
4 // Author: Francesco Montorsi
7 // Copyright: (c) 2009 Francesco Montorsi
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ----------------------------------------------------------------------------
13 // ----------------------------------------------------------------------------
27 #include "wx/palette.h"
30 #include "wx/mstream.h"
31 #include "wx/zstream.h"
32 #include "wx/wfstream.h"
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 }
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 class ImageTestCase
: public CppUnit::TestCase
66 CPPUNIT_TEST_SUITE( ImageTestCase
);
67 CPPUNIT_TEST( LoadFromSocketStream
);
68 CPPUNIT_TEST( LoadFromZipStream
);
69 CPPUNIT_TEST( LoadFromFile
);
70 CPPUNIT_TEST( SizeImage
);
71 CPPUNIT_TEST( CompareLoadedImage
);
72 CPPUNIT_TEST( CompareSavedImage
);
73 CPPUNIT_TEST_SUITE_END();
75 void LoadFromSocketStream();
76 void LoadFromZipStream();
79 void CompareLoadedImage();
80 void CompareSavedImage();
82 DECLARE_NO_COPY_CLASS(ImageTestCase
)
85 CPPUNIT_TEST_SUITE_REGISTRATION( ImageTestCase
);
86 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ImageTestCase
, "ImageTestCase" );
88 ImageTestCase::ImageTestCase()
90 wxSocketBase::Initialize();
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
);
107 ImageTestCase::~ImageTestCase()
109 wxSocketBase::Shutdown();
112 void ImageTestCase::LoadFromFile()
115 for (unsigned int i
=0; i
<WXSIZEOF(g_testfiles
); i
++)
116 CPPUNIT_ASSERT(img
.LoadFile(g_testfiles
[i
].file
));
119 void ImageTestCase::LoadFromSocketStream()
121 if (!IsNetworkAvailable()) // implemented in test.cpp
123 wxLogWarning("No network connectivity; skipping the "
124 "ImageTestCase::LoadFromSocketStream test unit.");
133 { "http://www.wxwidgets.org/logo9.jpg", wxBITMAP_TYPE_JPEG
},
134 { "http://www.wxwidgets.org/favicon.ico", wxBITMAP_TYPE_ICO
}
137 for (unsigned int i
=0; i
<WXSIZEOF(testData
); i
++)
139 wxURL
url(testData
[i
].url
);
140 WX_ASSERT_EQUAL_MESSAGE
142 ("Constructing URL \"%s\" failed.", testData
[i
].url
),
147 wxInputStream
*in_stream
= url
.GetInputStream();
150 ("Opening URL \"%s\" failed.", testData
[i
].url
),
151 in_stream
&& in_stream
->IsOk()
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!
161 ("Loading image from \"%s\" failed.", testData
[i
].url
),
162 img
.LoadFile(*in_stream
, testData
[i
].type
)
169 void ImageTestCase::LoadFromZipStream()
171 for (unsigned int i
=0; i
<WXSIZEOF(g_testfiles
); i
++)
173 switch (g_testfiles
[i
].type
)
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
187 // compress the test file on the fly:
188 wxMemoryOutputStream memOut
;
190 wxFileInputStream
file(g_testfiles
[i
].file
);
191 CPPUNIT_ASSERT(file
.IsOk());
193 wxZlibOutputStream
compressFilter(memOut
, 5, wxZLIB_GZIP
);
194 CPPUNIT_ASSERT(compressFilter
.IsOk());
196 file
.Read(compressFilter
);
197 CPPUNIT_ASSERT(file
.GetLastError() == wxSTREAM_EOF
);
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());
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
));
217 void ImageTestCase::SizeImage()
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.
224 static const char * xpm_orig
[] = {
225 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
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",
251 static const char * xpm_t
[] = {
252 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
264 static const char * xpm_r_t
[] = {
265 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
277 static const char * xpm_l
[] = {
278 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
290 static const char * xpm_r
[] = {
291 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
303 static const char * xpm_l_b
[] = {
304 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
316 static const char * xpm_b
[] = {
317 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
329 static const char * xpm_r_b
[] = {
330 "10 10 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
342 static const char * xpm_sm
[] = {
343 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
353 static const char * xpm_gt
[] = {
354 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
368 static const char * xpm_gt_l_t
[] = {
369 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
383 static const char * xpm_gt_l
[] = {
384 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
398 static const char * xpm_gt_l_b
[] = {
399 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
413 static const char * xpm_gt_l_bb
[] = {
414 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
428 static const char * xpm_gt_t
[] = {
429 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
443 static const char * xpm_gt_b
[] = {
444 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
458 static const char * xpm_gt_bb
[] = {
459 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
473 static const char * xpm_gt_r_t
[] = {
474 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
488 static const char * xpm_gt_r
[] = {
489 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
503 static const char * xpm_gt_r_b
[] = {
504 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
518 static const char * xpm_gt_r_bb
[] = {
519 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
533 static const char * xpm_gt_rr_t
[] = {
534 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
548 static const char * xpm_gt_rr
[] = {
549 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
563 static const char * xpm_gt_rr_b
[] = {
564 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
578 static const char * xpm_gt_rr_bb
[] = {
579 "12 12 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
593 static const char * xpm_sm_ll_tt
[] = {
594 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
604 static const char * xpm_sm_ll_t
[] = {
605 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
615 static const char * xpm_sm_ll
[] = {
616 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
626 static const char * xpm_sm_ll_b
[] = {
627 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
637 static const char * xpm_sm_l_tt
[] = {
638 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
648 static const char * xpm_sm_l_t
[] = {
649 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
659 static const char * xpm_sm_l
[] = {
660 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
670 static const char * xpm_sm_l_b
[] = {
671 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
681 static const char * xpm_sm_tt
[] = {
682 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
692 static const char * xpm_sm_t
[] = {
693 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
703 static const char * xpm_sm_b
[] = {
704 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
714 static const char * xpm_sm_r_tt
[] = {
715 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
725 static const char * xpm_sm_r_t
[] = {
726 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
736 static const char * xpm_sm_r
[] = {
737 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
747 static const char * xpm_sm_r_b
[] = {
748 "8 8 5 1", "B c Black", " c #00ff00", ". c #0000ff", "+ c #7f7f7f", "@ c #FF0000",
759 // this table defines all tests
762 int w
, h
, dx
, dy
; // first parameters for Size()
763 const char **ref_xpm
; // expected result
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
809 const wxImage
src_img(xpm_orig
);
810 for ( unsigned i
= 0; i
< WXSIZEOF(sizeTestData
); i
++ )
812 SizeTestData
& st
= sizeTestData
[i
];
814 actual(src_img
.Size(wxSize(st
.w
, st
.h
), wxPoint(st
.dx
, st
.dy
), 0, 0, 0)),
815 expected(st
.ref_xpm
);
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);
821 CPPUNIT_ASSERT_EQUAL( actual
.GetSize().x
, expected
.GetSize().x
);
822 CPPUNIT_ASSERT_EQUAL( actual
.GetSize().y
, expected
.GetSize().y
);
824 const unsigned data_len
= 3 * expected
.GetHeight() * expected
.GetWidth();
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
834 void ImageTestCase::CompareLoadedImage()
836 wxImage
expected8("horse.xpm");
837 CPPUNIT_ASSERT( expected8
.IsOk() );
839 wxImage
expected24("horse.png");
840 CPPUNIT_ASSERT( expected24
.IsOk() );
842 const size_t dataLen
= expected8
.GetWidth() * expected8
.GetHeight() * 3;
844 for (size_t i
=0; i
<WXSIZEOF(g_testfiles
); i
++)
846 if ( !(g_testfiles
[i
].bitDepth
== 8 || g_testfiles
[i
].bitDepth
== 24)
847 || g_testfiles
[i
].type
== wxBITMAP_TYPE_JPEG
/*skip lossy JPEG*/)
852 wxImage
actual(g_testfiles
[i
].file
);
854 if ( actual
.GetSize() != expected8
.GetSize() )
862 ("Compare test '%s' for loading failed", g_testfiles
[i
].file
),
864 memcmp(actual
.GetData(),
865 (g_testfiles
[i
].bitDepth
== 8)
866 ? expected8
.GetData()
867 : expected24
.GetData(),
876 wxIMAGE_HAVE_ALPHA
= (1 << 0),
877 wxIMAGE_HAVE_PALETTE
= (1 << 1)
881 void CompareImage(const wxImageHandler
& handler
, const wxImage
& image
,
882 int properties
= 0, const wxImage
*compareTo
= NULL
)
884 wxBitmapType type
= handler
.GetType();
886 const bool testPalette
= (properties
& wxIMAGE_HAVE_PALETTE
) != 0;
888 This is getting messy and should probably be transformed into a table
889 with image format features before it gets hairier.
892 && ( !(type
== wxBITMAP_TYPE_BMP
893 || type
== wxBITMAP_TYPE_GIF
894 || type
== wxBITMAP_TYPE_PNG
)
895 || type
== wxBITMAP_TYPE_XPM
) )
900 const bool testAlpha
= (properties
& wxIMAGE_HAVE_ALPHA
) != 0;
902 && !(type
== wxBITMAP_TYPE_PNG
|| type
== wxBITMAP_TYPE_TGA
) )
904 // don't test images with alpha if this handler doesn't support alpha
908 if (type
== wxBITMAP_TYPE_JPEG
/* skip lossy JPEG */
909 || type
== wxBITMAP_TYPE_TIF
)
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).
920 wxMemoryOutputStream memOut
;
921 if ( !image
.SaveFile(memOut
, type
) )
923 // Unfortunately we can't know if the handler just doesn't support
924 // saving images, or if it failed to save.
928 wxMemoryInputStream
memIn(memOut
);
929 CPPUNIT_ASSERT(memIn
.IsOk());
931 wxImage
actual(memIn
);
932 CPPUNIT_ASSERT(actual
.IsOk());
934 const wxImage
*expected
= compareTo
? compareTo
: &image
;
935 CPPUNIT_ASSERT( actual
.GetSize() == expected
->GetSize() );
937 unsigned bitsPerPixel
= testPalette
? 8 : (testAlpha
? 32 : 24);
940 ("Compare test '%s (%d-bit)' for saving failed",
941 handler
.GetExtension(), bitsPerPixel
),
943 memcmp(actual
.GetData(), expected
->GetData(),
944 expected
->GetWidth() * expected
->GetHeight() * 3) == 0
948 CPPUNIT_ASSERT(actual
.HasPalette()
949 == (testPalette
|| type
== wxBITMAP_TYPE_XPM
));
952 CPPUNIT_ASSERT( actual
.HasAlpha() == testAlpha
);
961 ("Compare alpha test '%s' for saving failed", handler
.GetExtension()),
963 memcmp(actual
.GetAlpha(), expected
->GetAlpha(),
964 expected
->GetWidth() * expected
->GetHeight()) == 0
968 void ImageTestCase::CompareSavedImage()
970 wxImage
expected24("horse.png");
971 CPPUNIT_ASSERT( expected24
.IsOk() );
972 CPPUNIT_ASSERT( !expected24
.HasAlpha() );
974 unsigned long numColours
= expected24
.CountColours();
975 wxImage expected8
= expected24
.ConvertToGreyscale();
976 numColours
= expected8
.CountColours();
978 unsigned char greys
[256];
979 for (size_t i
= 0; i
< 256; ++i
)
983 wxPalette
palette(256, greys
, greys
, greys
);
984 expected8
.SetPalette(palette
);
985 expected8
.SetOption(wxIMAGE_OPTION_BMP_FORMAT
, wxBMP_8BPP_PALETTE
);
987 // Create an image with alpha based on the loaded image
988 wxImage
expected32(expected24
);
989 expected32
.SetAlpha();
991 int width
= expected32
.GetWidth();
992 int height
= expected32
.GetHeight();
993 for (int y
= 0; y
< height
; ++y
)
995 for (int x
= 0; x
< width
; ++x
)
997 expected32
.SetAlpha(x
, y
, (x
*y
) & wxIMAGE_ALPHA_OPAQUE
);
1001 const wxList
& list
= wxImage::GetHandlers();
1002 for ( wxList::compatibility_iterator node
= list
.GetFirst();
1003 node
; node
= node
->GetNext() )
1005 wxImageHandler
*handler
= (wxImageHandler
*) node
->GetData();
1008 CompareImage(*handler
, expected8
, wxIMAGE_HAVE_PALETTE
);
1010 CompareImage(*handler
, expected24
);
1011 CompareImage(*handler
, expected32
, wxIMAGE_HAVE_ALPHA
);
1015 expected8
.LoadFile("horse.gif");
1016 CPPUNIT_ASSERT( expected8
.IsOk() );
1017 CPPUNIT_ASSERT( expected8
.HasPalette() );
1019 expected8
.SetAlpha();
1021 width
= expected8
.GetWidth();
1022 height
= expected8
.GetHeight();
1023 for (int y
= 0; y
< height
; ++y
)
1025 for (int x
= 0; x
< width
; ++x
)
1027 expected8
.SetAlpha(x
, y
, (x
*y
) & wxIMAGE_ALPHA_OPAQUE
);
1032 The image contains 256 indexed colours and needs another palette entry
1033 for storing the transparency index. This results in wanting 257 palette
1034 entries but that amount is not supported by PNG, as such this image
1035 should not contain a palette (but still have alpha) and be stored as a
1036 true colour image instead.
1038 CompareImage(*wxImage::FindHandler(wxBITMAP_TYPE_PNG
),
1039 expected8
, wxIMAGE_HAVE_ALPHA
);
1043 Now do the same test again but remove one (random) palette entry. This
1044 should result in saving the PNG with a palette.
1046 unsigned char red
[256], green
[256], blue
[256];
1047 const wxPalette
& pal
= expected8
.GetPalette();
1048 const int paletteCount
= pal
.GetColoursCount();
1049 for (int i
= 0; i
< paletteCount
; ++i
)
1051 expected8
.GetPalette().GetRGB(i
, &red
[i
], &green
[i
], &blue
[i
]);
1053 wxPalette
newPal(paletteCount
- 1, red
, green
, blue
);
1055 red
[paletteCount
-1], green
[paletteCount
-1], blue
[paletteCount
-1],
1056 red
[paletteCount
-2], green
[paletteCount
-2], blue
[paletteCount
-2]);
1058 expected8
.SetPalette(newPal
);
1060 Explicitly make known we want a palettised PNG. If we don't then this
1061 particular image gets saved as a true colour image because there's an
1062 alpha channel present and the PNG saver prefers to keep the alpha over
1063 saving as a palettised image that has alpha converted to a mask.
1065 expected8
.SetOption(wxIMAGE_OPTION_PNG_FORMAT
, wxPNG_TYPE_PALETTE
);
1067 wxImage ref8
= expected8
;
1070 Convert the alpha channel to a mask like the PNG saver does. Also convert
1071 the colour used for transparency from 1,0,0 to 2,0,0. The latter gets
1072 done by the PNG loader in search of an unused colour to use for
1073 transparency (this should be fixed).
1075 ref8
.ConvertAlphaToMask();
1076 ref8
.Replace(1, 0, 0, 2, 0, 0);
1078 CompareImage(*wxImage::FindHandler(wxBITMAP_TYPE_PNG
),
1079 expected8
, wxIMAGE_HAVE_PALETTE
, &ref8
);
1083 #endif //wxUSE_IMAGE
1087 TODO: add lots of more tests to wxImage functions