72794f16bc39ce3349806ce109bbd0053b39d5e1
[reactos.git] / rostests / apitests / atl / CImage.cpp
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for CImage
5 * PROGRAMMER: Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 */
7
8 #include <atlimage.h>
9 #include "resource.h"
10
11 #ifdef _MSC_VER
12 #pragma comment(lib, "rpcrt4.lib")
13 #endif
14
15 #ifdef __REACTOS__
16 #include <apitest.h>
17 #else
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <stdarg.h>
21 int g_tests_executed = 0;
22 int g_tests_failed = 0;
23 void ok_func(const char *file, int line, BOOL value, const char *fmt, ...)
24 {
25 va_list va;
26 va_start(va, fmt);
27 if (!value)
28 {
29 printf("%s (%d): ", file, line);
30 vprintf(fmt, va);
31 g_tests_failed++;
32 }
33 g_tests_executed++;
34 va_end(va);
35 }
36 #undef ok
37 #define ok(value, ...) ok_func(__FILE__, __LINE__, value, __VA_ARGS__)
38 #define START_TEST(x) int main(void)
39 #endif
40
41 bool IsGuidEqual(const GUID& guid1, const GUID& guid2)
42 {
43 RPC_STATUS status;
44 if (::UuidEqual(const_cast<GUID *>(&guid1),
45 const_cast<GUID *>(&guid2), &status))
46 {
47 if (status == RPC_S_OK)
48 return true;
49 }
50 return false;
51 }
52
53 const TCHAR* szFiles[] = {
54 TEXT("ant.png"),
55 TEXT("ant.tif"),
56 TEXT("ant.gif"),
57 TEXT("ant.jpg"),
58 TEXT("ant.bmp"),
59 };
60
61 static TCHAR szTempPath[MAX_PATH];
62 TCHAR* file_name(const TCHAR* file)
63 {
64 static TCHAR buffer[MAX_PATH];
65 lstrcpy(buffer, szTempPath);
66 lstrcat(buffer, TEXT("\\"));
67 lstrcat(buffer, file);
68 return buffer;
69 }
70
71 static void write_bitmap(HINSTANCE hInst, int id, TCHAR* file)
72 {
73 HRSRC rsrc;
74
75 rsrc = FindResource(hInst, MAKEINTRESOURCE(id), RT_BITMAP);
76 ok(rsrc != NULL, "Expected to find an image resource\n");
77 if (rsrc)
78 {
79 void *rsrc_data;
80 HANDLE hfile;
81 BOOL ret;
82 HGLOBAL glob = LoadResource(hInst, rsrc);
83 DWORD rsrc_size = SizeofResource(hInst, rsrc);
84
85 rsrc_data = LockResource(glob);
86
87 hfile = CreateFile(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
88 ok(hfile != INVALID_HANDLE_VALUE, "Unable to open temp file: %lu\n", GetLastError());
89 if (hfile != INVALID_HANDLE_VALUE)
90 {
91 BITMAPFILEHEADER bfh = { 0 };
92 DWORD dwWritten;
93
94 bfh.bfType = 'MB';
95 bfh.bfSize = rsrc_size + sizeof(BITMAPFILEHEADER);
96 bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
97 bfh.bfReserved1 = bfh.bfReserved2 = 0;
98 ret = WriteFile(hfile, &bfh, sizeof(bfh), &dwWritten, NULL);
99 ok(ret, "Unable to write temp file: %lu\n", GetLastError());
100 ret = WriteFile(hfile, rsrc_data, rsrc_size, &dwWritten, NULL);
101 ok(ret, "Unable to write temp file: %lu\n", GetLastError());
102 CloseHandle(hfile);
103 }
104 UnlockResource(rsrc_data);
105 }
106 }
107
108 typedef Gdiplus::GpStatus (WINAPI *STARTUP)(ULONG_PTR *, const Gdiplus::GdiplusStartupInput *, Gdiplus::GdiplusStartupOutput *);
109 typedef void (WINAPI *SHUTDOWN)(ULONG_PTR);
110 typedef Gdiplus::GpStatus (WINGDIPAPI *CREATEBITMAPFROMFILE)(GDIPCONST WCHAR*, Gdiplus::GpBitmap **);
111 typedef Gdiplus::GpStatus (WINGDIPAPI *GETPIXELFORMAT)(Gdiplus::GpImage *image, Gdiplus::PixelFormat *format);
112 typedef Gdiplus::GpStatus (WINGDIPAPI *DISPOSEIMAGE)(Gdiplus::GpImage *);
113
114 static HINSTANCE hinstGdiPlus;
115 static ULONG_PTR gdiplusToken;
116
117 static STARTUP Startup;
118 static SHUTDOWN Shutdown;
119 static CREATEBITMAPFROMFILE CreateBitmapFromFile;
120 static GETPIXELFORMAT GetImagePixelFormat;
121 static DISPOSEIMAGE DisposeImage;
122
123 template <typename TYPE>
124 TYPE AddrOf(const char *name)
125 {
126 FARPROC proc = ::GetProcAddress(hinstGdiPlus, name);
127 return reinterpret_cast<TYPE>(proc);
128 }
129
130 static void init_gdip()
131 {
132 hinstGdiPlus = ::LoadLibraryA("gdiplus.dll");
133 Startup = AddrOf<STARTUP>("GdiplusStartup");
134 Shutdown = AddrOf<SHUTDOWN>("GdiplusShutdown");
135 CreateBitmapFromFile = AddrOf<CREATEBITMAPFROMFILE>("GdipCreateBitmapFromFile");
136 GetImagePixelFormat = AddrOf<GETPIXELFORMAT>("GdipGetImagePixelFormat");
137 DisposeImage = AddrOf<DISPOSEIMAGE>("GdipDisposeImage");
138 }
139
140
141 static void determine_file_bpp(TCHAR* tfile, Gdiplus::PixelFormat expect_pf)
142 {
143 using namespace Gdiplus;
144 GpBitmap *pBitmap = NULL;
145
146 #ifdef UNICODE
147 WCHAR* file = tfile;
148 #else
149 WCHAR file[MAX_PATH];
150 ::MultiByteToWideChar(CP_ACP, 0, tfile, -1, file, MAX_PATH);
151 #endif
152
153 if (Startup == NULL)
154 init_gdip();
155
156 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
157 Startup(&gdiplusToken, &gdiplusStartupInput, NULL);
158
159
160 Gdiplus::GpStatus status = CreateBitmapFromFile(file, &pBitmap);
161 ok(status == Gdiplus::Ok, "Expected status to be %i, was: %i\n", (int)Gdiplus::Ok, (int)status);
162 ok(pBitmap != NULL, "Expected a valid bitmap\n");
163 if (pBitmap)
164 {
165 PixelFormat pf;
166 GetImagePixelFormat(pBitmap, &pf);
167 ok(pf == expect_pf, "Expected PixelFormat to be 0x%x, was: 0x%x\n", (int)expect_pf, (int)pf);
168
169 DisposeImage(pBitmap);
170 }
171 Shutdown(gdiplusToken);
172 }
173
174
175 START_TEST(CImage)
176 {
177 HRESULT hr;
178 TCHAR* file;
179 BOOL bOK;
180 int width, height, bpp;
181 size_t n;
182 CImage image1, image2;
183 COLORREF color;
184 HDC hDC;
185
186 #if 0
187 width = image1.GetWidth();
188 height = image1.GetHeight();
189 bpp = image1.GetBPP();
190 #endif
191
192 HINSTANCE hInst = GetModuleHandle(NULL);
193 GetTempPath(MAX_PATH, szTempPath);
194
195 image1.LoadFromResource(hInst, IDB_ANT);
196 ok(!image1.IsNull(), "Expected image1 is not null\n");
197
198 width = image1.GetWidth();
199 ok(width == 48, "Expected width to be 48, was: %d\n", width);
200 height = image1.GetHeight();
201 ok(height == 48, "Expected height to be 48, was: %d\n", height);
202 bpp = image1.GetBPP();
203 ok(bpp == 8, "Expected bpp to be 8, was: %d\n", bpp);
204
205
206 image2.LoadFromResource(hInst, IDB_CROSS);
207 ok(!image2.IsNull(), "Expected image2 is not null\n");
208 image2.SetTransparentColor(RGB(255, 255, 255));
209
210 width = image2.GetWidth();
211 ok(width == 32, "Expected width to be 32, was: %d\n", width);
212 height = image2.GetHeight();
213 ok(height == 32, "Expected height to be 32, was: %d\n", height);
214 bpp = image2.GetBPP();
215 ok(bpp == 8, "Expected bpp to be 8, was: %d\n", bpp);
216
217 color = image1.GetPixel(5, 5);
218 ok(color == RGB(166, 202, 240), "Expected color to be 166, 202, 240; was: %i, %i, %i\n", GetRValue(color), GetGValue(color), GetBValue(color));
219
220 hDC = image1.GetDC();
221 bOK = image2.Draw(hDC, 0, 0);
222 image1.ReleaseDC();
223 ok(bOK != FALSE, "Expected bDraw to be TRUE, was: %d\n", bOK);
224 image2.Destroy();
225
226 color = image1.GetPixel(5, 5);
227 ok(color == RGB(255, 0,0), "Expected color to be 255, 0, 0; was: %i, %i, %i\n", GetRValue(color), GetGValue(color), GetBValue(color));
228
229 file = file_name(TEXT("ant.bmp"));
230 write_bitmap(hInst, IDB_ANT, file);
231
232 init_gdip();
233
234 determine_file_bpp(file, PixelFormat8bppIndexed);
235
236 hr = image2.Load(file);
237 ok(hr == S_OK, "Expected hr to be S_OK, was: %08lx\n", hr);
238 ok(!image2.IsNull(), "Expected image1 is not null\n");
239 bOK = DeleteFile(file);
240 ok(bOK, "Expected bOK to be TRUE, was: %d\n", bOK);
241
242 width = image2.GetWidth();
243 ok(width == 48, "Expected width to be 48, was: %d\n", width);
244 height = image2.GetHeight();
245 ok(height == 48, "Expected height to be 48, was: %d\n", height);
246 bpp = image2.GetBPP();
247 ok(bpp == 8, "Expected bpp to be 8, was: %d\n", bpp);
248
249 for (n = 0; n < _countof(szFiles); ++n)
250 {
251 file = file_name(szFiles[n]);
252 image2.Destroy();
253
254 if (n == 0)
255 hr = image1.Save(file, Gdiplus::ImageFormatPNG);
256 else
257 hr = image1.Save(file);
258 ok(hr == S_OK, "Expected hr to be S_OK, was: %08lx (for %i)\n", hr, n);
259
260 bOK = (GetFileAttributes(file) != 0xFFFFFFFF);
261 ok(bOK, "Expected bOK to be TRUE, was: %d (for %i)\n", bOK, n);
262
263 hr = image2.Load(file);
264 ok(hr == S_OK, "Expected hr to be S_OK, was: %08lx (for %i)\n", hr, n);
265
266 width = image2.GetWidth();
267 ok(width == 48, "Expected width to be 48, was: %d (for %i)\n", width, n);
268 height = image2.GetHeight();
269 ok(height == 48, "Expected height to be 48, was: %d (for %i)\n", height, n);
270 bpp = image2.GetBPP();
271 if (n == 3)
272 {
273 ok(bpp == 24, "Expected bpp to be 24, was: %d (for %i)\n", bpp, n);
274 determine_file_bpp(file, PixelFormat24bppRGB);
275 }
276 else
277 {
278 ok(bpp == 8, "Expected bpp to be 8, was: %d (for %i)\n", bpp, n);
279 determine_file_bpp(file, PixelFormat8bppIndexed);
280 }
281 color = image1.GetPixel(5, 5);
282 ok(color == RGB(255, 0,0), "Expected color to be 255, 0, 0; was: %i, %i, %i (for %i)\n", GetRValue(color), GetGValue(color), GetBValue(color), n);
283
284 bOK = DeleteFile(file);
285 ok(bOK, "Expected bOK to be TRUE, was: %d (for %i)\n", bOK, n);
286 }
287
288 ATL::IAtlStringMgr *mgr = CAtlStringMgr::GetInstance();
289 CSimpleArray<GUID> aguidFileTypes;
290 #ifdef UNICODE
291 CHAR szBuff[512];
292 const WCHAR *psz;
293 #else
294 const CHAR *psz;
295 #endif
296
297 CSimpleString strImporters(mgr);
298 aguidFileTypes.RemoveAll();
299 hr = CImage::GetImporterFilterString(strImporters,
300 aguidFileTypes,
301 TEXT("All Image Files"), 0);
302 ok(hr == S_OK, "Expected hr to be S_OK, was: %ld\n", hr);
303 ok(aguidFileTypes.GetSize() == 9, "Expected aguidFileTypes.GetSize() to be 8, was %d.", aguidFileTypes.GetSize());
304 ok(IsGuidEqual(aguidFileTypes[0], GUID_NULL), "Expected aguidFileTypes[0] to be GUID_NULL.\n");
305 ok(IsGuidEqual(aguidFileTypes[1], Gdiplus::ImageFormatBMP), "Expected aguidFileTypes[1] to be Gdiplus::ImageFormatBMP.\n");
306 ok(IsGuidEqual(aguidFileTypes[2], Gdiplus::ImageFormatJPEG), "Expected aguidFileTypes[2] to be Gdiplus::ImageFormatJPEG.\n");
307 ok(IsGuidEqual(aguidFileTypes[3], Gdiplus::ImageFormatGIF), "Expected aguidFileTypes[3] to be Gdiplus::ImageFormatGIF.\n");
308 ok(IsGuidEqual(aguidFileTypes[4], Gdiplus::ImageFormatEMF), "Expected aguidFileTypes[4] to be Gdiplus::ImageFormatEMF.\n");
309 ok(IsGuidEqual(aguidFileTypes[5], Gdiplus::ImageFormatWMF), "Expected aguidFileTypes[5] to be Gdiplus::ImageFormatWMF.\n");
310 ok(IsGuidEqual(aguidFileTypes[6], Gdiplus::ImageFormatTIFF), "Expected aguidFileTypes[6] to be Gdiplus::ImageFormatTIFF.\n");
311 ok(IsGuidEqual(aguidFileTypes[7], Gdiplus::ImageFormatPNG), "Expected aguidFileTypes[7] to be Gdiplus::ImageFormatPNG.\n");
312 ok(IsGuidEqual(aguidFileTypes[8], Gdiplus::ImageFormatIcon), "Expected aguidFileTypes[8] to be Gdiplus::ImageFormatIcon.\n");
313
314 psz = strImporters.GetString();
315 #ifdef UNICODE
316 WideCharToMultiByte(CP_ACP, 0, psz, -1, szBuff, 512, NULL, NULL);
317 ok(lstrcmpA(szBuff, "All Image Files|*.BMP;*.DIB;*.RLE;*.JPG;*.JPEG;*.JPE;*.JFIF;*.GIF;*.EMF;*.WMF;*.TIF;*.TIFF;*.PNG;*.ICO|BMP (*.BMP;*.DIB;*.RLE)|*.BMP;*.DIB;*.RLE|JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)|*.JPG;*.JPEG;*.JPE;*.JFIF|GIF (*.GIF)|*.GIF|EMF (*.EMF)|*.EMF|WMF (*.WMF)|*.WMF|TIFF (*.TIF;*.TIFF)|*.TIF;*.TIFF|PNG (*.PNG)|*.PNG|ICO (*.ICO)|*.ICO||") == 0,
318 "The importer filter string is bad, was: %s\n", szBuff);
319 #else
320 ok(lstrcmpA(psz, "All Image Files|*.BMP;*.DIB;*.RLE;*.JPG;*.JPEG;*.JPE;*.JFIF;*.GIF;*.EMF;*.WMF;*.TIF;*.TIFF;*.PNG;*.ICO|BMP (*.BMP;*.DIB;*.RLE)|*.BMP;*.DIB;*.RLE|JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)|*.JPG;*.JPEG;*.JPE;*.JFIF|GIF (*.GIF)|*.GIF|EMF (*.EMF)|*.EMF|WMF (*.WMF)|*.WMF|TIFF (*.TIF;*.TIFF)|*.TIF;*.TIFF|PNG (*.PNG)|*.PNG|ICO (*.ICO)|*.ICO||") == 0,
321 "The importer filter string is bad, was: %s\n", psz);
322 #endif
323
324 CSimpleString strExporters(mgr);
325 aguidFileTypes.RemoveAll();
326 hr = CImage::GetExporterFilterString(strExporters,
327 aguidFileTypes,
328 TEXT("All Image Files"), 0);
329 ok(hr == S_OK, "Expected hr to be S_OK, was: %ld\n", hr);
330 ok(aguidFileTypes.GetSize() == 9, "Expected aguidFileTypes.GetSize() to be 8, was %d.", aguidFileTypes.GetSize());
331 ok(IsGuidEqual(aguidFileTypes[0], GUID_NULL), "Expected aguidFileTypes[0] to be GUID_NULL.\n");
332 ok(IsGuidEqual(aguidFileTypes[1], Gdiplus::ImageFormatBMP), "Expected aguidFileTypes[1] to be Gdiplus::ImageFormatBMP.\n");
333 ok(IsGuidEqual(aguidFileTypes[2], Gdiplus::ImageFormatJPEG), "Expected aguidFileTypes[2] to be Gdiplus::ImageFormatJPEG.\n");
334 ok(IsGuidEqual(aguidFileTypes[3], Gdiplus::ImageFormatGIF), "Expected aguidFileTypes[3] to be Gdiplus::ImageFormatGIF.\n");
335 ok(IsGuidEqual(aguidFileTypes[4], Gdiplus::ImageFormatEMF), "Expected aguidFileTypes[4] to be Gdiplus::ImageFormatEMF.\n");
336 ok(IsGuidEqual(aguidFileTypes[5], Gdiplus::ImageFormatWMF), "Expected aguidFileTypes[5] to be Gdiplus::ImageFormatWMF.\n");
337 ok(IsGuidEqual(aguidFileTypes[6], Gdiplus::ImageFormatTIFF), "Expected aguidFileTypes[6] to be Gdiplus::ImageFormatTIFF.\n");
338 ok(IsGuidEqual(aguidFileTypes[7], Gdiplus::ImageFormatPNG), "Expected aguidFileTypes[7] to be Gdiplus::ImageFormatPNG.\n");
339 ok(IsGuidEqual(aguidFileTypes[8], Gdiplus::ImageFormatIcon), "Expected aguidFileTypes[8] to be Gdiplus::ImageFormatIcon.\n");
340
341 psz = strExporters.GetString();
342 #ifdef UNICODE
343 WideCharToMultiByte(CP_ACP, 0, psz, -1, szBuff, 512, NULL, NULL);
344 ok(lstrcmpA(szBuff, "All Image Files|*.BMP;*.DIB;*.RLE;*.JPG;*.JPEG;*.JPE;*.JFIF;*.GIF;*.EMF;*.WMF;*.TIF;*.TIFF;*.PNG;*.ICO|BMP (*.BMP;*.DIB;*.RLE)|*.BMP;*.DIB;*.RLE|JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)|*.JPG;*.JPEG;*.JPE;*.JFIF|GIF (*.GIF)|*.GIF|EMF (*.EMF)|*.EMF|WMF (*.WMF)|*.WMF|TIFF (*.TIF;*.TIFF)|*.TIF;*.TIFF|PNG (*.PNG)|*.PNG|ICO (*.ICO)|*.ICO||") == 0,
345 "The exporter filter string is bad, was: %s\n", szBuff);
346 #else
347 ok(lstrcmpA(psz, "All Image Files|*.BMP;*.DIB;*.RLE;*.JPG;*.JPEG;*.JPE;*.JFIF;*.GIF;*.EMF;*.WMF;*.TIF;*.TIFF;*.PNG;*.ICO|BMP (*.BMP;*.DIB;*.RLE)|*.BMP;*.DIB;*.RLE|JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)|*.JPG;*.JPEG;*.JPE;*.JFIF|GIF (*.GIF)|*.GIF|EMF (*.EMF)|*.EMF|WMF (*.WMF)|*.WMF|TIFF (*.TIF;*.TIFF)|*.TIF;*.TIFF|PNG (*.PNG)|*.PNG|ICO (*.ICO)|*.ICO||") == 0,
348 "The exporter filter string is bad, was: %s\n", psz);
349 #endif
350
351 #ifndef __REACTOS__
352 printf("CImage: %i tests executed (0 marked as todo, %i failures), 0 skipped.\n", g_tests_executed, g_tests_failed);
353 return g_tests_failed;
354 #endif
355 }