cwebp (windows): fix alpha image import on XP

Query the converter to ensure the format is supported; add BGR formats
as RGBA was failing for PNG on XP

Fixes issue 129

Change-Id: I02e0d74b3b21337bc5fffd6a5dc158b7809b9aa9
This commit is contained in:
James Zern 2012-10-19 18:34:06 -07:00
parent 1765cb1ca5
commit eda8ee4b3b

View File

@ -113,6 +113,12 @@ static int ReadYUV(FILE* in_file, WebPPicture* const pic) {
#define MAKE_REFGUID(x) &(x) #define MAKE_REFGUID(x) &(x)
#endif #endif
typedef struct WICFormatImporter {
const GUID* pixel_format;
int bytes_per_pixel;
int (*import)(WebPPicture* const, const uint8_t* const, int);
} WICFormatImporter;
static HRESULT OpenInputStream(const char* filename, IStream** ppStream) { static HRESULT OpenInputStream(const char* filename, IStream** ppStream) {
HRESULT hr = S_OK; HRESULT hr = S_OK;
IFS(SHCreateStreamOnFileA(filename, STGM_READ, ppStream)); IFS(SHCreateStreamOnFileA(filename, STGM_READ, ppStream));
@ -123,6 +129,31 @@ static HRESULT OpenInputStream(const char* filename, IStream** ppStream) {
static HRESULT ReadPictureWithWIC(const char* filename, static HRESULT ReadPictureWithWIC(const char* filename,
WebPPicture* const pic, int keep_alpha) { WebPPicture* const pic, int keep_alpha) {
// From Microsoft SDK 7.0a -- wincodec.h
// Create local copies for compatibility when building against earlier
// versions of the SDK.
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppBGR_,
0x6fddc324, 0x4e03, 0x4bfe,
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c);
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_,
0x6fddc324, 0x4e03, 0x4bfe,
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d);
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_,
0x6fddc324, 0x4e03, 0x4bfe,
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f);
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_,
0xf5c7ad2d, 0x6a8d, 0x43dd,
0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9);
const WICFormatImporter alphaFormatImporters[] = {
{ &GUID_WICPixelFormat32bppBGRA_, 4, WebPPictureImportBGRA },
{ &GUID_WICPixelFormat32bppRGBA_, 4, WebPPictureImportRGBA },
{ NULL, 0, NULL },
};
const WICFormatImporter nonAlphaFormatImporters[] = {
{ &GUID_WICPixelFormat24bppBGR_, 3, WebPPictureImportBGR },
{ &GUID_WICPixelFormat24bppRGB_, 3, WebPPictureImportRGB },
{ NULL, 0, NULL },
};
HRESULT hr = S_OK; HRESULT hr = S_OK;
IWICBitmapFrameDecode* pFrame = NULL; IWICBitmapFrameDecode* pFrame = NULL;
IWICFormatConverter* pConverter = NULL; IWICFormatConverter* pConverter = NULL;
@ -133,6 +164,7 @@ static HRESULT ReadPictureWithWIC(const char* filename,
UINT width = 0, height = 0; UINT width = 0, height = 0;
BYTE* rgb = NULL; BYTE* rgb = NULL;
WICPixelFormatGUID srcPixelFormat = { 0 }; WICPixelFormatGUID srcPixelFormat = { 0 };
const WICFormatImporter* importer = NULL;
GUID srcContainerFormat = { 0 }; GUID srcContainerFormat = { 0 };
const GUID* alphaContainers[] = { const GUID* alphaContainers[] = {
&GUID_ContainerFormatBmp, &GUID_ContainerFormatBmp,
@ -141,18 +173,6 @@ static HRESULT ReadPictureWithWIC(const char* filename,
}; };
int has_alpha = 0; int has_alpha = 0;
int i, stride; int i, stride;
// From Microsoft SDK 7.0a
// Create local copies for compatibility when building against earlier
// versions of the SDK.
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_,
0x6fddc324, 0x4e03, 0x4bfe,
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d);
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_,
0xf5c7ad2d, 0x6a8d, 0x43dd,
0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9);
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_,
0x6fddc324, 0x4e03, 0x4bfe,
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f);
IFS(CoInitialize(NULL)); IFS(CoInitialize(NULL));
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL, IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
@ -195,15 +215,27 @@ static HRESULT ReadPictureWithWIC(const char* filename,
// Prepare for pixel format conversion (if necessary). // Prepare for pixel format conversion (if necessary).
IFS(IWICImagingFactory_CreateFormatConverter(pFactory, &pConverter)); IFS(IWICImagingFactory_CreateFormatConverter(pFactory, &pConverter));
for (importer = has_alpha ? alphaFormatImporters : nonAlphaFormatImporters;
hr == S_OK && importer->import != NULL; ++importer) {
BOOL canConvert;
const HRESULT cchr = IWICFormatConverter_CanConvert(
pConverter,
MAKE_REFGUID(srcPixelFormat),
MAKE_REFGUID(*importer->pixel_format),
&canConvert);
if (SUCCEEDED(cchr) && canConvert) break;
}
if (importer->import == NULL) hr = E_FAIL;
IFS(IWICFormatConverter_Initialize(pConverter, (IWICBitmapSource*)pFrame, IFS(IWICFormatConverter_Initialize(pConverter, (IWICBitmapSource*)pFrame,
has_alpha ? MAKE_REFGUID(GUID_WICPixelFormat32bppRGBA_) importer->pixel_format,
: MAKE_REFGUID(GUID_WICPixelFormat24bppRGB_),
WICBitmapDitherTypeNone, WICBitmapDitherTypeNone,
NULL, 0.0, WICBitmapPaletteTypeCustom)); NULL, 0.0, WICBitmapPaletteTypeCustom));
// Decode. // Decode.
IFS(IWICFormatConverter_GetSize(pConverter, &width, &height)); IFS(IWICFormatConverter_GetSize(pConverter, &width, &height));
stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb); stride = importer->bytes_per_pixel * width * sizeof(*rgb);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
rgb = (BYTE*)malloc(stride * height); rgb = (BYTE*)malloc(stride * height);
if (rgb == NULL) if (rgb == NULL)
@ -217,8 +249,7 @@ static HRESULT ReadPictureWithWIC(const char* filename,
int ok; int ok;
pic->width = width; pic->width = width;
pic->height = height; pic->height = height;
ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride) ok = importer->import(pic, rgb, stride);
: WebPPictureImportRGB(pic, rgb, stride);
if (!ok) if (!ok)
hr = E_FAIL; hr = E_FAIL;
} }