HBITMAP ImageDecoder::convertFrameToBitmap(IWICBitmapFrameDecode *frame) { IWICBitmapSource *bitmapSource = frame; if (FAILED(WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, frame, &bitmapSource))) { throw Exception("could not convert bitmap"); } UINT width = 0; UINT height = 0; if (FAILED(bitmapSource->GetSize(&width, &height)) || width == 0 || height == 0) { throw Exception("could not get image size"); } std::vector<BYTE> buffer(width * height * 4); if (FAILED(bitmapSource->CopyPixels(NULL, width * 4, buffer.size(), &buffer[0]))) { throw Exception("could not get image size"); } bitmapSource->Release(); return CreateBitmap(width, height, 1, 32, &buffer[0]); }
HBITMAP LoadPNGImage(UINT id, OUT VOID **bits) { HBITMAP hbmpSplash = NULL; // load the PNG image data into a stream IStream * ipImageStream = CreateStreamOnResource(MAKEINTRESOURCE(id), _T("PNG")); if (ipImageStream == NULL) goto Return; // load the bitmap with WIC IWICBitmapSource * ipBitmap = LoadBitmapFromStream(ipImageStream); if (ipBitmap == NULL) goto ReleaseStream; // create a HBITMAP containing the image hbmpSplash = CreateHBITMAP(ipBitmap, bits); ipBitmap->Release(); ReleaseStream: ipImageStream->Release(); Return: return hbmpSplash; }
Image::Buffer * WIC::Api::CreateImage(char * buffer, unsigned bufferLength) { if(!factory) return 0; // Create input stream for memory IWICStream * stream = 0; factory->CreateStream(&stream); if(!stream) return 0; stream->InitializeFromMemory((unsigned char*)(buffer), static_cast<DWORD>(bufferLength)); IWICBitmapDecoder * decoder = 0; factory->CreateDecoderFromStream(stream, 0, WICDecodeMetadataCacheOnDemand, &decoder); if(!decoder) return 0; IWICBitmapFrameDecode * bitmapSource = 0; decoder->GetFrame(0, &bitmapSource); if(!bitmapSource) { decoder->Release(); return 0; } IWICBitmapSource * convertedSource = 0; WICConvertBitmapSource(GUID_WICPixelFormat32bppRGBA, bitmapSource, &convertedSource); bitmapSource->Release(); if(!convertedSource) { decoder->Release(); return 0; } // Create the bitmap from the image frame. IWICBitmap * bitmap = 0; factory->CreateBitmapFromSource( convertedSource, // Create a bitmap from the image frame WICBitmapCacheOnDemand, // Cache metadata when needed &bitmap); // Pointer to the bitmap convertedSource->Release(); decoder->Release(); if(!bitmap) return 0; unsigned width = 0, height = 0; bitmap->GetSize(&width, &height); WICRect lockRect = { 0, 0, width, height }; IWICBitmapLock * lock = 0; bitmap->Lock(&lockRect, WICBitmapLockWrite, &lock); if(!lock) { bitmap->Release(); return 0; } return new WIC::Buffer(bitmap, lock, width, height); }
Image::Buffer * WIC::Api::CreateImage(char * data, unsigned dataSize, unsigned w, unsigned h, Image::Format format) { IWICBitmap * bitmap = 0; factory->CreateBitmap(w, h, IMAGE_FORMAT_TO_WIC_GUID[format], WICBitmapCacheOnLoad, &bitmap); if(!bitmap) return 0; WICRect lockRect = { 0, 0, w, h }; IWICBitmapLock * lock = 0; bitmap->Lock(&lockRect, WICBitmapLockWrite, &lock); if(!lock) { bitmap->Release(); return 0; } unsigned bufferSize = 0; WICInProcPointer dataPointer = 0; lock->GetDataPointer(&bufferSize, &dataPointer); memcpy(dataPointer, data, dataSize); lock->Release(); lock = 0; if(format != Image::Format_4x8intRGBA) { IWICBitmapSource * convertedSource = 0; WICConvertBitmapSource(GUID_WICPixelFormat32bppRGBA, bitmap, &convertedSource); bitmap->Release(); bitmap = 0; if(!convertedSource) return 0; // Create the bitmap from the image frame. factory->CreateBitmapFromSource( convertedSource, // Create a bitmap from the image frame WICBitmapCacheOnDemand, // Cache metadata when needed &bitmap); // Pointer to the bitmap convertedSource->Release(); if(!bitmap) return 0; } bitmap->Lock(&lockRect, WICBitmapLockWrite, &lock); if(!lock) { bitmap->Release(); return 0; } return new WIC::Buffer(bitmap, lock, w, h); }
//---------------------------------------------------------------------------- Texture2* WICFileIO::Load(std::string const& filename, bool wantMipmaps) { // Start COM and create WIC. ComInitializer comInitializer; if (!comInitializer.IsInitialized()) { LogError("Unable to initialize COM for WIC."); return nullptr; } // Create a WIC imaging factory. ComObject<IWICImagingFactory> wicFactory; HRESULT hr = ::CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<LPVOID*>(&wicFactory)); if (FAILED(hr)) { LogError("Unable to create WIC imaging factory."); return nullptr; } // Create a decoder based on the file name. std::wstring wfilename = Environment::Convert(filename); ComObject<IWICBitmapDecoder> wicDecoder; hr = wicFactory->CreateDecoderFromFilename(wfilename.c_str(), nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &wicDecoder); if (FAILED(hr)) { LogError("wicFactory->CreateDecoderFromFilename failed (" + filename + ")."); return nullptr; } // Create a WIC decoder. ComObject<IWICBitmapFrameDecode> wicFrameDecode; hr = wicDecoder->GetFrame(0, &wicFrameDecode); if (FAILED(hr)) { LogError("wicDecoder->GetFrame failed."); return nullptr; } // Get the pixel format of the image. WICPixelFormatGUID wicSourceGUID; hr = wicFrameDecode->GetPixelFormat(&wicSourceGUID); if (FAILED(hr)) { LogError("wicFrameDecode->GetPixelFormat failed."); return nullptr; } // Find the supported WIC input pixel format that matches a Texture2 // format. If a matching format is not found, the returned texture // is an R8G8B8A8 format with texels converted from the source format. WICPixelFormatGUID wicConvertGUID = GUID_WICPixelFormat32bppRGBA; DFType gtformat = DF_R8G8B8A8_UNORM; for (int i = 0; i < NUM_LOAD_FORMATS; ++i) { if (IsEqualGUID(wicSourceGUID, *msLoadFormatMap[i].wicInputGUID)) { // Determine whether there is a conversion format. if (msLoadFormatMap[i].wicConvertGUID) { wicConvertGUID = *msLoadFormatMap[i].wicConvertGUID; } else { wicConvertGUID = *msLoadFormatMap[i].wicInputGUID; } gtformat = msLoadFormatMap[i].gtFormat; break; } } // The wicFrameDecode value is used for no conversion. If the decoder // does not support the format in the texture, then a conversion is // required. IWICBitmapSource* wicBitmapSource = wicFrameDecode; ComObject<IWICFormatConverter> wicFormatConverter; if (!IsEqualGUID(wicSourceGUID, wicConvertGUID)) { // Create a WIC format converter. hr = wicFactory->CreateFormatConverter(&wicFormatConverter); if (FAILED(hr)) { LogError("wicFactory->CreateFormatConverter failed."); return false; } // Initialize format converter to convert the input texture format // to the nearest format supported by the decoder. hr = wicFormatConverter->Initialize(wicFrameDecode, wicConvertGUID, WICBitmapDitherTypeNone, nullptr, 0.0, WICBitmapPaletteTypeCustom); if (FAILED(hr)) { LogError("wicFormatConverter->Initialize failed."); return false; } // Use the format converter. wicBitmapSource = wicFormatConverter; } // Get the image dimensions. UINT width, height; hr = wicBitmapSource->GetSize(&width, &height); if (FAILED(hr)) { LogError("wicBitmapSource->GetSize failed."); return nullptr; } // Create the 2D texture and compute the stride and image size. std::unique_ptr<Texture2> texture(new Texture2(gtformat, width, height, wantMipmaps)); UINT const stride = width * texture->GetElementSize(); UINT const imageSize = stride * height; // Copy the pixels from the decoder to the texture. hr = wicBitmapSource->CopyPixels(nullptr, stride, imageSize, texture->Get<BYTE>()); if (FAILED(hr)) { LogError("wicBitmapSource->CopyPixels failed."); return nullptr; } return texture.release(); }
HBITMAP ImageUtil::LoadImage(string path) { size_t pathFileExtDot = path.find_last_of('.'); if (pathFileExtDot == string::npos || pathFileExtDot + 1 >= path.length()) throw INETRException("[imgLoadFailed]"); string ext = path.substr(pathFileExtDot + 1); const GUID *decoderCLSID = nullptr; if (ext == "png") decoderCLSID = &CLSID_WICPngDecoder; else if (ext == "bmp") decoderCLSID = &CLSID_WICBmpDecoder; else if (ext == "gif") decoderCLSID = &CLSID_WICGifDecoder; else if (ext == "jpg" || ext == "jpeg") decoderCLSID = &CLSID_WICJpegDecoder; if (decoderCLSID == nullptr) throw INETRException("[unsupportedImg]: " + ext); IStream *pngFileStream; if (FAILED(SHCreateStreamOnFile(path.c_str(), STGM_READ, &pngFileStream))) throw INETRException("[imgLoadFailed]:\n" + path); IWICBitmapDecoder *bmpDecoder = nullptr; if (FAILED(CoCreateInstance(*decoderCLSID, nullptr, CLSCTX_INPROC_SERVER, __uuidof(bmpDecoder), reinterpret_cast<void**>(&bmpDecoder)))) throw INETRException("[imgDecFailed]"); if (FAILED(bmpDecoder->Initialize(pngFileStream, WICDecodeMetadataCacheOnLoad))) { bmpDecoder->Release(); throw INETRException("[imgDecFailed]"); } UINT bmpFrameCount = 0; if (FAILED(bmpDecoder->GetFrameCount(&bmpFrameCount)) && bmpFrameCount != 1) { bmpDecoder->Release(); throw INETRException("[imgDecFailed]"); } IWICBitmapFrameDecode *bmpFrame = nullptr; if (FAILED(bmpDecoder->GetFrame(0, &bmpFrame))) { bmpDecoder->Release(); throw INETRException("[imgDecFailed]"); } IWICBitmapSource *bmpSource = nullptr; WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, bmpFrame, &bmpSource); bmpFrame->Release(); bmpDecoder->Release(); UINT width = 0, height = 0; if (FAILED(bmpSource->GetSize(&width, &height)) || width == 0 || height == 0) throw INETRException("[imgDecFailed]"); BITMAPINFO bmInfo; ZeroMemory(&bmInfo, sizeof(bmInfo)); bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmInfo.bmiHeader.biWidth = width; bmInfo.bmiHeader.biHeight = -((LONG)height); bmInfo.bmiHeader.biPlanes = 1; bmInfo.bmiHeader.biBitCount = 32; bmInfo.bmiHeader.biCompression = BI_RGB; HBITMAP hbmp = nullptr; void *imageBits = nullptr; HDC screenDC = GetDC(nullptr); hbmp = CreateDIBSection(screenDC, &bmInfo, DIB_RGB_COLORS, &imageBits, nullptr, 0); ReleaseDC(nullptr, screenDC); if (hbmp == nullptr) throw INETRException("[imgDecFailed]"); const UINT bmpStride = width * 4; const UINT bmpSize = bmpStride * height; if (FAILED(bmpSource->CopyPixels(nullptr, bmpStride, bmpSize, static_cast<BYTE*>(imageBits)))) { DeleteObject(hbmp); hbmp = nullptr; throw INETRException("[imgDecFailed]"); } bmpSource->Release(); return hbmp; }