Example #1
1
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;
}
Example #2
0
/// <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);
}
Example #3
0
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;
}
Example #5
0
	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);
}
Example #10
0
    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);
    }
Example #11
0
/// <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;
}
Example #12
0
    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);
    }
Example #13
0
    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;
    }
Example #14
0
// ----------------------------------------------------------------
//	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;
}
Example #15
0
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;
}
Example #17
0
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();
}
Example #18
0
//---------------------------------------------------------------------------------
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;
}
Example #22
0
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;
}
Example #23
0
	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;
	}
Example #24
0
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;
}
Example #25
0
/// <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;
}
Example #26
0
    //@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;
}
Example #29
0
//---------------------------------------------------------------------------------
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;
}