上面的答案是正确的方法,绝对不需要创建 50 行 if 语句。我必须承认这是我首先做的,但如果你得到一个新格式怎么办?你不会有答案的。这样做总是有效的。
感谢上面为解决方案发布此答案的人,但伪代码计算步幅有点错误。步幅本质上是编码所有位所需的字节数。因此,如果剩余的位少于 8 位,则需要多获得 1 个字节来管理它们。
这是 C++ 中的答案,主要是从 WIC 文档中复制的。该文档非常好,但正如所指出的,没有关于如何获取 IWICPixelFormatInfo 实例的示例。那是我无法得到的部分。
获取 BitsPerPixel 和 Stride:
第一:获取一个 IWICBitmapFrameDecode 作为 Bitmap 源
// Initialize COM.
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
IWICImagingFactory *piFactory = NULL;
IWICBitmapDecoder *piDecoder = NULL;
IWICBitmapFrameDecode *pIDecoderFrame = NULL;
GUID *pPixelFormat = NULL;
// Create the COM imaging factory.
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_WICImagingFactory,
NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&piFactory));
}
// Create the decoder.
if (SUCCEEDED(hr))
{
hr = piFactory->CreateDecoderFromFilename(L"test.tif", NULL, GENERIC_READ,
WICDecodeMetadataCacheOnDemand, //For JPEG lossless decoding/encoding.
&piDecoder);
}
// Retrieve the First frame from the image (tif might have more than 1)
if (SUCCEEDED(hr))
{
hr = pIDecoder->GetFrame(0, &pIDecoderFrame);
}
接下来获取像素格式和 BitsPerPixel
//////////////////////////////////////////////////////////////////////////////////
//// IMPORTANT PART OF THE ANSWER
//////////////////////////////////////////////////////////////////////////////////
// Get the Pixel Format
IDecoderFrame.GetPixelFormat(&pPixelFormat);
// Now get a POINTER to an instance of the Pixel Format
IWICComponentInfo *pIComponentInfo = NULL;
if (SUCCEEDED(hr))
{
hr = piFactory->CreateComponentInfo(pPixelFormat, &pIComponentInfo);
}
// Get IWICPixelFormatInfo from IWICComponentInfo
IWICPixelFormatInfo *pIPixelFormatInfo;
hr = pIComponentInfo->QueryInterface(__uuidof(IWICPixelFormatInfo), reinterpret_cast<void**>(&pIPixelFormatInfo));
// Now get the Bits Per Pixel
UInt32 bitsPerPixel;
if (SUCCEEDED(hr))
{
hr = pIPixelFormatInfo.GetBitsPerPixel(&bitsPerPixel);
}
你有两个选择:
//Manually Calculate the Stride from the Bits Per Pixel.
UINT width;
UINT height;
if (SUCCEEDED(hr))
{
hr = IDecoderFrame.GetSize(&width, &height);
}
float totalPixels = bitsPerPixel * width + 7; // +7 forces to next byte if needed
UINT stride = totalPixels / 8;
// ... now do something with stride-You can stop here if you dont need the bitmap
//////////////////////////////////////////////////////////////////////////////////
或者,如果你想使用图像,你可以创建它......
// Alternative is to get a lock, by you need to actually create the bitmap
// by calling CreateBitmapFromSource. IF you do want to create the bitmap,
// then by all means create one.
IWICBitmap *pIBitmap = NULL;
IWICBitmapLock *pILock = NULL;
WICRect rcLock = { 0, 0, width, height }; // from GetSize earlier
// Create the bitmap from the image frame.
if (SUCCEEDED(hr))
{
hr = m_pIWICFactory->CreateBitmapFromSource(
pIDecoderFrame, // Create a bitmap from the image frame
WICBitmapCacheOnDemand, // Cache metadata when needed
&pIBitmap); // Pointer to the bitmap
}
if (SUCCEEDED(hr))
{
hr = pIBitmap->Lock(&rcLock, WICBitmapLockWrite, &pILock);
}
// Now get the stride from the lock.
piLock.GetStride(&stride);
/// END OF ANSWER
/////////////////////////////////////////////////////////////////////////////////
别忘了收拾...
SafeRelease(&pILock);
...
更新:2020 年。对于托马斯。
当我回答这个问题时,我实际上正在编写 Delphi 代码,所以我正在翻译回 c++:
鉴于此 Pascal 标头:
function CreateComponentInfo(const clsidComponent: TGUID;
out ppIInfo: IWICComponentInfo): HRESULT; stdcall;
大概翻译成:
HRESULT CreateComponentInfo(pGUID *clsidComponent, pIWICComponentInfo *ppIInfo);
我怀疑在上面的示例中我没有正确引用指针。
这是工作的德尔福代码(对象帕斯卡)
// from the already created frame interface
var lPixelFormat: TGUID;
iFrame.GetPixelFormat(lPixelFormat);
if WCIUnSuccessful(lImagingFactory.CreateComponentInfo(lPixelFormat,
iComponentInfo)) then
exit;
iPixelformatInfo := iComponentInfo as IWICPixelFormatInfo;
if WCIUnSuccessful(iPixelformatInfo.GetBitsPerPixel(result.BitsPerPixel))
then
exit;
所以调用可以采用 GUID(如果你得到正确的指针)