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;
}