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