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 HAVE_APITEST 12 #include <apitest.h> 13 #else 14 #include "atltest.h" 15 #endif 16 17 const TCHAR* szFiles[] = { 18 TEXT("ant.png"), 19 TEXT("ant.tif"), 20 TEXT("ant.gif"), 21 TEXT("ant.jpg"), 22 TEXT("ant.bmp"), 23 }; 24 25 static TCHAR szTempPath[MAX_PATH]; 26 TCHAR* file_name(const TCHAR* file) 27 { 28 static TCHAR buffer[MAX_PATH]; 29 lstrcpy(buffer, szTempPath); 30 lstrcat(buffer, TEXT("\\")); 31 lstrcat(buffer, file); 32 return buffer; 33 } 34 35 static void write_bitmap(HINSTANCE hInst, int id, TCHAR* file) 36 { 37 HRSRC rsrc; 38 39 rsrc = FindResource(hInst, MAKEINTRESOURCE(id), RT_BITMAP); 40 ok(rsrc != NULL, "Expected to find an image resource\n"); 41 if (rsrc) 42 { 43 void *rsrc_data; 44 HANDLE hfile; 45 BOOL ret; 46 HGLOBAL glob = LoadResource(hInst, rsrc); 47 DWORD rsrc_size = SizeofResource(hInst, rsrc); 48 49 rsrc_data = LockResource(glob); 50 51 hfile = CreateFile(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 52 ok(hfile != INVALID_HANDLE_VALUE, "Unable to open temp file: %lu\n", GetLastError()); 53 if (hfile != INVALID_HANDLE_VALUE) 54 { 55 BITMAPFILEHEADER bfh = { 0 }; 56 DWORD dwWritten; 57 58 bfh.bfType = 'MB'; 59 bfh.bfSize = rsrc_size + sizeof(BITMAPFILEHEADER); 60 bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 61 bfh.bfReserved1 = bfh.bfReserved2 = 0; 62 ret = WriteFile(hfile, &bfh, sizeof(bfh), &dwWritten, NULL); 63 ok(ret, "Unable to write temp file: %lu\n", GetLastError()); 64 ret = WriteFile(hfile, rsrc_data, rsrc_size, &dwWritten, NULL); 65 ok(ret, "Unable to write temp file: %lu\n", GetLastError()); 66 CloseHandle(hfile); 67 } 68 UnlockResource(rsrc_data); 69 } 70 } 71 72 typedef Gdiplus::GpStatus (WINAPI *STARTUP)(ULONG_PTR *, const Gdiplus::GdiplusStartupInput *, Gdiplus::GdiplusStartupOutput *); 73 typedef void (WINAPI *SHUTDOWN)(ULONG_PTR); 74 typedef Gdiplus::GpStatus (WINGDIPAPI *CREATEBITMAPFROMFILE)(GDIPCONST WCHAR*, Gdiplus::GpBitmap **); 75 typedef Gdiplus::GpStatus (WINGDIPAPI *GETPIXELFORMAT)(Gdiplus::GpImage *image, Gdiplus::PixelFormat *format); 76 typedef Gdiplus::GpStatus (WINGDIPAPI *DISPOSEIMAGE)(Gdiplus::GpImage *); 77 78 static HINSTANCE hinstGdiPlus; 79 static ULONG_PTR gdiplusToken; 80 81 static STARTUP Startup; 82 static SHUTDOWN Shutdown; 83 static CREATEBITMAPFROMFILE CreateBitmapFromFile; 84 static GETPIXELFORMAT GetImagePixelFormat; 85 static DISPOSEIMAGE DisposeImage; 86 87 template <typename TYPE> 88 TYPE AddrOf(const char *name) 89 { 90 FARPROC proc = ::GetProcAddress(hinstGdiPlus, name); 91 return reinterpret_cast<TYPE>(proc); 92 } 93 94 static void init_gdip() 95 { 96 hinstGdiPlus = ::LoadLibraryA("gdiplus.dll"); 97 Startup = AddrOf<STARTUP>("GdiplusStartup"); 98 Shutdown = AddrOf<SHUTDOWN>("GdiplusShutdown"); 99 CreateBitmapFromFile = AddrOf<CREATEBITMAPFROMFILE>("GdipCreateBitmapFromFile"); 100 GetImagePixelFormat = AddrOf<GETPIXELFORMAT>("GdipGetImagePixelFormat"); 101 DisposeImage = AddrOf<DISPOSEIMAGE>("GdipDisposeImage"); 102 } 103 104 static void determine_file_bpp(TCHAR* tfile, Gdiplus::PixelFormat expect_pf) 105 { 106 using namespace Gdiplus; 107 GpBitmap *pBitmap = NULL; 108 109 #ifdef UNICODE 110 WCHAR* file = tfile; 111 #else 112 WCHAR file[MAX_PATH]; 113 ::MultiByteToWideChar(CP_ACP, 0, tfile, -1, file, MAX_PATH); 114 #endif 115 116 if (Startup == NULL) 117 init_gdip(); 118 119 Gdiplus::GdiplusStartupInput gdiplusStartupInput; 120 Startup(&gdiplusToken, &gdiplusStartupInput, NULL); 121 122 123 Gdiplus::GpStatus status = CreateBitmapFromFile(file, &pBitmap); 124 ok(status == Gdiplus::Ok, "Expected status to be %i, was: %i\n", (int)Gdiplus::Ok, (int)status); 125 ok(pBitmap != NULL, "Expected a valid bitmap\n"); 126 if (pBitmap) 127 { 128 PixelFormat pf; 129 GetImagePixelFormat(pBitmap, &pf); 130 ok(pf == expect_pf, "Expected PixelFormat to be 0x%x, was: 0x%x\n", (int)expect_pf, (int)pf); 131 132 DisposeImage(pBitmap); 133 } 134 Shutdown(gdiplusToken); 135 } 136 137 static void Test_LoadSaveImage(void) 138 { 139 HRESULT hr; 140 TCHAR* file; 141 BOOL bOK; 142 int width, height, bpp; 143 size_t n; 144 CImage image1, image2; 145 COLORREF color; 146 HDC hDC; 147 148 HINSTANCE hInst = GetModuleHandle(NULL); 149 GetTempPath(MAX_PATH, szTempPath); 150 151 image1.LoadFromResource(hInst, IDB_ANT); 152 ok(!image1.IsNull(), "Expected image1 is not null\n"); 153 154 width = image1.GetWidth(); 155 ok(width == 48, "Expected width to be 48, was: %d\n", width); 156 height = image1.GetHeight(); 157 ok(height == 48, "Expected height to be 48, was: %d\n", height); 158 bpp = image1.GetBPP(); 159 ok(bpp == 8, "Expected bpp to be 8, was: %d\n", bpp); 160 161 image2.LoadFromResource(hInst, IDB_CROSS); 162 ok(!image2.IsNull(), "Expected image2 is not null\n"); 163 image2.SetTransparentColor(RGB(255, 255, 255)); 164 165 width = image2.GetWidth(); 166 ok(width == 32, "Expected width to be 32, was: %d\n", width); 167 height = image2.GetHeight(); 168 ok(height == 32, "Expected height to be 32, was: %d\n", height); 169 bpp = image2.GetBPP(); 170 ok(bpp == 8, "Expected bpp to be 8, was: %d\n", bpp); 171 172 color = image1.GetPixel(5, 5); 173 ok(color == RGB(166, 202, 240), "Expected color to be 166, 202, 240; was: %i, %i, %i\n", GetRValue(color), GetGValue(color), GetBValue(color)); 174 175 hDC = image1.GetDC(); 176 bOK = image2.Draw(hDC, 0, 0); 177 image1.ReleaseDC(); 178 ok(bOK != FALSE, "Expected bDraw to be TRUE, was: %d\n", bOK); 179 image2.Destroy(); 180 181 color = image1.GetPixel(5, 5); 182 ok(color == RGB(255, 0,0), "Expected color to be 255, 0, 0; was: %i, %i, %i\n", GetRValue(color), GetGValue(color), GetBValue(color)); 183 184 file = file_name(TEXT("ant.bmp")); 185 write_bitmap(hInst, IDB_ANT, file); 186 187 init_gdip(); 188 189 determine_file_bpp(file, PixelFormat8bppIndexed); 190 191 hr = image2.Load(file); 192 ok(hr == S_OK, "Expected hr to be S_OK, was: %08lx\n", hr); 193 ok(!image2.IsNull(), "Expected image1 is not null\n"); 194 bOK = DeleteFile(file); 195 ok(bOK, "Expected bOK to be TRUE, was: %d\n", bOK); 196 197 width = image2.GetWidth(); 198 ok_int(width, 48); 199 height = image2.GetHeight(); 200 ok_int(height, 48); 201 bpp = image2.GetBPP(); 202 ok(bpp == 32 || bpp == 8, "bpp was %d\n", bpp); 203 204 for (n = 0; n < _countof(szFiles); ++n) 205 { 206 file = file_name(szFiles[n]); 207 image2.Destroy(); 208 209 if (n == 0) 210 hr = image1.Save(file, Gdiplus::ImageFormatPNG); 211 else 212 hr = image1.Save(file); 213 ok(hr == S_OK, "Expected hr to be S_OK, was: %08lx (for %i)\n", hr, n); 214 215 bOK = (GetFileAttributes(file) != 0xFFFFFFFF); 216 ok(bOK, "Expected bOK to be TRUE, was: %d (for %i)\n", bOK, n); 217 218 hr = image2.Load(file); 219 ok(hr == S_OK, "Expected hr to be S_OK, was: %08lx (for %i)\n", hr, n); 220 221 width = image2.GetWidth(); 222 ok(width == 48, "Expected width to be 48, was: %d (for %i)\n", width, n); 223 height = image2.GetHeight(); 224 ok(height == 48, "Expected height to be 48, was: %d (for %i)\n", height, n); 225 bpp = image2.GetBPP(); 226 if (n == 3) 227 { 228 ok(bpp == 24 || bpp == 32, "Expected bpp to be 24 or 32, was: %d (for %i)\n", bpp, n); 229 determine_file_bpp(file, PixelFormat24bppRGB); 230 } 231 else 232 { 233 determine_file_bpp(file, PixelFormat8bppIndexed); 234 } 235 color = image1.GetPixel(5, 5); 236 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); 237 238 bOK = DeleteFile(file); 239 ok(bOK, "Expected bOK to be TRUE, was: %d (for %i)\n", bOK, n); 240 } 241 } 242 243 static INT FindGUID(REFGUID rguid, const CSimpleArray<GUID>& guids) 244 { 245 for (INT i = 0; i < guids.GetSize(); ++i) 246 { 247 if (memcmp(&rguid, &guids[i], sizeof(GUID)) == 0) 248 return i; 249 } 250 return -1; 251 } 252 253 static INT FindFilterItem(const TCHAR *filter, const TCHAR *item) 254 { 255 INT iFilter = 0; 256 DWORD cbItem = lstrlen(item) * sizeof(TCHAR); 257 BOOL bSep = TRUE; 258 259 for (; *filter; ++filter) 260 { 261 if (bSep && memcmp(item, filter, cbItem) == 0) 262 return (iFilter + 1) / 2; 263 264 bSep = (*filter == TEXT('|')); 265 if (bSep) 266 ++iFilter; 267 } 268 269 return -1; 270 } 271 272 static void Test_Importer(void) 273 { 274 HRESULT hr; 275 ATL::IAtlStringMgr *mgr = CAtlStringMgr::GetInstance(); 276 CSimpleArray<GUID> aguidFileTypes; 277 INT iNULL, iBMP, iJPEG, iGIF, iPNG, iTIFF, iEMF, iWMF; 278 279 // Try importer with "All Image Files" 280 CSimpleString strImporters(mgr); 281 aguidFileTypes.RemoveAll(); 282 hr = CImage::GetImporterFilterString(strImporters, aguidFileTypes, TEXT("All Image Files"), 0); 283 ok(hr == S_OK, "Expected hr to be S_OK, was: %ld\n", hr); 284 ok(aguidFileTypes.GetSize() >= 8, 285 "Expected aguidFileTypes.GetSize() to be >= 8, was %d.", aguidFileTypes.GetSize()); 286 287 iNULL = FindGUID(GUID_NULL, aguidFileTypes); 288 iBMP = FindGUID(Gdiplus::ImageFormatBMP, aguidFileTypes); 289 iJPEG = FindGUID(Gdiplus::ImageFormatJPEG, aguidFileTypes); 290 iGIF = FindGUID(Gdiplus::ImageFormatGIF, aguidFileTypes); 291 iPNG = FindGUID(Gdiplus::ImageFormatPNG, aguidFileTypes); 292 iTIFF = FindGUID(Gdiplus::ImageFormatTIFF, aguidFileTypes); 293 iEMF = FindGUID(Gdiplus::ImageFormatEMF, aguidFileTypes); 294 iWMF = FindGUID(Gdiplus::ImageFormatWMF, aguidFileTypes); 295 296 ok_int(iNULL, 0); 297 ok(iBMP > 0, "iBMP was %d\n", iBMP); 298 ok(iJPEG > 0, "iJPEG was %d\n", iJPEG); 299 ok(iGIF > 0, "iGIF was %d\n", iGIF); 300 ok(iPNG > 0, "iPNG was %d\n", iPNG); 301 ok(iTIFF > 0, "iTIFF was %d\n", iTIFF); 302 ok(iEMF > 0, "iEMF was %d\n", iEMF); 303 ok(iWMF > 0, "iWMF was %d\n", iWMF); 304 305 ok_int(memcmp(strImporters, TEXT("All Image Files|"), sizeof(TEXT("All Image Files|")) - sizeof(TCHAR)), 0); 306 ok_int(iBMP, FindFilterItem(strImporters, TEXT("BMP (*.BMP;*.DIB;*.RLE)|*.BMP;*.DIB;*.RLE|"))); 307 ok_int(iJPEG, FindFilterItem(strImporters, TEXT("JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)|*.JPG;*.JPEG;*.JPE;*.JFIF|"))); 308 ok_int(iGIF, FindFilterItem(strImporters, TEXT("GIF (*.GIF)|*.GIF|"))); 309 ok_int(iPNG, FindFilterItem(strImporters, TEXT("PNG (*.PNG)|*.PNG|"))); 310 ok_int(iTIFF, FindFilterItem(strImporters, TEXT("TIFF (*.TIF;*.TIFF)|*.TIF;*.TIFF|"))); 311 312 // Try importer without "All Image Files" 313 aguidFileTypes.RemoveAll(); 314 strImporters.Empty(); 315 hr = CImage::GetImporterFilterString(strImporters, aguidFileTypes, NULL, 0); 316 ok(hr == S_OK, "Expected hr to be S_OK, was: %ld\n", hr); 317 ok(aguidFileTypes.GetSize() >= 7, 318 "Expected aguidFileTypes.GetSize() to be >= 7, was %d.", aguidFileTypes.GetSize()); 319 320 iNULL = FindGUID(GUID_NULL, aguidFileTypes); 321 iBMP = FindGUID(Gdiplus::ImageFormatBMP, aguidFileTypes); 322 iJPEG = FindGUID(Gdiplus::ImageFormatJPEG, aguidFileTypes); 323 iGIF = FindGUID(Gdiplus::ImageFormatGIF, aguidFileTypes); 324 iPNG = FindGUID(Gdiplus::ImageFormatPNG, aguidFileTypes); 325 iTIFF = FindGUID(Gdiplus::ImageFormatTIFF, aguidFileTypes); 326 iEMF = FindGUID(Gdiplus::ImageFormatEMF, aguidFileTypes); 327 iWMF = FindGUID(Gdiplus::ImageFormatWMF, aguidFileTypes); 328 329 ok_int(iNULL, -1); 330 ok_int(iBMP, 0); 331 ok(iJPEG > 0, "iJPEG was %d\n", iJPEG); 332 ok(iGIF > 0, "iGIF was %d\n", iGIF); 333 ok(iPNG > 0, "iPNG was %d\n", iPNG); 334 ok(iTIFF > 0, "iTIFF was %d\n", iTIFF); 335 ok(iEMF > 0, "iEMF was %d\n", iEMF); 336 ok(iWMF > 0, "iWMF was %d\n", iWMF); 337 338 ok_int(iBMP, FindFilterItem(strImporters, TEXT("BMP (*.BMP;*.DIB;*.RLE)|*.BMP;*.DIB;*.RLE|"))); 339 ok_int(iJPEG, FindFilterItem(strImporters, TEXT("JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)|*.JPG;*.JPEG;*.JPE;*.JFIF|"))); 340 ok_int(iGIF, FindFilterItem(strImporters, TEXT("GIF (*.GIF)|*.GIF|"))); 341 ok_int(iPNG, FindFilterItem(strImporters, TEXT("PNG (*.PNG)|*.PNG|"))); 342 ok_int(iTIFF, FindFilterItem(strImporters, TEXT("TIFF (*.TIF;*.TIFF)|*.TIF;*.TIFF|"))); 343 } 344 345 static void Test_Exporter(void) 346 { 347 HRESULT hr; 348 ATL::IAtlStringMgr *mgr = CAtlStringMgr::GetInstance(); 349 CSimpleArray<GUID> aguidFileTypes; 350 INT iNULL, iBMP, iJPEG, iGIF, iPNG, iTIFF; 351 352 // Try exporter with "All Image Files" 353 CSimpleString strExporters(mgr); 354 aguidFileTypes.RemoveAll(); 355 hr = CImage::GetExporterFilterString(strExporters, aguidFileTypes, TEXT("All Image Files"), 0); 356 ok(hr == S_OK, "Expected hr to be S_OK, was: %ld\n", hr); 357 ok(aguidFileTypes.GetSize() >= 6, 358 "Expected aguidFileTypes.GetSize() to be >= 6, was %d.", aguidFileTypes.GetSize()); 359 360 iNULL = FindGUID(GUID_NULL, aguidFileTypes); 361 iBMP = FindGUID(Gdiplus::ImageFormatBMP, aguidFileTypes); 362 iJPEG = FindGUID(Gdiplus::ImageFormatJPEG, aguidFileTypes); 363 iGIF = FindGUID(Gdiplus::ImageFormatGIF, aguidFileTypes); 364 iPNG = FindGUID(Gdiplus::ImageFormatPNG, aguidFileTypes); 365 iTIFF = FindGUID(Gdiplus::ImageFormatTIFF, aguidFileTypes); 366 367 ok_int(iNULL, 0); 368 ok(iBMP > 0, "iBMP was %d\n", iBMP); 369 ok(iJPEG > 0, "iJPEG was %d\n", iJPEG); 370 ok(iGIF > 0, "iGIF was %d\n", iGIF); 371 ok(iPNG > 0, "iPNG was %d\n", iPNG); 372 ok(iTIFF > 0, "iTIFF was %d\n", iTIFF); 373 374 ok_int(iBMP, FindFilterItem(strExporters, TEXT("BMP (*.BMP;*.DIB;*.RLE)|*.BMP;*.DIB;*.RLE|"))); 375 ok_int(iJPEG, FindFilterItem(strExporters, TEXT("JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)|*.JPG;*.JPEG;*.JPE;*.JFIF|"))); 376 ok_int(iGIF, FindFilterItem(strExporters, TEXT("GIF (*.GIF)|*.GIF|"))); 377 ok_int(iPNG, FindFilterItem(strExporters, TEXT("PNG (*.PNG)|*.PNG|"))); 378 ok_int(iTIFF, FindFilterItem(strExporters, TEXT("TIFF (*.TIF;*.TIFF)|*.TIF;*.TIFF|"))); 379 380 // Try exporter without "All Image Files" 381 strExporters.Empty(); 382 aguidFileTypes.RemoveAll(); 383 hr = CImage::GetExporterFilterString(strExporters, aguidFileTypes, NULL, 0); 384 ok(hr == S_OK, "Expected hr to be S_OK, was: %ld\n", hr); 385 ok(aguidFileTypes.GetSize() >= 5, 386 "Expected aguidFileTypes.GetSize() to be >= 5, was %d.", aguidFileTypes.GetSize()); 387 388 iNULL = FindGUID(GUID_NULL, aguidFileTypes); 389 iBMP = FindGUID(Gdiplus::ImageFormatBMP, aguidFileTypes); 390 iJPEG = FindGUID(Gdiplus::ImageFormatJPEG, aguidFileTypes); 391 iGIF = FindGUID(Gdiplus::ImageFormatGIF, aguidFileTypes); 392 iPNG = FindGUID(Gdiplus::ImageFormatPNG, aguidFileTypes); 393 iTIFF = FindGUID(Gdiplus::ImageFormatTIFF, aguidFileTypes); 394 395 ok_int(iNULL, -1); 396 ok_int(iBMP, 0); 397 ok(iJPEG > 0, "iJPEG was %d\n", iJPEG); 398 ok(iGIF > 0, "iGIF was %d\n", iGIF); 399 ok(iPNG > 0, "iPNG was %d\n", iPNG); 400 ok(iTIFF > 0, "iTIFF was %d\n", iTIFF); 401 402 ok_int(iBMP, FindFilterItem(strExporters, TEXT("BMP (*.BMP;*.DIB;*.RLE)|*.BMP;*.DIB;*.RLE|"))); 403 ok_int(iJPEG, FindFilterItem(strExporters, TEXT("JPEG (*.JPG;*.JPEG;*.JPE;*.JFIF)|*.JPG;*.JPEG;*.JPE;*.JFIF|"))); 404 ok_int(iGIF, FindFilterItem(strExporters, TEXT("GIF (*.GIF)|*.GIF|"))); 405 ok_int(iPNG, FindFilterItem(strExporters, TEXT("PNG (*.PNG)|*.PNG|"))); 406 ok_int(iTIFF, FindFilterItem(strExporters, TEXT("TIFF (*.TIF;*.TIFF)|*.TIF;*.TIFF|"))); 407 } 408 409 START_TEST(CImage) 410 { 411 Test_LoadSaveImage(); 412 Test_Importer(); 413 Test_Exporter(); 414 } 415