HRESULT Application::OnRender() { HRESULT hr = S_OK; hr = CreateDeviceResources(); if(SUCCEEDED(hr)) { _pRenderTarget->BeginDraw(); _pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); _pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White)); D2D1_SIZE_F rtSize = _pRenderTarget->GetSize(); // Draw a grid background. int width = static_cast<int>(rtSize.width); int height = static_cast<int>(rtSize.height); for (int x = 0; x < width; x += 10) { _pRenderTarget->DrawLine(D2D1::Point2F(static_cast<FLOAT>(x), 0.0f), D2D1::Point2F(static_cast<FLOAT>(x), rtSize.height), _pLightSlateGrayBrush, 0.5f); } for (int y = 0; y < height; y += 10) { _pRenderTarget->DrawLine(D2D1::Point2F(0.0f, static_cast<FLOAT>(y)), D2D1::Point2F(rtSize.width, static_cast<FLOAT>(y)), _pLightSlateGrayBrush, 0.5f); } // Try to draw bitmap. if(_buffer != 0) { // Why? http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/17e9e6bd-aa91-40a3-afc9-3241a24afe00 IWICBitmap *pEmbeddedBitmap; ID2D1Bitmap *pBitmap; IWICImagingFactory *pFactory = NULL; HDC screen = GetDC(0); float dpiScaleX = GetDeviceCaps(screen, LOGPIXELSX) / 96.0f; float dpiScaleY = GetDeviceCaps(screen, LOGPIXELSY) / 96.0f; ReleaseDC(0, screen); CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*) &pFactory); HDC memDC = CreateCompatibleDC(screen); hr = pFactory->CreateBitmapFromMemory(_width, _height, GUID_WICPixelFormat32bppPBGRA, _width * 4, _numBytes, _buffer, &pEmbeddedBitmap); if(SUCCEEDED(hr)) { hr = _pRenderTarget->CreateBitmapFromWicBitmap(pEmbeddedBitmap, &pBitmap); _pRenderTarget->DrawBitmap(pBitmap); } } hr = _pRenderTarget->EndDraw(); } if(hr == D2DERR_RECREATE_TARGET) { hr = S_OK; DiscardDeviceResources(); } return hr; }
/// <summary> /// Sets the default cover -- when we couldn't find any other cover. /// </summary> void CoverArt::SetDefaultCover() { IWICImagingFactory *factory = nullptr; IWICBitmapDecoder *decoder = nullptr; IWICBitmapFrameDecode *source = nullptr; HRESULT hr = E_FAIL; hr = Factories::GetWICFactory(reinterpret_cast<LPVOID*>(&factory)); if (SUCCEEDED(hr)) { hr = factory->CreateDecoderFromFilename(mDefaultCoverArt, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder); } if (SUCCEEDED(hr)) { hr = decoder->GetFrame(0, &source); } if (SUCCEEDED(hr)) { SendMessage(gLSModule.GetMessageWindow(), WM_COVERARTUPDATE, (WPARAM)this, (LPARAM)source); } else { SendMessage(gLSModule.GetMessageWindow(), WM_COVERARTUPDATE, (WPARAM)this, (LPARAM)nullptr); } SAFERELEASE(decoder); }
static HRESULT CopyPixelsHelper(IWICBitmapSource* source, bool flipVertically, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) { HRESULT hr = S_OK; IWICImagingFactory* pWIC = _GetWIC(); if (!pWIC) return E_NOINTERFACE; if (flipVertically) { ComPtr<IWICBitmapFlipRotator> pFlipRotator; hr = pWIC->CreateBitmapFlipRotator(&pFlipRotator); if (FAILED(hr)) return hr; hr = pFlipRotator->Initialize(source, WICBitmapTransformFlipVertical); if (FAILED(hr)) return hr; hr = pFlipRotator->CopyPixels(0, cbStride, cbBufferSize, pbBuffer); if (FAILED(hr)) return hr; } else { hr = source->CopyPixels(0, cbStride, cbBufferSize, pbBuffer); if (FAILED(hr)) return hr; } return hr; }
bool WICImageLoader::decodeImageData(ImageBlob blob, size_t size) { bool bRet = false; HRESULT hr = E_FAIL; IWICStream* pWicStream = NULL; IWICImagingFactory* pWicFactory = getWICFactory(); if(NULL != pWicFactory) { hr = pWicFactory->CreateStream(&pWicStream); } if(SUCCEEDED(hr)) { hr = pWicStream->InitializeFromMemory((BYTE*)blob, static_cast<DWORD>(size)); } IWICBitmapDecoder* pDecoder = NULL; if(SUCCEEDED(hr)) { hr = pWicFactory->CreateDecoderFromStream(pWicStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder); } bRet = processImage(pDecoder); SafeRelease(&pWicStream); SafeRelease(&pDecoder); return bRet; }
static size_t wicBitsPerPixel( REFGUID targetGuid ) { IWICImagingFactory* pWIC = getWIC(); if ( !pWIC ) return 0; IWICComponentInfo *cinfo; if ( FAILED( pWIC->CreateComponentInfo( targetGuid, &cinfo ) ) ) return 0; WICComponentType type; if ( FAILED( cinfo->GetComponentType( &type ) ) ) return 0; if ( type != WICPixelFormat ) return 0; IWICPixelFormatInfo *pfinfo; if ( FAILED( cinfo->QueryInterface( __uuidof(IWICPixelFormatInfo), reinterpret_cast<void**>( &pfinfo ) ) ) ) return 0; UINT bpp; if ( FAILED( pfinfo->GetBitsPerPixel( &bpp ) ) ) return 0; return bpp; }
//--------------------------------------------------------------------------------- static size_t _WICBitsPerPixel( REFGUID targetGuid ) { IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return 0; ComPtr<IWICComponentInfo> cinfo; if ( FAILED( pWIC->CreateComponentInfo( targetGuid, cinfo.GetAddressOf() ) ) ) return 0; WICComponentType type; if ( FAILED( cinfo->GetComponentType( &type ) ) ) return 0; if ( type != WICPixelFormat ) return 0; ComPtr<IWICPixelFormatInfo> pfinfo; if ( FAILED( cinfo.As( &pfinfo ) ) ) return 0; UINT bpp; if ( FAILED( pfinfo->GetBitsPerPixel( &bpp ) ) ) return 0; return bpp; }
SpriteSheet::SpriteSheet(wchar_t* filename, Graphics* gfx) { this->gfx = gfx; bmp = NULL; HRESULT hr; //create a wic factory IWICImagingFactory *wicFactory = NULL; hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&wicFactory); //create a decoder IWICBitmapDecoder *wicDecoder = NULL; hr = wicFactory->CreateDecoderFromFilename( filename, // THE FILE NAME NULL, // the preferred vendor GENERIC_READ, // we're reading the file, not writing WICDecodeMetadataCacheOnLoad, &wicDecoder); // read a frame from the image IWICBitmapFrameDecode* wicFrame = NULL; hr = wicDecoder->GetFrame(0, &wicFrame); // create a converter IWICFormatConverter *wicConverter = NULL; hr = wicFactory->CreateFormatConverter(&wicConverter); // setup the converter hr = wicConverter->Initialize( wicFrame, // frame GUID_WICPixelFormat32bppPBGRA, // pixel format WICBitmapDitherTypeNone, // irrelevant NULL, // no palette needed, irrlevant 0.0, // alpha transparency % irrelevant WICBitmapPaletteTypeCustom // irrelevant ); // use the converter to create an D2D1Bitmap /// ID2D1Bitmap* bmp; // this will be a member variable hr = gfx->GetRenderTarget()->CreateBitmapFromWicBitmap( wicConverter, // converter NULL, // D2D1_BITMAP_PROPERIES &bmp // destiatnion D2D1 bitmap ); if (wicFactory) wicFactory->Release(); if (wicDecoder) wicDecoder->Release(); if (wicConverter) wicConverter->Release(); if (wicFrame) wicFrame->Release(); }
//------------------------------------------------------------------------------------- // Do flip/rotate operation using WIC //------------------------------------------------------------------------------------- static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage ) { if ( !srcImage.pixels || !destImage.pixels ) return E_POINTER; assert( srcImage.format == destImage.format ); IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; ScopedObject<IWICBitmap> source; HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID, static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ), srcImage.pixels, &source ); if ( FAILED(hr) ) return hr; ScopedObject<IWICBitmapFlipRotator> FR; hr = pWIC->CreateBitmapFlipRotator( &FR ); if ( FAILED(hr) ) return hr; hr = FR->Initialize( source.Get(), static_cast<WICBitmapTransformOptions>( flags ) ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID pfFR; hr = FR->GetPixelFormat( &pfFR ); if ( FAILED(hr) ) return hr; if ( memcmp( &pfFR, &pfGUID, sizeof(GUID) ) != 0 ) { // Flip/rotate should return the same format as the source... return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } UINT nwidth, nheight; hr = FR->GetSize( &nwidth, &nheight ); if ( FAILED(hr) ) return hr; if ( destImage.width != nwidth || destImage.height != nheight ) return E_FAIL; hr = FR->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels ); if ( FAILED(hr) ) return hr; return S_OK; }
HRESULT WICImageLoader::convertFormatIfRequired(IWICBitmapFrameDecode* pFrame, IWICFormatConverter** ppConv) { *ppConv = NULL; if( (memcmp(&_format, &GUID_WICPixelFormat8bppGray, sizeof(WICPixelFormatGUID)) == 0) || (memcmp(&_format, &GUID_WICPixelFormat8bppAlpha, sizeof(WICPixelFormatGUID)) == 0) || (memcmp(&_format, &GUID_WICPixelFormat24bppRGB, sizeof(WICPixelFormatGUID)) == 0) || (memcmp(&_format, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID)) == 0)) { return S_OK; } HRESULT hr = E_FAIL; IWICImagingFactory* pFactory = getWICFactory(); IWICFormatConverter* pConv = NULL; if(NULL != pFactory) { hr = pFactory->CreateFormatConverter(&pConv); } WICPixelFormatGUID destFormat = GUID_WICPixelFormat32bppRGBA; // Fallback to RGBA 32-bit format which is supported by all devices for( size_t i=0; i < _countof(g_WICConvert); ++i ) { if ( memcmp( &g_WICConvert[i].source, &_format, sizeof(WICPixelFormatGUID) ) == 0 ) { memcpy( &destFormat, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) ); break; } } BOOL bCanConv = FALSE; if(SUCCEEDED(hr)) { hr = pConv->CanConvert(_format, destFormat, &bCanConv); } if(SUCCEEDED(hr) && bCanConv == TRUE) { hr = pConv->Initialize(pFrame, destFormat, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); } if(SUCCEEDED(hr)) { memcpy(&_format, &destFormat, sizeof(WICPixelFormatGUID)); *ppConv = pConv; } return SUCCEEDED(hr); }
int SImgX_WIC::LoadFromMemory(void *pBuf,size_t bufLen ) { SASSERT(m_pImgArray == NULL); IWICImagingFactory* factory = SImgDecoderFactory_WIC::s_wicImgFactory; CAutoRefPtr<IWICBitmapDecoder> decoder; CAutoRefPtr<IWICStream> stream ; if(FAILED(factory->CreateStream(&stream))) return 0; if(FAILED(stream->InitializeFromMemory((BYTE*)pBuf,(DWORD)bufLen))) return 0; if(FAILED(factory->CreateDecoderFromStream(stream,NULL,WICDecodeMetadataCacheOnDemand,&decoder))) return 0; return _DoDecode(decoder); }
/// <summary> /// Tries to get the cover from the specified folder. /// </summary> /// <param name="filePath">Path to the file to get the cover from.</param> bool CoverArt::SetCoverFromFolder(LPCWSTR filePath) { WCHAR folderPath[MAX_PATH] = {0}; IWICImagingFactory *factory = nullptr; IWICBitmapDecoder *decoder = nullptr; IWICBitmapFrameDecode *source = nullptr; HRESULT hr = E_FAIL; StringCchCopyW(folderPath, _countof(folderPath), filePath); PathRemoveFileSpecW(folderPath); // Check each covername WCHAR artPath[MAX_PATH]; for (auto &canidate : mFolderCanidates) { StringCchPrintfW(artPath, _countof(artPath), L"%s\\%s", folderPath, canidate.c_str()); for (auto &file : FileIterator(artPath)) { StringCchPrintfW(artPath, _countof(artPath), L"%s\\%s", folderPath, file.cFileName); hr = Factories::GetWICFactory(reinterpret_cast<LPVOID*>(&factory)); if (SUCCEEDED(hr)) { hr = factory->CreateDecoderFromFilename(artPath, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder); } if (SUCCEEDED(hr)) { hr = decoder->GetFrame(0, &source); } if (SUCCEEDED(hr)) { SendMessage(gLSModule.GetMessageWindow(), WM_COVERARTUPDATE, (WPARAM)this, (LPARAM)source); } SAFERELEASE(decoder); if (SUCCEEDED(hr)) { return true; } } } return false; }
int SImgX_WIC::LoadFromFile( LPCWSTR pszFileName ) { SASSERT(m_pImgArray == NULL); IWICImagingFactory* factory = SImgDecoderFactory_WIC::s_wicImgFactory; CAutoRefPtr<IWICBitmapDecoder> decoder; HRESULT hr = factory->CreateDecoderFromFilename( pszFileName, NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder ); if(FAILED(hr)) return 0; return _DoDecode(decoder); }
int SImgX_WIC::_DoDecode( IWICBitmapDecoder * pDecoder ) { SASSERT(m_uImgCount == 0); IWICImagingFactory* factory = SImgDecoderFactory_WIC::s_wicImgFactory; CAutoRefPtr<IWICFormatConverter> converter; if(FAILED(factory->CreateFormatConverter(&converter))) return 0; if(FAILED(pDecoder->GetFrameCount(&m_uImgCount))) return 0; m_pImgArray = new SImgFrame_WIC[m_uImgCount]; for(UINT i = 0; i< m_uImgCount ;i++) { CAutoRefPtr<IWICBitmapFrameDecode> frame; if(SUCCEEDED(pDecoder->GetFrame(i,&frame))) { // CAutoRefPtr<IWICMetadataQueryReader> pMetaReader; // pDecoder->GetMetadataQueryReader(&pMetaReader); // if(pMetaReader) // { // PROPVARIANT propValue; // PropVariantInit(&propValue); // HRESULT hr=pMetaReader->GetMetadataByName(L"/grctlext/Delay", &propValue); // if(SUCCEEDED(hr)) // { // m_pImgArray[i].SetFrameDelay(propValue.intVal); // } // PropVariantClear(&propValue); // } converter->Initialize(frame, m_bPremultiplied?GUID_WICPixelFormat32bppPBGRA:GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeNone,NULL, 0.f,WICBitmapPaletteTypeCustom); CAutoRefPtr<IWICBitmapSource> bmp; converter->QueryInterface(IID_PPV_ARGS(&bmp)); m_pImgArray[i].SetWICBitmapSource(bmp); } } return m_uImgCount; }
// ---------------------------------------------------------------- // LoadResource // ---------------------------------------------------------------- bool CD2DBitmap::LoadResource( ResourceId id ) { ID2D1HwndRenderTarget * renderTarget = CD2DRenderer::GetInstance().GetHwndRenderTarget(); IWICImagingFactory * imagingFactory = CD2DRenderer::GetInstance().GetImagingFactory(); IWICBitmapDecoder * bitmapDecoder = nullptr; IWICBitmapFrameDecode* bitmapFrameDecode = nullptr; imagingFactory->CreateDecoderFromFilename( id.c_str(), nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &bitmapDecoder ); bitmapDecoder->GetFrame( 0, &bitmapFrameDecode ); imagingFactory->CreateFormatConverter( &m_FmtConverter ); m_FmtConverter->Initialize( bitmapFrameDecode, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0f, WICBitmapPaletteTypeCustom ); renderTarget->CreateBitmapFromWicBitmap( m_FmtConverter, nullptr, &m_D2DBitmap ); SafeRelease( bitmapDecoder ); SafeRelease( bitmapFrameDecode ); return true; }
void GL::Image::load(const unsigned char *buf, size_t bufSize) { if (CoInitializeEx(NULL, COINIT_MULTITHREADED) != S_OK) { // bad! return; } IStream *stream = SHCreateMemStream((const BYTE*)buf, (UINT)bufSize); if (stream != NULL) { IWICImagingFactory *pFactory; if (CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pFactory) == S_OK) { IWICBitmapDecoder *pDecoder; if (pFactory->CreateDecoderFromStream(stream, &CLSID_WICPngDecoder, WICDecodeMetadataCacheOnDemand, &pDecoder) == S_OK) { IWICBitmapFrameDecode *frame; if (pDecoder->GetFrame(0, &frame) == S_OK) { UINT w, h; if (frame->GetSize(&w, &h) == S_OK) { width_ = w; height_ = h; } IWICFormatConverter *formatConverter; if (pFactory->CreateFormatConverter(&formatConverter) == S_OK) { if (formatConverter->Initialize(frame, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0, WICBitmapPaletteTypeCustom) == S_OK) { unsigned char *pixels = new unsigned char[w * h * 4]; if (formatConverter->CopyPixels(0, w * 4, w * h * 4, pixels) == S_OK) { loadTextureData_(pixels); } delete[] pixels; } formatConverter->Release(); } } pDecoder->Release(); } pFactory->Release(); } stream->Release(); } CoUninitialize(); }
size_t WICImageLoader::getBitsPerPixel(WICPixelFormatGUID format) { HRESULT hr = E_FAIL; IWICImagingFactory* pfactory = getWICFactory(); IWICComponentInfo* pCInfo = NULL; if(pfactory != NULL) { hr = pfactory->CreateComponentInfo(format, &pCInfo); } WICComponentType cType; if(SUCCEEDED(hr)) { hr = pCInfo->GetComponentType(&cType); } IWICPixelFormatInfo* pPInfo = NULL; if(SUCCEEDED(hr) && cType == WICPixelFormat) { hr = pCInfo->QueryInterface(IID_IWICPixelFormatInfo, (void**)&pPInfo); } UINT bpp = 0; if(SUCCEEDED(hr)) { hr = pPInfo->GetBitsPerPixel(&bpp); } SafeRelease(&pCInfo); SafeRelease(&pPInfo); return bpp; }
static void BuildSkinIcons(TEnumData *lParam) { IWICImagingFactory *factory = (bIsVistaPlus) ? ARGB_GetWorker() : NULL; TSlotIPC *pct = lParam->ipch->NewIconsBegin; TShellExt *Self = lParam->Self; while (pct != NULL) { if (pct->cbSize != sizeof(TSlotIPC) || pct->fType != REQUEST_NEWICONS) break; TSlotProtoIcons *p = (TSlotProtoIcons*)(PBYTE(pct) + sizeof(TSlotIPC)); Self->ProtoIcons = (TSlotProtoIcons*)realloc(Self->ProtoIcons, (Self->ProtoIconsCount + 1) * sizeof(TSlotProtoIcons)); TSlotProtoIcons *d = &Self->ProtoIcons[Self->ProtoIconsCount]; memmove(d, p, sizeof(TSlotProtoIcons)); // if using Vista (or later), clone all the icons into bitmaps and keep these around, // if using anything older, just use the default code, the bitmaps (and/or icons) will be freed // with the shell object. for (int j = 0; j < 10; j++) { if (bIsVistaPlus) { d->hBitmaps[j] = ARGB_BitmapFromIcon(factory, Self->hMemDC, p->hIcons[j]); d->hIcons[j] = NULL; } else { d->hBitmaps[j] = NULL; d->hIcons[j] = CopyIcon(p->hIcons[j]); } } Self->ProtoIconsCount++; pct = pct->Next; } if (factory) factory->Release(); }
//--------------------------------------------------------------------------------- HRESULT WICTexImage2DFromFile(GLenum target, GLint level, const wchar_t* fileName, GLboolean verticalFlip) { if (!fileName) { return E_INVALIDARG; } IWICImagingFactory* pWIC = _GetWIC(); if (!pWIC) return E_NOINTERFACE; // Initialize WIC ComPtr<IWICBitmapDecoder> decoder; HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder); if (FAILED(hr)) return hr; ComPtr<IWICBitmapFrameDecode> frame; hr = decoder->GetFrame(0, &frame); if (FAILED(hr)) return hr; return TexImage2DFromWIC(target, level, frame.Get(), !!verticalFlip); }
_Use_decl_annotations_ HRESULT DirectX::CreateWICTextureFromFileEx( ID3D11Device* d3dDevice, ID3D11DeviceContext* d3dContext, const wchar_t* fileName, size_t maxsize, D3D11_USAGE usage, unsigned int bindFlags, unsigned int cpuAccessFlags, unsigned int miscFlags, bool forceSRGB, ID3D11Resource** texture, ID3D11ShaderResourceView** textureView ) { if ( texture ) { *texture = nullptr; } if ( textureView ) { *textureView = nullptr; } if (!d3dDevice || !fileName || (!texture && !textureView)) return E_INVALIDARG; IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; // Initialize WIC ComPtr<IWICBitmapDecoder> decoder; HRESULT hr = pWIC->CreateDecoderFromFilename( fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() ); if ( FAILED(hr) ) return hr; ComPtr<IWICBitmapFrameDecode> frame; hr = decoder->GetFrame( 0, frame.GetAddressOf() ); if ( FAILED(hr) ) return hr; hr = CreateTextureFromWIC( d3dDevice, d3dContext, frame.Get(), maxsize, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, texture, textureView ); #if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) if ( SUCCEEDED(hr) ) { if (texture != 0 || textureView != 0) { CHAR strFileA[MAX_PATH]; int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, fileName, -1, strFileA, MAX_PATH, nullptr, FALSE ); if ( result > 0 ) { const CHAR* pstrName = strrchr( strFileA, '\\' ); if (!pstrName) { pstrName = strFileA; } else { pstrName++; } if (texture != 0 && *texture != 0) { (*texture)->SetPrivateData( WKPDID_D3DDebugObjectName, static_cast<UINT>( strnlen_s(pstrName, MAX_PATH) ), pstrName ); } if (textureView != 0 && *textureView != 0 ) { (*textureView)->SetPrivateData( WKPDID_D3DDebugObjectName, static_cast<UINT>( strnlen_s(pstrName, MAX_PATH) ), pstrName ); } } } } #endif return hr; }
_Use_decl_annotations_ HRESULT DirectX::CreateWICTextureFromMemoryEx( ID3D11Device* d3dDevice, ID3D11DeviceContext* d3dContext, const uint8_t* wicData, size_t wicDataSize, size_t maxsize, D3D11_USAGE usage, unsigned int bindFlags, unsigned int cpuAccessFlags, unsigned int miscFlags, bool forceSRGB, ID3D11Resource** texture, ID3D11ShaderResourceView** textureView ) { if ( texture ) { *texture = nullptr; } if ( textureView ) { *textureView = nullptr; } if (!d3dDevice || !wicData || (!texture && !textureView)) return E_INVALIDARG; if ( !wicDataSize ) return E_FAIL; #ifdef _M_AMD64 if ( wicDataSize > 0xFFFFFFFF ) return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE ); #endif IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; // Create input stream for memory ComPtr<IWICStream> stream; HRESULT hr = pWIC->CreateStream( stream.GetAddressOf() ); if ( FAILED(hr) ) return hr; hr = stream->InitializeFromMemory( const_cast<uint8_t*>( wicData ), static_cast<DWORD>( wicDataSize ) ); if ( FAILED(hr) ) return hr; // Initialize WIC ComPtr<IWICBitmapDecoder> decoder; hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() ); if ( FAILED(hr) ) return hr; ComPtr<IWICBitmapFrameDecode> frame; hr = decoder->GetFrame( 0, frame.GetAddressOf() ); if ( FAILED(hr) ) return hr; hr = CreateTextureFromWIC( d3dDevice, d3dContext, frame.Get(), maxsize, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, texture, textureView ); if ( FAILED(hr)) return hr; if (texture != 0 && *texture != 0) { SetDebugObjectName(*texture, "WICTextureLoader"); } if (textureView != 0 && *textureView != 0) { SetDebugObjectName(*textureView, "WICTextureLoader"); } return hr; }
//--------------------------------------------------------------------------------- static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice, _In_opt_ ID3D11DeviceContext* d3dContext, _In_ IWICBitmapFrameDecode *frame, _In_ size_t maxsize, _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB, _Out_opt_ ID3D11Resource** texture, _Out_opt_ ID3D11ShaderResourceView** textureView ) { UINT width, height; HRESULT hr = frame->GetSize( &width, &height ); if ( FAILED(hr) ) return hr; assert( width > 0 && height > 0 ); if ( !maxsize ) { // This is a bit conservative because the hardware could support larger textures than // the Feature Level defined minimums, but doing it this way is much easier and more // performant for WIC than the 'fail and retry' model used by DDSTextureLoader switch( d3dDevice->GetFeatureLevel() ) { case D3D_FEATURE_LEVEL_9_1: case D3D_FEATURE_LEVEL_9_2: maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; case D3D_FEATURE_LEVEL_9_3: maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_10_1: maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; default: maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; break; } } assert( maxsize > 0 ); UINT twidth, theight; if ( width > maxsize || height > maxsize ) { float ar = static_cast<float>(height) / static_cast<float>(width); if ( width > height ) { twidth = static_cast<UINT>( maxsize ); theight = static_cast<UINT>( static_cast<float>(maxsize) * ar ); } else { theight = static_cast<UINT>( maxsize ); twidth = static_cast<UINT>( static_cast<float>(maxsize) / ar ); } assert( twidth <= maxsize && theight <= maxsize ); } else { twidth = width; theight = height; } // Determine format WICPixelFormatGUID pixelFormat; hr = frame->GetPixelFormat( &pixelFormat ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID convertGUID; memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) ); size_t bpp = 0; DXGI_FORMAT format = _WICToDXGI( pixelFormat ); if ( format == DXGI_FORMAT_UNKNOWN ) { if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) if ( g_WIC2 ) { memcpy( &convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32_FLOAT; } else #endif { memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32A32_FLOAT; } } else { for( size_t i=0; i < _countof(g_WICConvert); ++i ) { if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) ); format = _WICToDXGI( g_WICConvert[i].target ); assert( format != DXGI_FORMAT_UNKNOWN ); bpp = _WICBitsPerPixel( convertGUID ); break; } } } if ( format == DXGI_FORMAT_UNKNOWN ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } else { bpp = _WICBitsPerPixel( pixelFormat ); } #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) if ( (format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0 ) { // Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT UINT fmtSupport = 0; hr = d3dDevice->CheckFormatSupport( DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport ); if ( FAILED(hr) || !( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) { // Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32A32_FLOAT; bpp = 128; } } #endif if ( !bpp ) return E_FAIL; // Handle sRGB formats if ( forceSRGB ) { format = MakeSRGB( format ); } else { ComPtr<IWICMetadataQueryReader> metareader; if ( SUCCEEDED( frame->GetMetadataQueryReader( metareader.GetAddressOf() ) ) ) { GUID containerFormat; if ( SUCCEEDED( metareader->GetContainerFormat( &containerFormat ) ) ) { // Check for sRGB colorspace metadata bool sRGB = false; PROPVARIANT value; PropVariantInit( &value ); if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 ) { // Check for sRGB chunk if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 ) { sRGB = true; } } else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 ) { sRGB = true; } PropVariantClear( &value ); if ( sRGB ) format = MakeSRGB( format ); } } } // Verify our target format is supported by the current device // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) UINT support = 0; hr = d3dDevice->CheckFormatSupport( format, &support ); if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) { // Fallback to RGBA 32-bit format which is supported by all devices memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R8G8B8A8_UNORM; bpp = 32; } // Allocate temporary memory for image size_t rowPitch = ( twidth * bpp + 7 ) / 8; size_t imageSize = rowPitch * theight; std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ imageSize ] ); if (!temp) return E_OUTOFMEMORY; // Load image data if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0 && twidth == width && theight == height ) { // No format conversion or resize needed hr = frame->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } else if ( twidth != width || theight != height ) { // Resize IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; ComPtr<IWICBitmapScaler> scaler; hr = pWIC->CreateBitmapScaler( scaler.GetAddressOf() ); if ( FAILED(hr) ) return hr; hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID pfScaler; hr = scaler->GetPixelFormat( &pfScaler ); if ( FAILED(hr) ) return hr; if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 ) { // No format conversion needed hr = scaler->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } else { ComPtr<IWICFormatConverter> FC; hr = pWIC->CreateFormatConverter( FC.GetAddressOf() ); if ( FAILED(hr) ) return hr; BOOL canConvert = FALSE; hr = FC->CanConvert( pfScaler, convertGUID, &canConvert ); if ( FAILED(hr) || !canConvert ) { return E_UNEXPECTED; } hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } } else { // Format conversion but no resize IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; ComPtr<IWICFormatConverter> FC; hr = pWIC->CreateFormatConverter( FC.GetAddressOf() ); if ( FAILED(hr) ) return hr; BOOL canConvert = FALSE; hr = FC->CanConvert( pixelFormat, convertGUID, &canConvert ); if ( FAILED(hr) || !canConvert ) { return E_UNEXPECTED; } hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } // See if format is supported for auto-gen mipmaps (varies by feature level) bool autogen = false; if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps { UINT fmtSupport = 0; hr = d3dDevice->CheckFormatSupport( format, &fmtSupport ); if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) { autogen = true; } } // Create texture D3D11_TEXTURE2D_DESC desc; desc.Width = twidth; desc.Height = theight; desc.MipLevels = (autogen) ? 0 : 1; desc.ArraySize = 1; desc.Format = format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = usage; desc.CPUAccessFlags = cpuAccessFlags; if ( autogen ) { desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET; desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS; } else { desc.BindFlags = bindFlags; desc.MiscFlags = miscFlags; } D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = temp.get(); initData.SysMemPitch = static_cast<UINT>( rowPitch ); initData.SysMemSlicePitch = static_cast<UINT>( imageSize ); ID3D11Texture2D* tex = nullptr; hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex ); if ( SUCCEEDED(hr) && tex != 0 ) { if (textureView != 0) { D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; memset( &SRVDesc, 0, sizeof( SRVDesc ) ); SRVDesc.Format = desc.Format; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView ); if ( FAILED(hr) ) { tex->Release(); return hr; } if ( autogen ) { assert( d3dContext != 0 ); d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) ); d3dContext->GenerateMips( *textureView ); } } if (texture != 0) { *texture = tex; } else { SetDebugObjectName(tex, "WICTextureLoader"); tex->Release(); } } return hr; }
HRESULT CMainWindow::DecodeImageFromThumbCache( IShellItem *pShellItem, ID2D1Bitmap **ppBitmap ) { const UINT THUMB_SIZE = 256; // Read the bitmap from the thumbnail cache IThumbnailCache *pThumbCache; HRESULT hr = CoCreateInstance( CLSID_LocalThumbnailCache, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pThumbCache) ); if (SUCCEEDED(hr)) { ISharedBitmap *pBitmap; hr = pThumbCache->GetThumbnail( pShellItem, THUMB_SIZE, WTS_SCALETOREQUESTEDSIZE, &pBitmap, NULL, NULL ); if (SUCCEEDED(hr)) { HBITMAP hBitmap; hr = pBitmap->GetSharedBitmap( &hBitmap ); if (SUCCEEDED(hr)) { // Create a WIC bitmap from the shared bitmap IWICImagingFactory *pFactory; hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFactory) ); if (SUCCEEDED(hr)) { IWICBitmap *pWICBitmap; hr = pFactory->CreateBitmapFromHBITMAP( hBitmap, NULL, WICBitmapIgnoreAlpha, &pWICBitmap ); if (SUCCEEDED(hr)) { // Create a D2D bitmap from the WIC bitmap hr = m_pRenderTarget->CreateBitmapFromWicBitmap( pWICBitmap, NULL, ppBitmap ); pWICBitmap->Release(); } pFactory->Release(); } } pBitmap->Release(); } pThumbCache->Release(); } return hr; }
HRESULT loadAsShaderResource( const std::wstring &file, ID3D11Resource **texture, ID3D11ShaderResourceView **shaderView, ID3D11Device *dxDev, ID3D11DeviceContext *dxDevCont ) { if ( !dxDev || !dxDevCont ) return E_INVALIDARG; if ( !comIsInit ) { CoInitialize(NULL); comIsInit = true; } ScopedObject<IWICBitmapDecoder> decoder; HRESULT res = getWIC()->CreateDecoderFromFilename( file.c_str(), 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder ); if ( FAILED(res) ) return res; ScopedObject<IWICBitmapFrameDecode> frame; res = decoder->GetFrame(0, &frame); if ( FAILED(res) ) return res; UINT width, height; res = frame->GetSize( &width, &height ); if ( FAILED(res) ) return res; assert( width > 0 && height > 0 ); //calculate max width and height UINT maxSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; UINT tWidth, tHeight; if ( width > maxSize || height > maxSize ) { float ar = (float)height / width; if ( width > height ) { tWidth = maxSize; tHeight = (UINT)(float(maxSize) * ar); } else { tWidth = (UINT)(float(maxSize) / ar); tHeight = maxSize; } assert( tWidth <= maxSize && tHeight <= maxSize ); } else { tWidth = width; tHeight = height; } // Determine format WICPixelFormatGUID pixelFormat; res = frame->GetPixelFormat( &pixelFormat ); WICPixelFormatGUID convertGUID; memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) ); size_t bpp = 0; DXGI_FORMAT format = wicToDXGI( pixelFormat ); if ( format == DXGI_FORMAT_UNKNOWN ) { for( size_t i = 0; i < _countof(wicConvertList); ++i ) { if ( memcmp( &wicConvertList[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { memcpy( &convertGUID, &wicConvertList[i].target, sizeof(WICPixelFormatGUID) ); format = wicToDXGI( wicConvertList[i].target ); assert( format != DXGI_FORMAT_UNKNOWN ); bpp = wicBitsPerPixel( convertGUID ); break; } } if ( format == DXGI_FORMAT_UNKNOWN ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } else { bpp = wicBitsPerPixel( pixelFormat ); } if ( !bpp ) return E_FAIL; // Verify our target format is supported by the current device // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) UINT support = 0; res = dxDev->CheckFormatSupport( format, &support ); if ( FAILED(res) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) { // Fallback to RGBA 32-bit format which is supported by all devices memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R8G8B8A8_UNORM; bpp = 32; } // Allocate temporary memory for image size_t rowPitch = ( tWidth * bpp + 7 ) / 8; size_t imageSize = rowPitch * tHeight; std::unique_ptr<uint8_t[]> temp( new uint8_t[ imageSize ] ); // Load image data if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0 && tWidth == width && tHeight == height ) { // No format conversion or resize needed res = frame->CopyPixels( 0, (UINT)rowPitch, (UINT)imageSize, temp.get() ); if ( FAILED(res) ) return res; } else if ( tWidth != width || tHeight != height ) { // Resize IWICImagingFactory* pWIC = getWIC(); if ( !pWIC ) return E_NOINTERFACE; ScopedObject<IWICBitmapScaler> scaler; res = pWIC->CreateBitmapScaler( &scaler ); if ( FAILED(res) ) return res; res = scaler->Initialize( frame.get(), tWidth, tHeight, WICBitmapInterpolationModeFant ); if ( FAILED(res) ) return res; WICPixelFormatGUID pfScaler; res = scaler->GetPixelFormat( &pfScaler ); if ( FAILED(res) ) return res; if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 ) { // No format conversion needed res = scaler->CopyPixels( 0, (UINT)rowPitch, (UINT)imageSize, temp.get() ); if ( FAILED(res) ) return res; } else { ScopedObject<IWICFormatConverter> FC; res = pWIC->CreateFormatConverter( &FC ); if ( FAILED(res) ) return res; res = FC->Initialize( scaler.get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(res) ) return res; res = FC->CopyPixels( 0, (UINT)rowPitch, (UINT)imageSize, temp.get() ); if ( FAILED(res) ) return res; } } else { // Format conversion but no resize IWICImagingFactory* pWIC = getWIC(); if ( !pWIC ) return E_NOINTERFACE; ScopedObject<IWICFormatConverter> FC; res = pWIC->CreateFormatConverter( &FC ); if ( FAILED(res) ) return res; res = FC->Initialize( frame.get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(res) ) return res; res = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(res) ) return res; } // See if format is supported for auto-gen mipmaps bool autogen = false; if ( dxDevCont != 0 && shaderView != 0 ) // Must have context and shader-view to auto generate mipmaps { UINT fmtSupport = 0; res = dxDev->CheckFormatSupport( format, &fmtSupport ); if ( SUCCEEDED(res) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) autogen = true; } // Create texture D3D11_TEXTURE2D_DESC desc; desc.Width = tWidth; desc.Height = tHeight; desc.MipLevels = autogen ? 0 : 1; desc.ArraySize = 1; desc.Format = format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = autogen ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE); desc.CPUAccessFlags = 0; desc.MiscFlags = autogen ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = temp.get(); initData.SysMemPitch = (UINT)rowPitch; initData.SysMemSlicePitch = (UINT)imageSize; ID3D11Texture2D *tex = nullptr; res = dxDev->CreateTexture2D( &desc, autogen ? nullptr : &initData, &tex ); if ( SUCCEEDED(res) && tex != 0 ) { if (shaderView != 0) { D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; memset( &SRVDesc, 0, sizeof( SRVDesc ) ); SRVDesc.Format = format; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = autogen ? -1 : 1; res = dxDev->CreateShaderResourceView( tex, &SRVDesc, shaderView ); if ( FAILED(res) ) { tex->Release(); return res; } if ( autogen ) { assert( dxDevCont != 0 ); dxDevCont->UpdateSubresource( tex, 0, nullptr, temp.get(), (UINT)rowPitch, (UINT)imageSize ); dxDevCont->GenerateMips( *shaderView ); } } if (texture != 0) *texture = tex; else tex->Release(); } return S_OK; }
unsigned char *BBWin8Game::LoadImageData( String path,int *pwidth,int *pheight,int *pformat ){ if( !_wicFactory ){ DXASS( CoCreateInstance( CLSID_WICImagingFactory,0,CLSCTX_INPROC_SERVER,__uuidof(IWICImagingFactory),(LPVOID*)&_wicFactory ) ); } path=PathToFilePath( path ); IWICBitmapDecoder *decoder; if( !SUCCEEDED( _wicFactory->CreateDecoderFromFilename( path.ToCString<wchar_t>(),NULL,GENERIC_READ,WICDecodeMetadataCacheOnDemand,&decoder ) ) ){ return 0; } unsigned char *data=0; IWICBitmapFrameDecode *bitmapFrame; DXASS( decoder->GetFrame( 0,&bitmapFrame ) ); UINT width,height; WICPixelFormatGUID pixelFormat; DXASS( bitmapFrame->GetSize( &width,&height ) ); DXASS( bitmapFrame->GetPixelFormat( &pixelFormat ) ); if( pixelFormat==GUID_WICPixelFormat24bppBGR ){ unsigned char *t=(unsigned char*)malloc( width*3*height ); DXASS( bitmapFrame->CopyPixels( 0,width*3,width*3*height,t ) ); data=(unsigned char*)malloc( width*4*height ); unsigned char *s=t,*d=data; int n=width*height; while( n-- ){ *d++=s[2]; *d++=s[1]; *d++=s[0]; *d++=0xff; s+=3; } free( t ); }else if( pixelFormat==GUID_WICPixelFormat32bppBGRA ){ unsigned char *t=(unsigned char*)malloc( width*4*height ); DXASS( bitmapFrame->CopyPixels( 0,width*4,width*4*height,t ) ); data=t; int n=width*height; while( n-- ){ //premultiply alpha unsigned char r=t[0]; t[0]=t[2]*t[3]/255; t[1]=t[1]*t[3]/255; t[2]=r*t[3]/255; t+=4; } } if( data ){ *pwidth=width; *pheight=height; *pformat=4; } bitmapFrame->Release(); decoder->Release(); gc_force_sweep=true; return data; }
/// <summary> /// Tries to set the cover based on the Tags of the specified file. /// </summary> /// <param name="filePath">Path to the file to get the cover from.</param> bool CoverArt::SetCoverFromTag(LPCWSTR filePath) { LPCWSTR extension = wcsrchr(filePath, L'.'); if (extension == nullptr) { return false; } auto ParseImage = [this] (const BYTE * data, UINT size) { IWICImagingFactory *factory = nullptr; IWICBitmapDecoder *decoder = nullptr; IWICBitmapFrameDecode *source = nullptr; HRESULT hr = E_FAIL; IStream *stream = SHCreateMemStream(data, size); if (stream) { hr = Factories::GetWICFactory(reinterpret_cast<LPVOID*>(&factory)); if (SUCCEEDED(hr)) { hr = factory->CreateDecoderFromStream(stream, nullptr, WICDecodeMetadataCacheOnDemand, &decoder); } if (SUCCEEDED(hr)) { hr = decoder->GetFrame(0, &source); } if (SUCCEEDED(hr)) { SendMessage(gLSModule.GetMessageWindow(), WM_COVERARTUPDATE, (WPARAM)this, (LPARAM)source); } SAFERELEASE(decoder); SAFERELEASE(stream); } return hr == S_OK; }; ++extension; if (_wcsicmp(extension, L"mp3") == 0) { TagLib::ID3v2::AttachedPictureFrame *pictureFrame = nullptr; BYTE picturePriority = 0xFF; TagLib::MPEG::File mp3File(filePath); auto tag = mp3File.ID3v2Tag(); if (tag && tag->frameListMap().contains("APIC")) { for (auto frame : mp3File.ID3v2Tag()->frameListMap()["APIC"]) { auto picFrame = (TagLib::ID3v2::AttachedPictureFrame *)frame; BYTE priority = mID3CoverTypePriority[picFrame->type()]; if (priority < picturePriority) { pictureFrame = picFrame; picturePriority = priority; } } if (pictureFrame != nullptr) { return ParseImage((const BYTE *)pictureFrame->picture().data(), pictureFrame->picture().size()); } } } else if (_wcsicmp(extension, L"flac") == 0) { TagLib::FLAC::File flacFile(filePath); for (auto &picture : flacFile.pictureList()) { if (picture->type() == TagLib::FLAC::Picture::FrontCover) { return ParseImage((const BYTE *)picture->data().data(), picture->data().size()); } } } else if (_wcsicmp(extension, L"mp4") == 0 || _wcsicmp(extension, L"m4a") == 0) { TagLib::MP4::File mp4File(filePath); if (mp4File.tag()->itemListMap().contains("covr")) { auto map = mp4File.tag()->itemListMap()["covr"]; auto list = map.toCoverArtList(); auto cover = list.front(); return ParseImage((const BYTE *)cover.data().data(), cover.data().size()); } } return false; }
//@https://msdn.microsoft.com/de-de/library/windows/desktop/dd756686(v=vs.85).aspx HRESULT BitmapDecoder::LoadBitmapFromFile(ID2D1RenderTarget * pRenderTarget, PCWSTR uri, ID2D1Bitmap ** ppBitmap) { IWICImagingFactory* pFactory; HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pFactory ); //IWICStream *pStream = NULL; //? //IWICBitmapScaler *pScaler = NULL; //? IWICBitmapDecoder *pDecoder = NULL; if (SUCCEEDED(hr)) { hr = pFactory->CreateDecoderFromFilename(uri, NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &pDecoder); } IWICBitmapFrameDecode *pSource = NULL; if (SUCCEEDED(hr)) { hr = pDecoder->GetFrame(0, &pSource); } IWICFormatConverter *pConverter = NULL; if (SUCCEEDED(hr)) { hr = pFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut ); } if (SUCCEEDED(hr)) { pRenderTarget->CreateBitmapFromWicBitmap(pConverter, NULL, ppBitmap); } if (pDecoder != nullptr) { pDecoder->Release();//SafeRelease(&pDecoder); } if (pSource != nullptr) { pSource->Release(); } //SafeRelease(&pSource); // pStream->Release();//SafeRelease(&pStream); if(pConverter!= nullptr) { pConverter->Release(); } //SafeRelease(&pConverter); // pScaler->Release();//SafeRelease(&pScaler); if (pFactory != nullptr) { pFactory->Release(); } return hr; }
bool WICImageLoader::encodeImageData(std::string path, const unsigned char* data, size_t dataLen, WICPixelFormatGUID pixelFormat, int width, int height, GUID containerFormat) { assert(data != NULL); assert(dataLen > 0 && width > 0 && height > 0); IWICImagingFactory* pFact = getWICFactory(); HRESULT hr = E_FAIL; IWICStream* pStream = NULL; if (NULL != pFact) { hr = pFact->CreateStream(&pStream); } if (SUCCEEDED(hr)) { hr = pStream->InitializeFromFilename(StringUtf8ToWideChar(path).c_str(), GENERIC_WRITE); } IWICBitmapEncoder* pEnc = NULL; if (SUCCEEDED(hr)) { hr = pFact->CreateEncoder(containerFormat, NULL, &pEnc); } if (SUCCEEDED(hr)) { hr = pEnc->Initialize(pStream, WICBitmapEncoderNoCache); } IWICBitmapFrameEncode* pFrame = NULL; IPropertyBag2* pProp = NULL; if (SUCCEEDED(hr)) { hr = pEnc->CreateNewFrame(&pFrame, &pProp); } if (SUCCEEDED(hr)) { hr = pFrame->Initialize(pProp); } if (SUCCEEDED(hr)) { hr = pFrame->SetSize(width, height); } if (SUCCEEDED(hr)) { WICPixelFormatGUID targetFormat = pixelFormat; hr = pFrame->SetPixelFormat(&targetFormat); if (targetFormat != pixelFormat) { hr = E_INVALIDARG; } } if (SUCCEEDED(hr)) { size_t bpp = getBitsPerPixel(pixelFormat); size_t stride = (width * bpp + 7) / 8; hr = pFrame->WritePixels(height, static_cast<UINT>(stride), static_cast<UINT>(dataLen), (BYTE*)data); } if (SUCCEEDED(hr)) { hr = pFrame->Commit(); } if (SUCCEEDED(hr)) { hr = pEnc->Commit(); } SafeRelease(&pStream); SafeRelease(&pEnc); SafeRelease(&pFrame); SafeRelease(&pProp); return SUCCEEDED(hr); }
HRESULT SaveToImageFile() { HRESULT hr = S_OK; // // Create Factories // IWICImagingFactory *pWICFactory = NULL; ID2D1Factory *pD2DFactory = NULL; IDWriteFactory *pDWriteFactory = NULL; IWICBitmap *pWICBitmap = NULL; ID2D1RenderTarget *pRT = NULL; IDWriteTextFormat *pTextFormat = NULL; ID2D1PathGeometry *pPathGeometry = NULL; ID2D1GeometrySink *pSink = NULL; ID2D1GradientStopCollection *pGradientStops = NULL; ID2D1LinearGradientBrush *pLGBrush = NULL; ID2D1SolidColorBrush *pBlackBrush = NULL; IWICBitmapEncoder *pEncoder = NULL; IWICBitmapFrameEncode *pFrameEncode = NULL; IWICStream *pStream = NULL; hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void **>(&pWICFactory) ); if (SUCCEEDED(hr)) { hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory); } if (SUCCEEDED(hr)) { hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(pDWriteFactory), reinterpret_cast<IUnknown **>(&pDWriteFactory) ); } // // Create IWICBitmap and RT // static const UINT sc_bitmapWidth = 640; static const UINT sc_bitmapHeight = 480; if (SUCCEEDED(hr)) { hr = pWICFactory->CreateBitmap( sc_bitmapWidth, sc_bitmapHeight, GUID_WICPixelFormat32bppBGR, WICBitmapCacheOnLoad, &pWICBitmap ); } if (SUCCEEDED(hr)) { hr = pD2DFactory->CreateWicBitmapRenderTarget( pWICBitmap, D2D1::RenderTargetProperties(), &pRT ); } if (SUCCEEDED(hr)) { // // Create text format // static const WCHAR sc_fontName[] = L"Calibri"; static const FLOAT sc_fontSize = 50; hr = pDWriteFactory->CreateTextFormat( sc_fontName, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, sc_fontSize, L"", //locale &pTextFormat ); } if (SUCCEEDED(hr)) { pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER); pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); // // Create a path geometry representing an hour glass // hr = pD2DFactory->CreatePathGeometry(&pPathGeometry); } if (SUCCEEDED(hr)) { hr = pPathGeometry->Open(&pSink); } if (SUCCEEDED(hr)) { pSink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); pSink->BeginFigure( D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_FILLED ); pSink->AddLine(D2D1::Point2F(200, 0)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(150, 50), D2D1::Point2F(150, 150), D2D1::Point2F(200, 200)) ); pSink->AddLine(D2D1::Point2F(0, 200)); pSink->AddBezier( D2D1::BezierSegment( D2D1::Point2F(50, 150), D2D1::Point2F(50, 50), D2D1::Point2F(0, 0)) ); pSink->EndFigure(D2D1_FIGURE_END_CLOSED); hr = pSink->Close(); } if (SUCCEEDED(hr)) { // // Create a linear-gradient brush // static const D2D1_GRADIENT_STOP stops[] = { { 0.f, { 0.f, 1.f, 1.f, 1.f } }, { 1.f, { 0.f, 0.f, 1.f, 1.f } }, }; hr = pRT->CreateGradientStopCollection( stops, ARRAYSIZE(stops), &pGradientStops ); } if (SUCCEEDED(hr)) { hr = pRT->CreateLinearGradientBrush( D2D1::LinearGradientBrushProperties( D2D1::Point2F(100, 0), D2D1::Point2F(100, 200)), D2D1::BrushProperties(), pGradientStops, &pLGBrush ); } if (SUCCEEDED(hr)) { hr = pRT->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black), &pBlackBrush ); } if (SUCCEEDED(hr)) { // // Render into the bitmap // pRT->BeginDraw(); pRT->Clear(D2D1::ColorF(D2D1::ColorF::White)); D2D1_SIZE_F rtSize = pRT->GetSize(); // Set the world transform to a 45 degree rotation at the center of the render target // and write "Hello, World". pRT->SetTransform( D2D1::Matrix3x2F::Rotation( 45, D2D1::Point2F( rtSize.width / 2, rtSize.height / 2)) ); static const WCHAR sc_helloWorld[] = L"Hello, World!"; pRT->DrawText( sc_helloWorld, ARRAYSIZE(sc_helloWorld) - 1, pTextFormat, D2D1::RectF(0, 0, rtSize.width, rtSize.height), pBlackBrush); // // Reset back to the identity transform // pRT->SetTransform(D2D1::Matrix3x2F::Translation(0, rtSize.height - 200)); pRT->FillGeometry(pPathGeometry, pLGBrush); pRT->SetTransform(D2D1::Matrix3x2F::Translation(rtSize.width - 200, 0)); pRT->FillGeometry(pPathGeometry, pLGBrush); hr = pRT->EndDraw(); } if (SUCCEEDED(hr)) { // // Save image to file // hr = pWICFactory->CreateStream(&pStream); } WICPixelFormatGUID format = GUID_WICPixelFormatDontCare; if (SUCCEEDED(hr)) { static const WCHAR filename[] = L"output.png"; hr = pStream->InitializeFromFilename(filename, GENERIC_WRITE); } if (SUCCEEDED(hr)) { hr = pWICFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder); } if (SUCCEEDED(hr)) { hr = pEncoder->Initialize(pStream, WICBitmapEncoderNoCache); } if (SUCCEEDED(hr)) { hr = pEncoder->CreateNewFrame(&pFrameEncode, NULL); } if (SUCCEEDED(hr)) { hr = pFrameEncode->Initialize(NULL); } if (SUCCEEDED(hr)) { hr = pFrameEncode->SetSize(sc_bitmapWidth, sc_bitmapHeight); } if (SUCCEEDED(hr)) { hr = pFrameEncode->SetPixelFormat(&format); } if (SUCCEEDED(hr)) { hr = pFrameEncode->WriteSource(pWICBitmap, NULL); } if (SUCCEEDED(hr)) { hr = pFrameEncode->Commit(); } if (SUCCEEDED(hr)) { hr = pEncoder->Commit(); } SafeRelease(&pWICFactory); SafeRelease(&pD2DFactory); SafeRelease(&pDWriteFactory); SafeRelease(&pWICBitmap); SafeRelease(&pRT); SafeRelease(&pTextFormat); SafeRelease(&pPathGeometry); SafeRelease(&pSink); SafeRelease(&pGradientStops); SafeRelease(&pLGBrush); SafeRelease(&pBlackBrush); SafeRelease(&pEncoder); SafeRelease(&pFrameEncode); SafeRelease(&pStream); return hr; }
//--------------------------------------------------------------------------------- static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice, _In_opt_ ID3D11DeviceContext* d3dContext, _In_ IWICBitmapFrameDecode *frame, _Out_opt_ ID3D11Resource** texture, _Out_opt_ ID3D11ShaderResourceView** textureView, _In_ size_t maxsize ) { UINT width, height; HRESULT hr = frame->GetSize( &width, &height ); if ( FAILED(hr) ) return hr; assert( width > 0 && height > 0 ); if ( !maxsize ) { // This is a bit conservative because the hardware could support larger textures than // the Feature Level defined minimums, but doing it this way is much easier and more // performant for WIC than the 'fail and retry' model used by DDSTextureLoader switch( d3dDevice->GetFeatureLevel() ) { case D3D_FEATURE_LEVEL_9_1: case D3D_FEATURE_LEVEL_9_2: maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; case D3D_FEATURE_LEVEL_9_3: maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_10_1: maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; default: maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; break; } } assert( maxsize > 0 ); UINT twidth, theight; if ( width > maxsize || height > maxsize ) { float ar = static_cast<float>(height) / static_cast<float>(width); if ( width > height ) { twidth = static_cast<UINT>( maxsize ); theight = static_cast<UINT>( static_cast<float>(maxsize) * ar ); } else { theight = static_cast<UINT>( maxsize ); twidth = static_cast<UINT>( static_cast<float>(maxsize) / ar ); } assert( twidth <= maxsize && theight <= maxsize ); } else { twidth = width; theight = height; } UINT nwidth = 1; while(nwidth < twidth) nwidth <<= 1; if (nwidth != twidth) twidth = nwidth; UINT nheight = 1; while(nheight < theight) nheight <<= 1; if (nheight != theight) theight = nheight; // Determine format WICPixelFormatGUID pixelFormat; hr = frame->GetPixelFormat( &pixelFormat ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID convertGUID; memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) ); size_t bpp = 0; DXGI_FORMAT format = _WICToDXGI( pixelFormat ); if ( format == DXGI_FORMAT_UNKNOWN ) { for( size_t i=0; i < _countof(g_WICConvert); ++i ) { if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) ); format = _WICToDXGI( g_WICConvert[i].target ); assert( format != DXGI_FORMAT_UNKNOWN ); bpp = _WICBitsPerPixel( convertGUID ); break; } } if ( format == DXGI_FORMAT_UNKNOWN ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } else { bpp = _WICBitsPerPixel( pixelFormat ); } if ( !bpp ) return E_FAIL; // Verify our target format is supported by the current device // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) UINT support = 0; hr = d3dDevice->CheckFormatSupport( format, &support ); if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) { // Fallback to RGBA 32-bit format which is supported by all devices memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R8G8B8A8_UNORM; bpp = 32; } // Allocate temporary memory for image size_t rowPitch = ( twidth * bpp + 7 ) / 8; size_t imageSize = rowPitch * theight; std::unique_ptr<uint8_t[]> temp( new uint8_t[ imageSize ] ); // Load image data if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0 && twidth == width && theight == height ) { // No format conversion or resize needed hr = frame->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } else if ( twidth != width || theight != height ) { // Resize IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; ScopedObject<IWICBitmapScaler> scaler; hr = pWIC->CreateBitmapScaler( &scaler ); if ( FAILED(hr) ) return hr; hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID pfScaler; hr = scaler->GetPixelFormat( &pfScaler ); if ( FAILED(hr) ) return hr; if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 ) { // No format conversion needed hr = scaler->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } else { ScopedObject<IWICFormatConverter> FC; hr = pWIC->CreateFormatConverter( &FC ); if ( FAILED(hr) ) return hr; hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } } else { // Format conversion but no resize IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; ScopedObject<IWICFormatConverter> FC; hr = pWIC->CreateFormatConverter( &FC ); if ( FAILED(hr) ) return hr; hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } // See if format is supported for auto-gen mipmaps (varies by feature level) bool autogen = false; if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps { UINT fmtSupport = 0; hr = d3dDevice->CheckFormatSupport( format, &fmtSupport ); if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) { autogen = true; } } // Create texture D3D11_TEXTURE2D_DESC desc; desc.Width = twidth; desc.Height = theight; desc.MipLevels = (autogen) ? 0 : 1; desc.ArraySize = 1; desc.Format = format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = (autogen) ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE); desc.CPUAccessFlags = 0; desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = temp.get(); initData.SysMemPitch = static_cast<UINT>( rowPitch ); initData.SysMemSlicePitch = static_cast<UINT>( imageSize ); ID3D11Texture2D* tex = nullptr; hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex ); if ( SUCCEEDED(hr) && tex != 0 ) { if (textureView != 0) { D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; memset( &SRVDesc, 0, sizeof( SRVDesc ) ); SRVDesc.Format = format; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView ); if ( FAILED(hr) ) { tex->Release(); return hr; } if ( autogen ) { assert( d3dContext != 0 ); d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) ); d3dContext->GenerateMips( *textureView ); } } if (texture != 0) { *texture = tex; } else { #if defined(_DEBUG) || defined(PROFILE) tex->SetPrivateData( WKPDID_D3DDebugObjectName, sizeof("WICTextureLoader")-1, "WICTextureLoader" ); #endif tex->Release(); } } return hr; }
/// <summary> /// Load an image from a resource into a buffer /// </summary> /// <param name="resourceName">name of image resource to load</param> /// <param name="resourceType">type of resource to load</param> /// <param name="nOutputWidth">width (in pixels) of scaled output bitmap</param> /// <param name="nOutputHeight">height (in pixels) of scaled output bitmap</param> /// <param name="pOutputBuffer">buffer that will hold the loaded image</param> /// <returns>S_OK on success, otherwise failure code</returns> HRESULT CCoordinateMappingBasics::LoadResourceImage(PCWSTR resourceName, PCWSTR resourceType, UINT nOutputWidth, UINT nOutputHeight, RGBQUAD* pOutputBuffer) { IWICImagingFactory* pIWICFactory = NULL; IWICBitmapDecoder* pDecoder = NULL; IWICBitmapFrameDecode* pSource = NULL; IWICStream* pStream = NULL; IWICFormatConverter* pConverter = NULL; IWICBitmapScaler* pScaler = NULL; HRSRC imageResHandle = NULL; HGLOBAL imageResDataHandle = NULL; void *pImageFile = NULL; DWORD imageFileSize = 0; HRESULT hrCoInit = CoInitialize(NULL); HRESULT hr = hrCoInit; if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pIWICFactory); } if (SUCCEEDED(hr)) { // Locate the resource imageResHandle = FindResourceW(HINST_THISCOMPONENT, resourceName, resourceType); hr = imageResHandle ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Load the resource imageResDataHandle = LoadResource(HINST_THISCOMPONENT, imageResHandle); hr = imageResDataHandle ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Lock it to get a system memory pointer. pImageFile = LockResource(imageResDataHandle); hr = pImageFile ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Calculate the size. imageFileSize = SizeofResource(HINST_THISCOMPONENT, imageResHandle); hr = imageFileSize ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Create a WIC stream to map onto the memory. hr = pIWICFactory->CreateStream(&pStream); } if (SUCCEEDED(hr)) { // Initialize the stream with the memory pointer and size. hr = pStream->InitializeFromMemory( reinterpret_cast<BYTE*>(pImageFile), imageFileSize); } if (SUCCEEDED(hr)) { // Create a decoder for the stream. hr = pIWICFactory->CreateDecoderFromStream( pStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder); } if (SUCCEEDED(hr)) { // Create the initial frame. hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { // Convert the image format to 32bppPBGRA // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). hr = pIWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { hr = pIWICFactory->CreateBitmapScaler(&pScaler); } if (SUCCEEDED(hr)) { hr = pScaler->Initialize( pSource, nOutputWidth, nOutputHeight, WICBitmapInterpolationModeCubic ); } if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut); } UINT width = 0; UINT height = 0; if (SUCCEEDED(hr)) { hr = pConverter->GetSize(&width, &height); } // make sure the image scaled correctly so the output buffer is big enough if (SUCCEEDED(hr)) { if ((width != nOutputWidth) || (height != nOutputHeight)) { hr = E_FAIL; } } if (SUCCEEDED(hr)) { hr = pConverter->CopyPixels(NULL, width * sizeof(RGBQUAD), nOutputWidth * nOutputHeight * sizeof(RGBQUAD), reinterpret_cast<BYTE*>(pOutputBuffer)); } SafeRelease(pScaler); SafeRelease(pConverter); SafeRelease(pSource); SafeRelease(pDecoder); SafeRelease(pStream); SafeRelease(pIWICFactory); if (SUCCEEDED(hrCoInit)) { CoUninitialize(); } return hr; }