21 ComInitializer comInitializer;
22 if (!comInitializer.IsInitialized())
24 LogError(
"Unable to initialize COM for WIC.");
29 ComObject<IWICImagingFactory> wicFactory;
30 HRESULT hr = ::CoCreateInstance(CLSID_WICImagingFactory,
nullptr,
31 CLSCTX_INPROC_SERVER, IID_IWICImagingFactory,
32 reinterpret_cast<LPVOID*>(&wicFactory));
35 LogError(
"Unable to create WIC imaging factory.");
40 std::wstring wfilename(filename.begin(), filename.end());
41 ComObject<IWICBitmapDecoder> wicDecoder;
42 hr = wicFactory->CreateDecoderFromFilename(wfilename.c_str(),
43 nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &wicDecoder);
46 LogError(
"wicFactory->CreateDecoderFromFilename failed (" +
52 ComObject<IWICBitmapFrameDecode> wicFrameDecode;
53 hr = wicDecoder->GetFrame(0, &wicFrameDecode);
56 LogError(
"wicDecoder->GetFrame failed.");
61 WICPixelFormatGUID wicSourceGUID;
62 hr = wicFrameDecode->GetPixelFormat(&wicSourceGUID);
65 LogError(
"wicFrameDecode->GetPixelFormat failed.");
72 WICPixelFormatGUID wicConvertGUID = GUID_WICPixelFormat32bppRGBA;
95 IWICBitmapSource* wicBitmapSource = wicFrameDecode;
96 ComObject<IWICFormatConverter> wicFormatConverter;
97 if (!IsEqualGUID(wicSourceGUID, wicConvertGUID))
100 hr = wicFactory->CreateFormatConverter(&wicFormatConverter);
103 LogError(
"wicFactory->CreateFormatConverter failed.");
109 hr = wicFormatConverter->Initialize(wicFrameDecode, wicConvertGUID,
110 WICBitmapDitherTypeNone,
nullptr, 0.0,
111 WICBitmapPaletteTypeCustom);
114 LogError(
"wicFormatConverter->Initialize failed.");
119 wicBitmapSource = wicFormatConverter;
124 hr = wicBitmapSource->GetSize(&width, &height);
127 LogError(
"wicBitmapSource->GetSize failed.");
132 std::shared_ptr<Texture2>
texture = std::make_shared<Texture2>(
134 UINT const stride = width * texture->GetElementSize();
138 hr = wicBitmapSource->CopyPixels(
nullptr, stride, imageSize,
139 texture->Get<BYTE>());
142 LogError(
"wicBitmapSource->CopyPixels failed.");
150 std::shared_ptr<Texture2>
const&
texture)
152 return SaveTo(filename, texture, -1.0
f);
156 std::shared_ptr<Texture2>
const&
texture,
float imageQuality)
158 imageQuality = std::min(std::max(imageQuality, 0.0
f), 1.0
f);
159 return SaveTo(filename, texture, imageQuality);
163 std::shared_ptr<Texture2>
const&
texture,
float imageQuality)
165 if (!texture || !texture->GetData())
167 LogError(
"The texture and its data must exist.");
172 WICPixelFormatGUID wicSourceGUID = GUID_WICPixelFormatUndefined;
181 if (IsEqualGUID(wicSourceGUID, GUID_WICPixelFormatUndefined))
185 "is not supported for saving.");
193 LogError(
"Unable to initialize COM for WIC.");
199 HRESULT hr = ::CoCreateInstance(CLSID_WICImagingFactory,
nullptr,
200 CLSCTX_INPROC_SERVER, IID_IWICImagingFactory,
201 reinterpret_cast<LPVOID*>(&wicFactory));
204 LogError(
"Unable to create WIC imaging factory.");
210 hr = wicFactory->CreateStream(&wicStream);
213 LogError(
"wicFactory->CreateStream failed.");
217 std::wstring wfilename(filename.begin(), filename.end());
218 hr = wicStream->InitializeFromFilename(wfilename.c_str(), GENERIC_WRITE);
221 LogError(
"wicStream->InitializeFromFilename failed (" +
228 if (imageQuality == -1.0
f)
230 hr = wicFactory->CreateEncoder(GUID_ContainerFormatPng,
nullptr, &wicEncoder);
234 hr = wicFactory->CreateEncoder(GUID_ContainerFormatJpeg,
nullptr, &wicEncoder);
238 LogError(
"wicFactory->CreateEncoder failed.");
242 hr = wicEncoder->Initialize(wicStream, WICBitmapEncoderNoCache);
245 LogError(
"wicEncoder->Initialize failed.");
252 hr = wicEncoder->CreateNewFrame(&wicFrameEncode, &wicPropertyBag);
255 LogError(
"wicEncoder->CreateNewFrame failed.");
259 if (imageQuality == -1.0
f)
266 option.pstrName = L
"InterlaceOption";
267 VariantInit(&varValue);
268 varValue.vt = VT_BOOL;
269 varValue.boolVal = FALSE;
270 hr = wicPropertyBag->Write(1, &option, &varValue);
273 LogError(
"wicPropertyBag->Write failed for InterlaceOption.");
278 option.pstrName = L
"FilterOption";
279 VariantInit(&varValue);
280 varValue.vt = VT_UI1;
281 varValue.bVal = WICPngFilterNone;
282 hr = wicPropertyBag->Write(1, &option, &varValue);
285 LogError(
"wicPropertyBag->Write failed for FilterOption.");
296 option.pstrName = L
"ImageQuality";
297 VariantInit(&varValue);
299 varValue.fltVal = imageQuality;
300 hr = wicPropertyBag->Write(1, &option, &varValue);
303 LogError(
"wicPropertyBag->Write failed for ImageQuality.");
309 hr = wicFrameEncode->Initialize(wicPropertyBag);
312 LogError(
"wicFrameEncode->Initialize failed.");
319 hr = wicFrameEncode->SetSize(width, height);
322 LogError(
"wicFrameEncode->SetSize failed.");
327 WICPixelFormatGUID wicTargetGUID = wicSourceGUID;
328 hr = wicFrameEncode->SetPixelFormat(&wicTargetGUID);
331 LogError(
"wicFrameEncode->SetPixelFormat failed.");
336 UINT const stride = width * texture->GetElementSize();
341 hr = wicFactory->CreateBitmapFromMemory(width, height,
342 wicSourceGUID, stride, imageSize, texture->Get<BYTE>(),
346 LogError(
"wicFactory->CreateBitmapFromMemory failed.");
353 IWICBitmapSource* wicBitmapSource = wicTextureBitmap;
355 if (!IsEqualGUID(wicSourceGUID, wicTargetGUID))
358 hr = wicFactory->CreateFormatConverter(&wicFormatConverter);
361 LogError(
"wicFactory->CreateFormatConverter failed.");
367 hr = wicFormatConverter->Initialize(wicTextureBitmap, wicTargetGUID,
368 WICBitmapDitherTypeNone,
nullptr, 0.0, WICBitmapPaletteTypeCustom);
371 LogError(
"wicFormatConverter->Initialize failed.");
376 wicBitmapSource = wicFormatConverter;
380 hr = wicFrameEncode->WriteSource(wicBitmapSource,
nullptr);
383 LogError(
"wicFrameEncode->WriteSource failed.");
388 hr = wicFrameEncode->Commit();
391 LogError(
"wicFrameEncode->Commit failed.");
396 hr = wicEncoder->Commit();
399 LogError(
"wicEncoder->Commit failed.");
416 HRESULT hr = ::CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED);
417 mInitialized = SUCCEEDED(hr);
425 template <
typename T>
432 template <
typename T>
437 if (
object !=
nullptr)
443 template <
typename T>
452 template <
typename T>
458 template <
typename T>
464 template <
typename T>
470 template <
typename T>
483 {
DF_R1_UNORM, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat8bppGray },
484 {
DF_R8_UNORM, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat8bppGray },
485 {
DF_R8_UNORM, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat8bppGray },
486 {
DF_R8_UNORM, &GUID_WICPixelFormat8bppGray,
nullptr },
487 {
DF_R16_UNORM, &GUID_WICPixelFormat16bppGray,
nullptr },
488 {
DF_R32_FLOAT, &GUID_WICPixelFormat32bppGrayFloat,
nullptr },
490 {
DF_R8G8B8A8_UNORM, &GUID_WICPixelFormat32bppBGRA, &GUID_WICPixelFormat32bppRGBA },
static bool SaveTo(std::string const &filename, std::shared_ptr< Texture2 > const &texture, float imageQuality)
static LoadFormatMap const msLoadFormatMap[NUM_LOAD_FORMATS]
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei imageSize
static bool SaveToJPEG(std::string const &filename, std::shared_ptr< Texture2 > const &texture, float imageQuality)
GLsizei const GLchar *const * string
#define LogError(message)
GLint GLsizei GLsizei height
static SaveFormatMap const msSaveFormatMap[NUM_SAVE_FORMATS]
static std::shared_ptr< Texture2 > Load(std::string const &filename, bool wantMipmaps)
bool IsInitialized() const
typedef UINT(WINAPI *PFNWGLGETGPUIDSAMDPROC)(UINT maxCount
GLint GLenum GLboolean GLsizei stride
static bool SaveToPNG(std::string const &filename, std::shared_ptr< Texture2 > const &texture)