ImageInfo DirectXTileRenderer::LoadImageCommon()

in cpp/AdvancedColorImages/AdvancedColorImages/DirectXTileRenderer.cpp [393:515]


ImageInfo DirectXTileRenderer::LoadImageCommon(_In_ IWICBitmapSource* source)
{
	m_imageInfo = {};

	// Attempt to read the embedded color profile from the image; only valid for WIC images.
	com_ptr<IWICBitmapFrameDecode> frame;
	HRESULT hr = (reinterpret_cast<::IUnknown*>(source)->QueryInterface(winrt::guid_of<IWICBitmapFrameDecode>(),
		reinterpret_cast<void**>(winrt::put_abi(frame))));
	if (hr >= 0)
	{
		check_hresult(
			m_wicFactory->CreateColorContext(m_wicColorContext.put())
		);

		IWICColorContext* temp = m_wicColorContext.get();

		check_hresult(
			frame->GetColorContexts(
				1,
				&temp,
				&m_imageInfo.numProfiles
			)
		);
	}

	// Check whether the image data is natively stored in a floating-point format, and
	// decode to the appropriate WIC pixel format.

	WICPixelFormatGUID pixelFormat;
	check_hresult(
		source->GetPixelFormat(&pixelFormat)
	);

	com_ptr<IWICComponentInfo> componentInfo;
	check_hresult(
		m_wicFactory->CreateComponentInfo(
			pixelFormat,
			componentInfo.put()
		)
	);

	com_ptr<IWICPixelFormatInfo2> pixelFormatInfo = componentInfo.as<IWICPixelFormatInfo2>();


	WICPixelFormatNumericRepresentation formatNumber;
	check_hresult(
		pixelFormatInfo->GetNumericRepresentation(&formatNumber)
	);

	check_hresult(pixelFormatInfo->GetBitsPerPixel(&m_imageInfo.bitsPerPixel));

	// Calculate the bits per channel (bit depth) using GetChannelMask.
	// This accounts for nonstandard color channel packing and padding, e.g. 32bppRGB.
	unsigned char channelMaskBytes[sc_MaxBytesPerPixel];
	ZeroMemory(channelMaskBytes, ARRAYSIZE(channelMaskBytes));
	unsigned int maskSize;

	check_hresult(
		pixelFormatInfo->GetChannelMask(
			0,  // Read the first color channel.
			ARRAYSIZE(channelMaskBytes),
			channelMaskBytes,
			&maskSize)
	);

	// Count up the number of bits set in the mask for the first color channel.
	for (unsigned int i = 0; i < maskSize * 8; i++)
	{
		unsigned int byte = i / 8;
		unsigned int bit = i % 8;
		if ((channelMaskBytes[byte] & (1 << bit)) != 0)
		{
			m_imageInfo.bitsPerChannel += 1;
		}
	}

	m_imageInfo.isFloat = (WICPixelFormatNumericRepresentationFloat == formatNumber) ? true : false;

	// When decoding, preserve the numeric representation (float vs. non-float)
	// of the native image data. This avoids WIC performing an implicit gamma conversion
	// which occurs when converting between a fixed-point/integer pixel format (sRGB gamma)
	// and a float-point pixel format (linear gamma). Gamma adjustment, if specified by
	// the ICC profile, will be performed by the Direct2D color management effect.

	WICPixelFormatGUID fmt = {};
	if (m_imageInfo.isFloat)
	{
		fmt = GUID_WICPixelFormat64bppPRGBAHalf; // Equivalent to DXGI_FORMAT_R16G16B16A16_FLOAT.
	}
	else
	{
		fmt = GUID_WICPixelFormat64bppPRGBA; // Equivalent to DXGI_FORMAT_R16G16B16A16_UNORM.
											 // Many SDR images (e.g. JPEG) use <=32bpp, so it
											 // is possible to further optimize this for memory usage.
	}

	check_hresult(
		m_wicFactory->CreateFormatConverter(m_formatConvert.put())
	);

	check_hresult(
		m_formatConvert->Initialize(
			source,
			fmt,
			WICBitmapDitherTypeNone,
			nullptr,
			0.0f,
			WICBitmapPaletteTypeCustom
		)
	);

	UINT width;
	UINT height;
	check_hresult(
		m_formatConvert->GetSize(&width, &height)
	);

	m_imageInfo.size = Size(static_cast<float>(width), static_cast<float>(height));

	PopulateImageInfoACKind(&m_imageInfo);

	return m_imageInfo;
}