WIC 的 JPEG 解码问题
JPEG Decoding problems with WIC
我目前正在尝试使用 WIC 将图像从磁盘加载到内存中。我使用 MSDN 文档 here 编写我的代码。
加载 PNG 图像一切正常。加载 JPEG 图像没有任何错误,但不会产生正确的结果!有趣的是,当我将图像从 JPEG 转换为 PNG(使用 irfan 视图)时,错误仍然存在。
考虑以下测试图像:
如您所见,图像在 x 方向上缩小了,所有颜色信息都消失了。然而,当你放大时,你可以看到仍然有一些颜色存在,但它看起来不像预期的那样:
(将图像作为纹理上传到 GPU 时问题仍然存在)
为了便于阅读,我删除了我的 WIC 加载代码,省略了错误处理和资源释放:
// CoInitialize(NULL) called in main
// WIC Factory
IWICImagingFactory* ptrFactory = NULL;
CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&ptrFactory));
// Open decoder
IWICBitmapDecoder* ptrDecoder = NULL;
ptrFactory->CreateDecoderFromFilename(fileName, NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &ptrDecoder)
// Get first frame
IWICBitmapFrameDecode* ptrFrameDecoder = NULL;
ptrDecoder->GetFrame(0, &ptrFrameDecoder));
// Read formate
WICPixelFormatGUID frameNativeFormat;
ptrFrameDecoder->GetPixelFormat(&frameNativeFormat);
// Computing target format selectConverterWic(...) and selectConverterDx(...) are just some very basic functions for selecting the right convert to formate by iterating over an std::array witch contains the mappings suggested by the MSDC article mentioned above
WICPixelFormatGUID targetFormat;
DXGI_FORMAT targetFormatDx;
if (!selectConverterDx(frameNativeFormat, &targetFormatDx)) {
// Try to find WIC to WIC converter
selectConverterWic(frameNativeFormat, &targetFormat)
selectConverterDx(targetFormat, &targetFormatDx)
}else {
memcpy(&targetFormat, &frameNativeFormat, sizeof(GUID));
}
// Get format info
IWICComponentInfo* ptrCmpInfo = NULL;
ptrFactory->CreateComponentInfo(targetFormat, &ptrCmpInfo);
// Get type
WICComponentType ptrCmpType;
ptrCmpInfo->GetComponentType(&ptrCmpType);
// Get info from type
IWICPixelFormatInfo* ptrFormatInfo = NULL;
ptrCmpInfo->QueryInterface(IID_PPV_ARGS(&ptrFormatInfo));
// Get BBP
UINT uiBitsPerPixel;
ptrFormatInfo->GetBitsPerPixel(&uiBitsPerPixel);
// ID3D12Device->CheckFeatureSupport(...) and fallback omitted
// Image size
UINT width, height;
ptrFrameDecoder->GetSize(&width, &height);
// Tempory memory allocation
UINT rowPitch = (width * uiBitsPerPixel + 7) / 8;
SIZE_T imageSize = (SIZE_T)rowPitch * (SIZE_T)height;
void* workMemory = malloc(imageSize);
// Check if direct copy is possible
if (memcmp(&frameNativeFormat, &targetFormat, sizeof(GUID)) == 0){
ptrFrameDecoder->CopyPixels(NULL, rowPitch, (UINT)imageSize, (BYTE*)workMemory);
}else{
// Format conversion (Got never hit by a jpeg file; I tried to force it but results weren't right asswell)
IWICFormatConverter* ptrFormatConverter = NULL;
ptrFactory->CreateFormatConverter(&ptrFormatConverter);
ptrFormatConverter->Initialize(ptrFrameDecoder, targetFormat, WICBitmapDitherTypeErrorDiffusion, NULL, 0, WICBitmapPaletteTypeCustom);
ptrFormatConverter->CopyPixels(NULL, rowPitch, (UINT)imageSize, (BYTE*)workMemory);
}
// I inspected workMemory and got the result you saw above
// Some more code for copying data to user supplied parameters
在此先感谢您的帮助!
上面的代码完全可以正常工作!问题出在省略的 DirectX 12 功能支持检查中:
ID3D12Device->CheckFeatureSupport(...)
我忘记了一个反转导致执行了以下代码片段
memcpy(&frameNativeFormat, &GUID_WICPixelFormat32bppRGBA, sizeof(GUID));
targetFormatDx = DXGI_FORMAT_R8G8B8A8_UNORM;
uiBitsPerPixel = 32;
第二个错误是我覆盖了“frameNativeFormat”而不是“targetFormat”,这导致没有执行任何转换(至少对于 JPEG)。
解决这两个问题给了我一个不错的纹理加载算法(至少 Windows)
我目前正在尝试使用 WIC 将图像从磁盘加载到内存中。我使用 MSDN 文档 here 编写我的代码。
加载 PNG 图像一切正常。加载 JPEG 图像没有任何错误,但不会产生正确的结果!有趣的是,当我将图像从 JPEG 转换为 PNG(使用 irfan 视图)时,错误仍然存在。
考虑以下测试图像:
如您所见,图像在 x 方向上缩小了,所有颜色信息都消失了。然而,当你放大时,你可以看到仍然有一些颜色存在,但它看起来不像预期的那样:
(将图像作为纹理上传到 GPU 时问题仍然存在)
为了便于阅读,我删除了我的 WIC 加载代码,省略了错误处理和资源释放:
// CoInitialize(NULL) called in main
// WIC Factory
IWICImagingFactory* ptrFactory = NULL;
CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&ptrFactory));
// Open decoder
IWICBitmapDecoder* ptrDecoder = NULL;
ptrFactory->CreateDecoderFromFilename(fileName, NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &ptrDecoder)
// Get first frame
IWICBitmapFrameDecode* ptrFrameDecoder = NULL;
ptrDecoder->GetFrame(0, &ptrFrameDecoder));
// Read formate
WICPixelFormatGUID frameNativeFormat;
ptrFrameDecoder->GetPixelFormat(&frameNativeFormat);
// Computing target format selectConverterWic(...) and selectConverterDx(...) are just some very basic functions for selecting the right convert to formate by iterating over an std::array witch contains the mappings suggested by the MSDC article mentioned above
WICPixelFormatGUID targetFormat;
DXGI_FORMAT targetFormatDx;
if (!selectConverterDx(frameNativeFormat, &targetFormatDx)) {
// Try to find WIC to WIC converter
selectConverterWic(frameNativeFormat, &targetFormat)
selectConverterDx(targetFormat, &targetFormatDx)
}else {
memcpy(&targetFormat, &frameNativeFormat, sizeof(GUID));
}
// Get format info
IWICComponentInfo* ptrCmpInfo = NULL;
ptrFactory->CreateComponentInfo(targetFormat, &ptrCmpInfo);
// Get type
WICComponentType ptrCmpType;
ptrCmpInfo->GetComponentType(&ptrCmpType);
// Get info from type
IWICPixelFormatInfo* ptrFormatInfo = NULL;
ptrCmpInfo->QueryInterface(IID_PPV_ARGS(&ptrFormatInfo));
// Get BBP
UINT uiBitsPerPixel;
ptrFormatInfo->GetBitsPerPixel(&uiBitsPerPixel);
// ID3D12Device->CheckFeatureSupport(...) and fallback omitted
// Image size
UINT width, height;
ptrFrameDecoder->GetSize(&width, &height);
// Tempory memory allocation
UINT rowPitch = (width * uiBitsPerPixel + 7) / 8;
SIZE_T imageSize = (SIZE_T)rowPitch * (SIZE_T)height;
void* workMemory = malloc(imageSize);
// Check if direct copy is possible
if (memcmp(&frameNativeFormat, &targetFormat, sizeof(GUID)) == 0){
ptrFrameDecoder->CopyPixels(NULL, rowPitch, (UINT)imageSize, (BYTE*)workMemory);
}else{
// Format conversion (Got never hit by a jpeg file; I tried to force it but results weren't right asswell)
IWICFormatConverter* ptrFormatConverter = NULL;
ptrFactory->CreateFormatConverter(&ptrFormatConverter);
ptrFormatConverter->Initialize(ptrFrameDecoder, targetFormat, WICBitmapDitherTypeErrorDiffusion, NULL, 0, WICBitmapPaletteTypeCustom);
ptrFormatConverter->CopyPixels(NULL, rowPitch, (UINT)imageSize, (BYTE*)workMemory);
}
// I inspected workMemory and got the result you saw above
// Some more code for copying data to user supplied parameters
在此先感谢您的帮助!
上面的代码完全可以正常工作!问题出在省略的 DirectX 12 功能支持检查中:
ID3D12Device->CheckFeatureSupport(...)
我忘记了一个反转导致执行了以下代码片段
memcpy(&frameNativeFormat, &GUID_WICPixelFormat32bppRGBA, sizeof(GUID));
targetFormatDx = DXGI_FORMAT_R8G8B8A8_UNORM;
uiBitsPerPixel = 32;
第二个错误是我覆盖了“frameNativeFormat”而不是“targetFormat”,这导致没有执行任何转换(至少对于 JPEG)。
解决这两个问题给了我一个不错的纹理加载算法(至少 Windows)