Commit d6c2734d authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

windowscodecs: Add support for converting to 8bppIndexed format.

parent 84459ba9
......@@ -76,7 +76,7 @@ typedef struct FormatConverter {
const struct pixelformatinfo *dst_format, *src_format;
WICBitmapDitherType dither;
double alpha_threshold;
WICBitmapPaletteType palette_type;
IWICPalette *palette;
CRITICAL_SECTION lock; /* must be held when initialized */
} FormatConverter;
......@@ -1219,11 +1219,99 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec
return hr;
}
static UINT rgb_to_palette_index(BYTE bgr[3], WICColor *colors, UINT count)
{
UINT best_diff, best_index, i;
best_diff = ~0;
best_index = 0;
for (i = 0; i < count; i++)
{
BYTE pal_r, pal_g, pal_b;
UINT diff_r, diff_g, diff_b, diff;
pal_r = colors[i] >> 16;
pal_g = colors[i] >> 8;
pal_b = colors[i];
diff_r = bgr[2] - pal_r;
diff_g = bgr[1] - pal_g;
diff_b = bgr[0] - pal_b;
diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b;
if (diff == 0) return i;
if (diff < best_diff)
{
best_diff = diff;
best_index = i;
}
}
return best_index;
}
static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WICRect *prc,
UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
{
HRESULT hr;
BYTE *srcdata;
WICColor colors[256];
UINT srcstride, srcdatasize, count;
if (source_format == format_8bppIndexed)
{
if (prc)
return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
return S_OK;
}
if (!prc)
return copypixels_to_24bppBGR(This, NULL, cbStride, cbBufferSize, pbBuffer, source_format);
if (!This->palette) return WINCODEC_ERR_WRONGSTATE;
hr = IWICPalette_GetColors(This->palette, 256, colors, &count);
if (hr != S_OK) return hr;
if (!count) return WINCODEC_ERR_WRONGSTATE;
srcstride = 3 * prc->Width;
srcdatasize = srcstride * prc->Height;
srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format);
if (SUCCEEDED(hr) && prc)
{
INT x, y;
BYTE *src = srcdata, *dst = pbBuffer;
for (y = 0; y < prc->Height; y++)
{
BYTE *bgr = src;
for (x = 0; x < prc->Width; x++)
{
dst[x] = rgb_to_palette_index(bgr, colors, count);
bgr += 3;
}
src += srcstride;
dst += cbStride;
}
}
HeapFree(GetProcessHeap(), 0, srcdata);
return hr;
}
static const struct pixelformatinfo supported_formats[] = {
{format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL},
{format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL},
{format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL},
{format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, NULL},
{format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed},
{format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL},
{format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL},
{format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL},
......@@ -1300,6 +1388,7 @@ static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock);
if (This->source) IWICBitmapSource_Release(This->source);
if (This->palette) IWICPalette_Release(This->palette);
HeapFree(GetProcessHeap(), 0, This);
}
......@@ -1348,10 +1437,16 @@ static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface,
}
static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface,
IWICPalette *pIPalette)
IWICPalette *palette)
{
FIXME("(%p,%p): stub\n", iface, pIPalette);
return E_NOTIMPL;
FormatConverter *This = impl_from_IWICFormatConverter(iface);
TRACE("(%p,%p)\n", iface, palette);
if (!palette) return E_INVALIDARG;
if (!This->palette) return WINCODEC_ERR_WRONGSTATE;
return IWICPalette_InitializeFromPalette(palette, This->palette);
}
static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
......@@ -1384,19 +1479,52 @@ static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
}
static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
IWICBitmapSource *pISource, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
IWICPalette *pIPalette, double alphaThresholdPercent, WICBitmapPaletteType paletteTranslate)
IWICBitmapSource *source, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
IWICPalette *palette, double alpha_threshold, WICBitmapPaletteType palette_type)
{
FormatConverter *This = impl_from_IWICFormatConverter(iface);
const struct pixelformatinfo *srcinfo, *dstinfo;
static INT fixme=0;
GUID srcFormat;
HRESULT res=S_OK;
HRESULT res;
TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source, debugstr_guid(dstFormat),
dither, palette, alpha_threshold, palette_type);
if (!palette)
{
res = PaletteImpl_Create(&palette);
if (res != S_OK) return res;
switch (palette_type)
{
case WICBitmapPaletteTypeCustom:
IWICPalette_Release(palette);
palette = NULL;
res = S_OK;
break;
case WICBitmapPaletteTypeMedianCut:
{
UINT bpp;
res = get_pixelformat_bpp(dstFormat, &bpp);
if (res == S_OK && bpp <= 8)
res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE);
break;
}
TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface, pISource, debugstr_guid(dstFormat),
dither, pIPalette, alphaThresholdPercent, paletteTranslate);
default:
res = IWICPalette_InitializePredefined(palette, palette_type, FALSE);
break;
}
if (pIPalette && !fixme++) FIXME("ignoring palette\n");
if (res != S_OK)
{
IWICPalette_Release(palette);
return res;
}
}
else
IWICPalette_AddRef(palette);
EnterCriticalSection(&This->lock);
......@@ -1406,7 +1534,7 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
goto end;
}
res = IWICBitmapSource_GetPixelFormat(pISource, &srcFormat);
res = IWICBitmapSource_GetPixelFormat(source, &srcFormat);
if (FAILED(res)) goto end;
srcinfo = get_formatinfo(&srcFormat);
......@@ -1427,13 +1555,13 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
if (dstinfo->copy_function)
{
IWICBitmapSource_AddRef(pISource);
IWICBitmapSource_AddRef(source);
This->src_format = srcinfo;
This->dst_format = dstinfo;
This->dither = dither;
This->alpha_threshold = alphaThresholdPercent;
This->palette_type = paletteTranslate;
This->source = pISource;
This->alpha_threshold = alpha_threshold;
This->palette = palette;
This->source = source;
}
else
{
......@@ -1512,6 +1640,7 @@ HRESULT FormatConverter_CreateInstance(REFIID iid, void** ppv)
This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl;
This->ref = 1;
This->source = NULL;
This->palette = NULL;
InitializeCriticalSection(&This->lock);
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment