HBITMAP ImageDecoder::convertFrameToBitmap(IWICBitmapFrameDecode *frame)
{
	IWICBitmapSource *bitmapSource = frame;
	if (FAILED(WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, frame, &bitmapSource)))
	{
		throw Exception("could not convert bitmap");
	}

	UINT width = 0;
	UINT height = 0;
	if (FAILED(bitmapSource->GetSize(&width, &height)) || width == 0 || height == 0)
	{
		throw Exception("could not get image size");
	}

	std::vector<BYTE> buffer(width * height * 4);
	if (FAILED(bitmapSource->CopyPixels(NULL, width * 4, buffer.size(), &buffer[0])))
	{
		throw Exception("could not get image size");
	}

	bitmapSource->Release();

	return CreateBitmap(width, height, 1, 32, &buffer[0]);
}
//----------------------------------------------------------------------------
Texture2* WICFileIO::Load(std::string const& filename, bool wantMipmaps)
{
    // Start COM and create WIC.
    ComInitializer comInitializer;
    if (!comInitializer.IsInitialized())
    {
        LogError("Unable to initialize COM for WIC.");
        return nullptr;
    }

    // Create a WIC imaging factory.
    ComObject<IWICImagingFactory> wicFactory;
    HRESULT hr = ::CoCreateInstance(CLSID_WICImagingFactory, nullptr,
        CLSCTX_INPROC_SERVER, IID_IWICImagingFactory,
        reinterpret_cast<LPVOID*>(&wicFactory));
    if (FAILED(hr))
    {
        LogError("Unable to create WIC imaging factory.");
        return nullptr;
    }

    // Create a decoder based on the file name.
    std::wstring wfilename = Environment::Convert(filename);
    ComObject<IWICBitmapDecoder> wicDecoder;
    hr = wicFactory->CreateDecoderFromFilename(wfilename.c_str(),
        nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &wicDecoder);
    if (FAILED(hr))
    {
        LogError("wicFactory->CreateDecoderFromFilename failed (" +
            filename + ").");
        return nullptr;
    }

    // Create a WIC decoder.
    ComObject<IWICBitmapFrameDecode> wicFrameDecode;
    hr = wicDecoder->GetFrame(0, &wicFrameDecode);
    if (FAILED(hr))
    {
        LogError("wicDecoder->GetFrame failed.");
        return nullptr;
    }

    // Get the pixel format of the image.
    WICPixelFormatGUID wicSourceGUID;
    hr = wicFrameDecode->GetPixelFormat(&wicSourceGUID);
    if (FAILED(hr))
    {
        LogError("wicFrameDecode->GetPixelFormat failed.");
        return nullptr;
    }

    // Find the supported WIC input pixel format that matches a Texture2
    // format.  If a matching format is not found, the returned texture
    // is an R8G8B8A8 format with texels converted from the source format.
    WICPixelFormatGUID wicConvertGUID = GUID_WICPixelFormat32bppRGBA;
    DFType gtformat = DF_R8G8B8A8_UNORM;
    for (int i = 0; i < NUM_LOAD_FORMATS; ++i)
    {
        if (IsEqualGUID(wicSourceGUID, *msLoadFormatMap[i].wicInputGUID))
        {
            // Determine whether there is a conversion format.
            if (msLoadFormatMap[i].wicConvertGUID)
            {
                wicConvertGUID = *msLoadFormatMap[i].wicConvertGUID;
            }
            else
            {
                wicConvertGUID = *msLoadFormatMap[i].wicInputGUID;
            }
            gtformat = msLoadFormatMap[i].gtFormat;
            break;
        }
    }

    // The wicFrameDecode value is used for no conversion.  If the decoder
    // does not support the format in the texture, then a conversion is
    // required.
    IWICBitmapSource* wicBitmapSource = wicFrameDecode;
    ComObject<IWICFormatConverter> wicFormatConverter;
    if (!IsEqualGUID(wicSourceGUID, wicConvertGUID))
    {
        // Create a WIC format converter.
        hr = wicFactory->CreateFormatConverter(&wicFormatConverter);
        if (FAILED(hr))
        {
            LogError("wicFactory->CreateFormatConverter failed.");
            return false;
        }

        // Initialize format converter to convert the input texture format
        // to the nearest format supported by the decoder.
        hr = wicFormatConverter->Initialize(wicFrameDecode, wicConvertGUID,
            WICBitmapDitherTypeNone, nullptr, 0.0,
            WICBitmapPaletteTypeCustom);
        if (FAILED(hr))
        {
            LogError("wicFormatConverter->Initialize failed.");
            return false;
        }

        // Use the format converter.
        wicBitmapSource = wicFormatConverter;
    }

    // Get the image dimensions.
    UINT width, height;
    hr = wicBitmapSource->GetSize(&width, &height);
    if (FAILED(hr))
    {
        LogError("wicBitmapSource->GetSize failed.");
        return nullptr;
    }

    // Create the 2D texture and compute the stride and image size.
    std::unique_ptr<Texture2> texture(new Texture2(gtformat, width,
        height, wantMipmaps));
    UINT const stride = width * texture->GetElementSize();
    UINT const imageSize = stride * height;

    // Copy the pixels from the decoder to the texture.
    hr = wicBitmapSource->CopyPixels(nullptr, stride, imageSize,
        texture->Get<BYTE>());
    if (FAILED(hr))
    {
        LogError("wicBitmapSource->CopyPixels failed.");
        return nullptr;
    }

    return texture.release();
}
示例#3
0
	HBITMAP ImageUtil::LoadImage(string path) {
		size_t pathFileExtDot = path.find_last_of('.');
		if (pathFileExtDot == string::npos || pathFileExtDot + 1 >=
			path.length())
			throw INETRException("[imgLoadFailed]");
		string ext = path.substr(pathFileExtDot + 1);

		const GUID *decoderCLSID = nullptr;
		if (ext == "png")
			decoderCLSID = &CLSID_WICPngDecoder;
		else if (ext == "bmp")
			decoderCLSID = &CLSID_WICBmpDecoder;
		else if (ext == "gif")
			decoderCLSID = &CLSID_WICGifDecoder;
		else if (ext == "jpg" || ext == "jpeg")
			decoderCLSID = &CLSID_WICJpegDecoder;

		if (decoderCLSID == nullptr)
			throw INETRException("[unsupportedImg]: " + ext);

		IStream *pngFileStream;
		if (FAILED(SHCreateStreamOnFile(path.c_str(), STGM_READ,
			&pngFileStream)))
			throw INETRException("[imgLoadFailed]:\n" + path);

		IWICBitmapDecoder *bmpDecoder = nullptr;
		if (FAILED(CoCreateInstance(*decoderCLSID, nullptr,
			CLSCTX_INPROC_SERVER, __uuidof(bmpDecoder),
			reinterpret_cast<void**>(&bmpDecoder))))
			throw INETRException("[imgDecFailed]");

		if (FAILED(bmpDecoder->Initialize(pngFileStream,
			WICDecodeMetadataCacheOnLoad))) {

			bmpDecoder->Release();
			throw INETRException("[imgDecFailed]");
		}

		UINT bmpFrameCount = 0;
		if (FAILED(bmpDecoder->GetFrameCount(&bmpFrameCount)) && bmpFrameCount
			!= 1) {

			bmpDecoder->Release();
			throw INETRException("[imgDecFailed]");
		}

		IWICBitmapFrameDecode *bmpFrame = nullptr;
		if (FAILED(bmpDecoder->GetFrame(0, &bmpFrame))) {
			bmpDecoder->Release();
			throw INETRException("[imgDecFailed]");
		}

		IWICBitmapSource *bmpSource = nullptr;
		WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, bmpFrame,
			&bmpSource);

		bmpFrame->Release();
		bmpDecoder->Release();

		UINT width = 0, height = 0;
		if (FAILED(bmpSource->GetSize(&width, &height)) || width == 0 || height
			== 0)
			throw INETRException("[imgDecFailed]");

		BITMAPINFO bmInfo;
		ZeroMemory(&bmInfo, sizeof(bmInfo));
		bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
		bmInfo.bmiHeader.biWidth = width;
		bmInfo.bmiHeader.biHeight = -((LONG)height);
		bmInfo.bmiHeader.biPlanes = 1;
		bmInfo.bmiHeader.biBitCount = 32;
		bmInfo.bmiHeader.biCompression = BI_RGB;

		HBITMAP hbmp = nullptr;

		void *imageBits = nullptr;
		HDC screenDC = GetDC(nullptr);
		hbmp = CreateDIBSection(screenDC, &bmInfo, DIB_RGB_COLORS, &imageBits,
			nullptr, 0);
		ReleaseDC(nullptr, screenDC);
		if (hbmp == nullptr)
			throw INETRException("[imgDecFailed]");

		const UINT bmpStride = width * 4;
		const UINT bmpSize = bmpStride * height;
		if (FAILED(bmpSource->CopyPixels(nullptr, bmpStride, bmpSize,
			static_cast<BYTE*>(imageBits)))) {

			DeleteObject(hbmp);
			hbmp = nullptr;
			throw INETRException("[imgDecFailed]");
		}

		bmpSource->Release();

		return hbmp;
	}