我使用ATL:CImage
类来解码png图像。
但是加载后图像会转换为RGBA
(每像素4个字节)图像。
ATL:CImage img;
img.Load((LPCTSTR)("test.png")); // 8bit grayscale
成功加载后,m_nBPP成员为32(也称为4字节),m_bHasAlphaChannel为真。但它们应该是8而且是假的。
由于隐式转换,我们需要手动将RGBA转换回8BPP。我正在处理超过400张图片。所以这是应用程序的主要减速。
在Visual Studio论坛上,我读到这是GDI +中的一个问题,因为它隐式将所有灰度PNG图像转换为32bpp ARGB
。
有解决方法吗?
答案 0 :(得分:0)
如果您想要控制,请使用Windows Imaging Component。您需要创建Decoder并检索您感兴趣的image frame(s)。PNG Format Overview概述了PNG支持。
以下示例代码打开灰度PNG图像,并显示有关媒体的信息:
#include <windows.h>
#include <wincodec.h>
#pragma comment(lib, "Windowscodecs.lib")
#include <iostream>
int main() {
::CoInitialize( NULL );
创建工厂COM服务器:
IWICImagingFactory* pFactory = NULL;
HRESULT hr = ::CoCreateInstance( CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(void**)&pFactory );
根据图像源创建解码器:
IWICBitmapDecoder* pDecoder = NULL;
if ( SUCCEEDED( hr ) ) {
hr = pFactory->CreateDecoderFromFilename( L"test.png",
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnDemand,
&pDecoder );
}
虽然PNG文件始终包含单个图像,但有一些图像格式允许在单个文件中存储多个图像。通常,您将不得不查询帧计数并迭代所有帧,一个接一个地解码:
UINT frameCount = 0;
if ( SUCCEEDED( hr ) ) {
hr = pDecoder->GetFrameCount( &frameCount );
}
if ( SUCCEEDED( hr ) ) {
std::wcout << L"Framecount: " << frameCount << std::endl;
for ( UINT frameIndex = 0; frameIndex < frameCount; ++frameIndex ) {
std::wcout << std::endl << L"Frame " << frameIndex << L":" << std::endl;
IWICBitmapFrameDecode* pFrame = NULL;
hr = pDecoder->GetFrame( frameIndex, &pFrame );
转储图片尺寸以供说明之用:
if ( SUCCEEDED( hr ) ) {
UINT width = 0, height = 0;
hr = pFrame->GetSize( &width, &height );
if ( SUCCEEDED( hr ) ) {
std::wcout << L" width: " << width <<
L", height: " << height << std::endl;
}
}
要验证图像数据是否未被更改,请转储bpp和通道计数信息:
if ( SUCCEEDED( hr ) ) {
WICPixelFormatGUID pixelFormat = { 0 };
pFrame->GetPixelFormat( &pixelFormat );
if ( SUCCEEDED( hr ) ) {
// Translate pixelformat to bpp
IWICComponentInfo* pComponentInfo = NULL;
hr = pFactory->CreateComponentInfo( pixelFormat, &pComponentInfo );
IWICPixelFormatInfo* pPixelFormatInfo = NULL;
if ( SUCCEEDED( hr ) ) {
hr = pComponentInfo->QueryInterface( &pPixelFormatInfo );
}
UINT bpp = 0;
if ( SUCCEEDED( hr ) ) {
hr = pPixelFormatInfo->GetBitsPerPixel( &bpp );
}
if ( SUCCEEDED( hr ) ) {
std::wcout << L" bpp: " << bpp << std::endl;
}
UINT channelCount = 0;
if ( SUCCEEDED( hr ) ) {
hr = pPixelFormatInfo->GetChannelCount( &channelCount );
}
if ( SUCCEEDED( hr ) ) {
std::wcout << L" Channel Count: " << channelCount << std::endl;
}
// Cleanup
if ( pPixelFormatInfo != NULL ) { pPixelFormatInfo->Release(); }
if ( pComponentInfo != NULL ) { pComponentInfo->Release(); }
}
}
剩下的就是资源清理:
// Cleanup
if ( pFrame != NULL ) { pFrame->Release(); }
}
}
// Cleanup
if ( pDecoder != NULL ) { pDecoder->Release(); }
if ( pFactory != NULL ) { pFactory->Release(); }
return 0;
}
针对此图片运行此代码
产生以下输出:
Framecount: 1 Frame 0: width: 50, height: 50 bpp: 8 Channel Count: 1