我正在尝试从位图资源加载ID2D1Bitmap。为此,我咨询了MSDN guide,告诉我在Direct2D使用之前使用Windows Imaging Component(IWIC)来处理图像。
然而,当我调用CreateDecoderFromStream()
时它失败了,它返回一条奇怪的错误消息 - 0x88982f50
- 它什么也没告诉我。我搜索了Google并使用了DirectX Error Lookup。 DirectX错误查找工具只告诉我:
HRESULT: 0x88982f50 (2291674960)
Name: Unknown
Description: n/a
Severity code: Failed
Facility Code: FACILITY_DWRITE (2200)
Error Code: 0x2f50 (12112)
这是我用来尝试从资源加载ID2D1Bitmap的代码:
int LoadBitmapFromResource( IWICImagingFactory *pIWICFactory, ID2D1RenderTarget *pRT, int resID, ID2D1Bitmap **ppD2DBitmap )
{
int errmsg;
HRSRC hbmp;
HGLOBAL hbmpdata;
void *pbmp; //system memory pointer to bitmap resource
DWORD bmpsize;
IWICStream *pStream;
IWICBitmapDecoder *pbmpdecoder;
IWICBitmapFrameDecode *pSource;
IWICFormatConverter *pConverter;
hbmp = FindResourceW( GetModuleHandleW(NULL), MAKEINTRESOURCEW(resID), RT_BITMAP );
if( NULL == hbmp )
{
printf("LoadBitmapFromResource::FindResourceW() error: %d\r\n", GetLastError() );
return GetLastError();
}
hbmpdata = LoadResource( GetModuleHandleW(NULL), hbmp );
if( NULL == hbmpdata )
{
printf("LoadBitmapFromResource::LoadResource() error: %d\r\n", GetLastError() );
return GetLastError();
}
pbmp = LockResource( hbmpdata );
if( NULL == pbmp )
{
printf("LoadBitmapFromResource::LockResource() error: %d\r\n", GetLastError() );
return GetLastError();
}
bmpsize = SizeofResource( GetModuleHandleW(NULL), hbmp );
if( NULL == bmpsize )
{
printf("LoadBitmapFromResource::SizeofResource() error: %d\r\n", GetLastError() );
return GetLastError();
}
errmsg = pIWICFactory->CreateStream( &pStream );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::CreateStream() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = pStream->InitializeFromMemory( (BYTE*)pbmp, bmpsize );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::InitializeFromMemory() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = pIWICFactory->CreateDecoderFromStream( pStream, NULL, WICDecodeMetadataCacheOnLoad, &pbmpdecoder );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::CreateDecoderFromStream() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = pbmpdecoder->GetFrame( 0, &pSource );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::GetFrame() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = pIWICFactory->CreateFormatConverter( &pConverter );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::CreateFormatConverter() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = pConverter->Initialize( pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeMedianCut );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::Initialize() error: %x\r\n", errmsg );
return errmsg;
}
errmsg = pRT->CreateBitmapFromWicBitmap( pConverter, ppD2DBitmap );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::CreateBitmapFromWicBitmap() error: %x\r\n", errmsg );
return errmsg;
}
pConverter->Release();
pSource->Release();
pbmpdecoder->Release();
pStream->Release();
return 0;
}
答案 0 :(得分:0)
事实证明我不应该将WIC解码器用于我的位图资源,因为它显然是无法解码的原始像素数据。
答案 1 :(得分:0)
(我理解这个有点旧的帖子,但是我把它放在这里,以防它帮助别人或OP,如果他碰巧再次看到这个。)
我有与您使用WIC从exe文件中的资源加载ID2D1Bitmap的完全相同的代码,除了我的工作完美。我可以完美地从我的exe文件中加载一个位图。我看到的代码与我的不同之处在于,我使用reinterpret_cast而不是使用(BYTE *)强制转换。
所以而不是
errmsg = pStream->InitializeFromMemory( (BYTE*)pbmp, bmpsize );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::InitializeFromMemory() error: %x\r\n", errmsg );
return errmsg;
}
我会尝试做
errmsg = pStream->InitializeFromMemory( reinterpret_cast<BYTE*>(pbmp), bmpsize );
if( !SUCCEEDED(errmsg) )
{
printf("LoadBitmapFromResource::InitializeFromMemory() error: %x\r\n", errmsg );
return errmsg;
}
答案 2 :(得分:0)
出现这个问题是因为 LockResource() 返回的位图数据不包含前 14 个字节的位图头。您可以比较从 LockResource() 返回的数据和原始位图文件以查看。下面是简单的C语言测试代码,可以在SizeofResource()之后添加,然后查看out.bmp文件,这是一个无效的位图文件。并且由于图像数据错误,它没有任何有效的解码器 (WINCODEC_ERR_COMPONENTNOTFOUND)。
FILE* file;
fopen_s( &file, "out.bmp", "wb");
fwrite((const char*)(pbmp), 1, bmpsize, file);
fclose(file);
有两个明显的解决方案。
不要从资源创建 IWICStream/IWICBitmapDecoder。相反,直接使用外部位图文件来创建它们。检查 MSDN 的示例代码。 https://docs.microsoft.com/en-us/windows/win32/direct2d/how-to-load-a-direct2d-bitmap-from-a-file
在资源数据前添加位图头。类似的东西:
BITMAPFILEHEADER header;
header.bfType = 0x4D42; // 'BM'
header.bfSize = bmpsize + 14; // resource data size + 14 bytes header
header.bfReserved1 = 0;
header.bfReserved2 = 0;
header.bfOffBits = 14 + 40; // details in bitmap format
BYTE* buffer = new BYTE[header.bfSize];
memcpy(buffer, &header, 14);
memcpy(buffer + 14, pbmp, bmpsize);
// Initialize the stream with the memory pointer and size.
hr = pStream->InitializeFromMemory(
reinterpret_cast<BYTE*>(buffer),
header.bfSize
);
请注意,在 IWICStream 的生命周期中,“缓冲区”必须处于活动状态。