| 362 | } |
| 363 | |
| 364 | BOOL ReadImageProperty(const TCHAR *lpszImage, PROPID propId, TCHAR *szProperty, int cchMax) |
| 365 | { |
| 366 | Gdiplus::GdiplusStartupInput gdiplusStartupInput; |
| 367 | ULONG_PTR token; |
| 368 | Gdiplus::Status status = GdiplusStartup(&token, &gdiplusStartupInput, NULL); |
| 369 | |
| 370 | if(status != Gdiplus::Ok) |
| 371 | { |
| 372 | return FALSE; |
| 373 | } |
| 374 | |
| 375 | BOOL bSuccess = FALSE; |
| 376 | |
| 377 | /* This object needs to be |
| 378 | deleted before GdiplusShutdown |
| 379 | is called. If it were stack |
| 380 | allocated, it would go out of |
| 381 | scope _after_ the call to |
| 382 | GdiplusShutdown. By allocating |
| 383 | it on the heap, the lifetime |
| 384 | can be directly controlled. */ |
| 385 | auto *image = new Gdiplus::Image(lpszImage, FALSE); |
| 386 | |
| 387 | if(image->GetLastStatus() == Gdiplus::Ok) |
| 388 | { |
| 389 | if(propId == PropertyTagImageWidth) |
| 390 | { |
| 391 | bSuccess = TRUE; |
| 392 | StringCchPrintf(szProperty, cchMax, _T("%u pixels"), image->GetWidth()); |
| 393 | } |
| 394 | else if(propId == PropertyTagImageHeight) |
| 395 | { |
| 396 | bSuccess = TRUE; |
| 397 | StringCchPrintf(szProperty, cchMax, _T("%u pixels"), image->GetHeight()); |
| 398 | } |
| 399 | else |
| 400 | { |
| 401 | UINT size = image->GetPropertyItemSize(propId); |
| 402 | |
| 403 | if(size != 0) |
| 404 | { |
| 405 | auto *propertyItem = reinterpret_cast<Gdiplus::PropertyItem *>(malloc(size)); |
| 406 | |
| 407 | if(propertyItem != NULL) |
| 408 | { |
| 409 | status = image->GetPropertyItem(propId, size, propertyItem); |
| 410 | |
| 411 | if(status == Gdiplus::Ok) |
| 412 | { |
| 413 | if(propertyItem->type == PropertyTagTypeASCII) |
| 414 | { |
| 415 | int iRes = MultiByteToWideChar(CP_ACP, 0, reinterpret_cast<LPCSTR>(propertyItem->value), -1, |
| 416 | szProperty, cchMax); |
| 417 | |
| 418 | if(iRes != 0) |
| 419 | { |
| 420 | bSuccess = TRUE; |
| 421 | } |
no outgoing calls