format_16bppGray,
format_16bppBGR555,
format_16bppBGR565,
+ format_16bppBGRA5551,
format_24bppBGR,
format_32bppBGR,
format_32bppBGRA,
+ format_32bppPBGRA,
format_48bppRGB,
format_64bppRGBA,
+ format_32bppCMYK,
};
typedef HRESULT (*copyfunc)(struct FormatConverter *This, const WICRect *prc,
};
typedef struct FormatConverter {
- const IWICFormatConverterVtbl *lpVtbl;
+ IWICFormatConverter IWICFormatConverter_iface;
LONG ref;
IWICBitmapSource *source;
const struct pixelformatinfo *dst_format, *src_format;
CRITICAL_SECTION lock; /* must be held when initialized */
} FormatConverter;
-static void make_grayscale_palette(WICColor *colors, UINT num_colors)
+static inline FormatConverter *impl_from_IWICFormatConverter(IWICFormatConverter *iface)
{
- int i, v;
- for (i=0; i<num_colors; i++)
- {
- v = i * 255 / (num_colors-1);
- colors[i] = 0xff000000 | v<<16 | v<<8 | v;
- }
+ return CONTAINING_RECORD(iface, FormatConverter, IWICFormatConverter_iface);
}
static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRect *prc,
IWICPalette *palette;
UINT actualcolors;
- if (source_format == format_1bppIndexed)
- {
- res = PaletteImpl_Create(&palette);
- if (FAILED(res)) return res;
+ res = PaletteImpl_Create(&palette);
+ if (FAILED(res)) return res;
+ if (source_format == format_1bppIndexed)
res = IWICBitmapSource_CopyPalette(This->source, palette);
- if (SUCCEEDED(res))
- res = IWICPalette_GetColors(palette, 2, colors, &actualcolors);
+ else
+ res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedBW, FALSE);
- IWICPalette_Release(palette);
+ if (SUCCEEDED(res))
+ res = IWICPalette_GetColors(palette, 2, colors, &actualcolors);
- if (FAILED(res)) return res;
- }
- else
- {
- colors[0] = 0xff000000;
- colors[1] = 0xffffffff;
- }
+ IWICPalette_Release(palette);
+ if (FAILED(res)) return res;
srcstride = (prc->Width+7)/8;
srcdatasize = srcstride * prc->Height;
srcrow = srcdata;
dstrow = pbBuffer;
for (y=0; y<prc->Height; y++) {
- srcbyte=(const BYTE*)srcrow;
+ srcbyte = srcrow;
dstpixel=(DWORD*)dstrow;
for (x=0; x<prc->Width; x+=8) {
BYTE srcval;
IWICPalette *palette;
UINT actualcolors;
- if (source_format == format_2bppIndexed)
- {
- res = PaletteImpl_Create(&palette);
- if (FAILED(res)) return res;
+ res = PaletteImpl_Create(&palette);
+ if (FAILED(res)) return res;
+ if (source_format == format_2bppIndexed)
res = IWICBitmapSource_CopyPalette(This->source, palette);
- if (SUCCEEDED(res))
- res = IWICPalette_GetColors(palette, 4, colors, &actualcolors);
+ else
+ res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray4, FALSE);
- IWICPalette_Release(palette);
+ if (SUCCEEDED(res))
+ res = IWICPalette_GetColors(palette, 4, colors, &actualcolors);
- if (FAILED(res)) return res;
- }
- else
- make_grayscale_palette(colors, 4);
+ IWICPalette_Release(palette);
+ if (FAILED(res)) return res;
srcstride = (prc->Width+3)/4;
srcdatasize = srcstride * prc->Height;
srcrow = srcdata;
dstrow = pbBuffer;
for (y=0; y<prc->Height; y++) {
- srcbyte=(const BYTE*)srcrow;
+ srcbyte = srcrow;
dstpixel=(DWORD*)dstrow;
for (x=0; x<prc->Width; x+=4) {
BYTE srcval;
IWICPalette *palette;
UINT actualcolors;
- if (source_format == format_4bppIndexed)
- {
- res = PaletteImpl_Create(&palette);
- if (FAILED(res)) return res;
+ res = PaletteImpl_Create(&palette);
+ if (FAILED(res)) return res;
+ if (source_format == format_4bppIndexed)
res = IWICBitmapSource_CopyPalette(This->source, palette);
- if (SUCCEEDED(res))
- res = IWICPalette_GetColors(palette, 16, colors, &actualcolors);
+ else
+ res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray16, FALSE);
- IWICPalette_Release(palette);
+ if (SUCCEEDED(res))
+ res = IWICPalette_GetColors(palette, 16, colors, &actualcolors);
- if (FAILED(res)) return res;
- }
- else
- make_grayscale_palette(colors, 16);
+ IWICPalette_Release(palette);
+ if (FAILED(res)) return res;
srcstride = (prc->Width+1)/2;
srcdatasize = srcstride * prc->Height;
srcrow = srcdata;
dstrow = pbBuffer;
for (y=0; y<prc->Height; y++) {
- srcbyte=(const BYTE*)srcrow;
+ srcbyte = srcrow;
dstpixel=(DWORD*)dstrow;
for (x=0; x<prc->Width; x+=2) {
BYTE srcval;
srcrow = srcdata;
dstrow = pbBuffer;
for (y=0; y<prc->Height; y++) {
- srcbyte=(const BYTE*)srcrow;
+ srcbyte = srcrow;
dstpixel=(DWORD*)dstrow;
for (x=0; x<prc->Width; x++)
{
srcrow = srcdata;
dstrow = pbBuffer;
for (y=0; y<prc->Height; y++) {
- srcbyte=(const BYTE*)srcrow;
+ srcbyte = srcrow;
dstpixel=(DWORD*)dstrow;
for (x=0; x<prc->Width; x++)
*dstpixel++ = colors[*srcbyte++];
srcrow = srcdata;
dstrow = pbBuffer;
for (y=0; y<prc->Height; y++) {
- srcbyte=(const BYTE*)srcrow;
+ srcbyte = srcrow;
dstpixel=(DWORD*)dstrow;
for (x=0; x<prc->Width; x++)
{
return res;
}
return S_OK;
+ case format_16bppBGRA5551:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+ BYTE *srcdata;
+ UINT srcstride, srcdatasize;
+ const BYTE *srcrow;
+ const WORD *srcpixel;
+ BYTE *dstrow;
+ DWORD *dstpixel;
+
+ srcstride = 2 * prc->Width;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
+
+ if (SUCCEEDED(res))
+ {
+ srcrow = srcdata;
+ dstrow = pbBuffer;
+ for (y=0; y<prc->Height; y++) {
+ srcpixel=(const WORD*)srcrow;
+ dstpixel=(DWORD*)dstrow;
+ for (x=0; x<prc->Width; x++) {
+ WORD srcval;
+ srcval=*srcpixel++;
+ *dstpixel++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */
+ ((srcval << 9) & 0xf80000) | /* r */
+ ((srcval << 4) & 0x070000) | /* r - 3 bits */
+ ((srcval << 6) & 0x00f800) | /* g */
+ ((srcval << 1) & 0x000700) | /* g - 3 bits */
+ ((srcval << 3) & 0x0000f8) | /* b */
+ ((srcval >> 2) & 0x000007); /* b - 3 bits */
+ }
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
+
+ return res;
+ }
+ return S_OK;
case format_24bppBGR:
if (prc)
{
if (prc)
return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
return S_OK;
+ case format_32bppPBGRA:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
+ if (FAILED(res)) return res;
+
+ for (y=0; y<prc->Height; y++)
+ for (x=0; x<prc->Width; x++)
+ {
+ BYTE alpha = pbBuffer[cbStride*y+4*x+3];
+ if (alpha != 0 && alpha != 255)
+ {
+ pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * 255 / alpha;
+ pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * 255 / alpha;
+ pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * 255 / alpha;
+ }
+ }
+ }
+ return S_OK;
case format_48bppRGB:
if (prc)
{
return res;
}
return S_OK;
+ case format_32bppCMYK:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
+ if (FAILED(res)) return res;
+
+ for (y=0; y<prc->Height; y++)
+ for (x=0; x<prc->Width; x++)
+ {
+ BYTE *pixel = pbBuffer+cbStride*y+4*x;
+ BYTE c=pixel[0], m=pixel[1], y=pixel[2], k=pixel[3];
+ pixel[0] = (255-y)*(255-k)/255; /* blue */
+ pixel[1] = (255-m)*(255-k)/255; /* green */
+ pixel[2] = (255-c)*(255-k)/255; /* red */
+ pixel[3] = 255; /* alpha */
+ }
+ }
+ return S_OK;
default:
return WINCODEC_ERR_UNSUPPORTEDOPERATION;
}
{
case format_32bppBGR:
case format_32bppBGRA:
+ case format_32bppPBGRA:
if (prc)
return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
return S_OK;
}
}
+static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICRect *prc,
+ UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
+{
+ HRESULT hr;
+
+ switch (source_format)
+ {
+ case format_32bppPBGRA:
+ if (prc)
+ return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
+ return S_OK;
+ default:
+ hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
+ if (SUCCEEDED(hr) && prc)
+ {
+ UINT x, y;
+
+ for (y=0; y<prc->Height; y++)
+ for (x=0; x<prc->Width; x++)
+ {
+ BYTE alpha = pbBuffer[cbStride*y+4*x+3];
+ if (alpha != 255)
+ {
+ pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255;
+ pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255;
+ pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255;
+ }
+ }
+ }
+ return hr;
+ }
+}
+
static const struct pixelformatinfo supported_formats[] = {
{format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL},
{format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL},
{format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL},
{format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL},
{format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL},
+ {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, NULL},
{format_24bppBGR, &GUID_WICPixelFormat24bppBGR, NULL},
{format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR},
{format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA},
+ {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA},
{format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL},
{format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL},
+ {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL},
{0}
};
static HRESULT WINAPI FormatConverter_QueryInterface(IWICFormatConverter *iface, REFIID iid,
void **ppv)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
if (!ppv) return E_INVALIDARG;
IsEqualIID(&IID_IWICBitmapSource, iid) ||
IsEqualIID(&IID_IWICFormatConverter, iid))
{
- *ppv = This;
+ *ppv = &This->IWICFormatConverter_iface;
}
else
{
static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter *iface)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) refcount=%u\n", iface, ref);
static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) refcount=%u\n", iface, ref);
static HRESULT WINAPI FormatConverter_GetSize(IWICFormatConverter *iface,
UINT *puiWidth, UINT *puiHeight)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
static HRESULT WINAPI FormatConverter_GetPixelFormat(IWICFormatConverter *iface,
WICPixelFormatGUID *pPixelFormat)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
TRACE("(%p,%p): stub\n", iface, pPixelFormat);
static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface,
double *pDpiX, double *pDpiY)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
TRACE("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
+ WICRect rc;
+ HRESULT hr;
TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
if (This->source)
+ {
+ if (!prc)
+ {
+ UINT width, height;
+ hr = IWICBitmapSource_GetSize(This->source, &width, &height);
+ if (FAILED(hr)) return hr;
+ rc.X = 0;
+ rc.Y = 0;
+ rc.Width = width;
+ rc.Height = height;
+ prc = &rc;
+ }
+
return This->dst_format->copy_function(This, prc, cbStride, cbBufferSize,
pbBuffer, This->src_format->format);
+ }
else
return WINCODEC_ERR_NOTINITIALIZED;
}
IWICBitmapSource *pISource, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
IWICPalette *pIPalette, double alphaThresholdPercent, WICBitmapPaletteType paletteTranslate)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
const struct pixelformatinfo *srcinfo, *dstinfo;
static INT fixme=0;
GUID srcFormat;
if (!srcinfo)
{
res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+ FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat));
goto end;
}
if (!dstinfo)
{
res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+ FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat));
goto end;
}
This->source = pISource;
}
else
+ {
+ FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
res = WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ }
end:
REFWICPixelFormatGUID srcPixelFormat, REFWICPixelFormatGUID dstPixelFormat,
BOOL *pfCanConvert)
{
- FormatConverter *This = (FormatConverter*)iface;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
const struct pixelformatinfo *srcinfo, *dstinfo;
TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(srcPixelFormat),
debugstr_guid(dstPixelFormat), pfCanConvert);
srcinfo = get_formatinfo(srcPixelFormat);
- if (!srcinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+ if (!srcinfo)
+ {
+ FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat));
+ return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+ }
dstinfo = get_formatinfo(dstPixelFormat);
- if (!dstinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+ if (!dstinfo)
+ {
+ FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat));
+ return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+ }
if (dstinfo->copy_function &&
SUCCEEDED(dstinfo->copy_function(This, NULL, 0, 0, NULL, dstinfo->format)))
*pfCanConvert = TRUE;
else
+ {
+ FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat), debugstr_guid(dstPixelFormat));
*pfCanConvert = FALSE;
+ }
return S_OK;
}
This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter));
if (!This) return E_OUTOFMEMORY;
- This->lpVtbl = &FormatConverter_Vtbl;
+ This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl;
This->ref = 1;
This->source = NULL;
InitializeCriticalSection(&This->lock);
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock");
- ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
- IUnknown_Release((IUnknown*)This);
+ ret = IWICFormatConverter_QueryInterface(&This->IWICFormatConverter_iface, iid, ppv);
+ IWICFormatConverter_Release(&This->IWICFormatConverter_iface);
return ret;
}