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);
}
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;
}
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);
}
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;
}
bool WICImageLoader::encodeImageData(std::string path, ImageBlob 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 = S_FALSE;
	IWICStream* pStream = NULL;

	if(NULL != pFact)
	{
		hr = pFact->CreateStream(&pStream);
	}

	if(SUCCEEDED(hr))
	{
		std::wstring wpath;
		wpath.assign(path.begin(), path.end());
		hr = pStream->InitializeFromFilename(wpath.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))
	{
		hr = pFrame->SetPixelFormat(&pixelFormat);
	}

	if(SUCCEEDED(hr))
	{
		size_t bpp = getBitsPerPixel(pixelFormat);
		size_t stride = (width * bpp + 7) / 8;

		hr = pFrame->WritePixels(height, stride, 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);
}