https://git.reactos.org/?p=reactos.git;a=commitdiff;h=197ed01e95f242af87a39…
commit 197ed01e95f242af87a3905d83c2cd22326a7668
Author: Mikhail Tyukin <mishakeys20(a)gmail.com>
AuthorDate: Sun Jan 26 12:59:50 2025 -0500
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Fri Feb 7 16:57:02 2025 +0100
[WINDOWSCODECS][WINDOWSCODECSEXT] Sync to wine-10.0 (#7665)
---
dll/win32/windowscodecs/CMakeLists.txt | 19 +-
dll/win32/windowscodecs/bitmap.c | 55 +-
dll/win32/windowscodecs/bmpdecode.c | 82 +-
dll/win32/windowscodecs/bmpencode.c | 44 +-
dll/win32/windowscodecs/clipper.c | 12 +-
dll/win32/windowscodecs/clsfactory.c | 24 +-
dll/win32/windowscodecs/colorcontext.c | 24 +-
dll/win32/windowscodecs/colortransform.c | 10 +-
dll/win32/windowscodecs/converter.c | 276 +-
dll/win32/windowscodecs/ddsformat.c | 2162 +++++++++++++
dll/win32/windowscodecs/decoder.c | 811 +++++
dll/win32/windowscodecs/encoder.c | 903 ++++++
dll/win32/windowscodecs/fliprotate.c | 14 +-
dll/win32/windowscodecs/gifformat.c | 521 ++--
dll/win32/windowscodecs/icnsformat.c | 743 -----
dll/win32/windowscodecs/icoformat.c | 40 +-
dll/win32/windowscodecs/imgfactory.c | 470 ++-
dll/win32/windowscodecs/info.c | 309 +-
dll/win32/windowscodecs/jpegformat.c | 1562 ----------
dll/win32/windowscodecs/libjpeg.c | 662 ++++
dll/win32/windowscodecs/libpng.c | 842 +++++
dll/win32/windowscodecs/libtiff.c | 1352 +++++++++
dll/win32/windowscodecs/main.c | 230 +-
dll/win32/windowscodecs/metadatahandler.c | 295 +-
dll/win32/windowscodecs/metadataquery.c | 580 ++--
dll/win32/windowscodecs/palette.c | 56 +-
dll/win32/windowscodecs/pngformat.c | 2093 +------------
dll/win32/windowscodecs/precomp.h | 3 +-
dll/win32/windowscodecs/propertybag.c | 33 +-
dll/win32/windowscodecs/proxy.c | 2 -
dll/win32/windowscodecs/regsvr.c | 207 +-
dll/win32/windowscodecs/scaler.c | 28 +-
dll/win32/windowscodecs/stream.c | 108 +-
dll/win32/windowscodecs/tgaformat.c | 34 +-
dll/win32/windowscodecs/tiffformat.c | 2385 ---------------
dll/win32/windowscodecs/ungif.c | 93 +-
dll/win32/windowscodecs/ungif.h | 7 +-
dll/win32/windowscodecs/uuid.c | 36 +
dll/win32/windowscodecs/wincodecs_common.c | 211 ++
dll/win32/windowscodecs/wincodecs_common.h | 214 ++
dll/win32/windowscodecs/wincodecs_private.h | 325 +-
dll/win32/windowscodecs/windowscodecs_wincodec.idl | 32 +-
dll/win32/windowscodecsext/main.c | 18 -
media/doc/WINESYNC.txt | 4 +-
.../winetests/windowscodecs/CMakeLists.txt | 8 +-
modules/rostests/winetests/windowscodecs/bitmap.c | 460 +--
.../rostests/winetests/windowscodecs/bmpformat.c | 647 +++-
.../rostests/winetests/windowscodecs/converter.c | 578 ++--
.../rostests/winetests/windowscodecs/ddsformat.c | 1579 ++++++++++
.../rostests/winetests/windowscodecs/gifformat.c | 198 +-
.../rostests/winetests/windowscodecs/icoformat.c | 20 +-
modules/rostests/winetests/windowscodecs/info.c | 263 +-
.../rostests/winetests/windowscodecs/jpegformat.c | 38 +-
.../rostests/winetests/windowscodecs/metadata.c | 3204 ++++++++++++++------
modules/rostests/winetests/windowscodecs/palette.c | 154 +-
.../rostests/winetests/windowscodecs/pngformat.c | 203 +-
.../rostests/winetests/windowscodecs/propertybag.c | 56 +-
modules/rostests/winetests/windowscodecs/stream.c | 438 +--
.../rostests/winetests/windowscodecs/testlist.c | 4 +
.../rostests/winetests/windowscodecs/tiffformat.c | 344 ++-
.../rostests/winetests/windowscodecs/wmpformat.c | 182 ++
.../winetests/windowscodecsext/CMakeLists.txt | 1 +
.../winetests/windowscodecsext/transform.c | 12 +-
sdk/include/psdk/CMakeLists.txt | 1 +
sdk/include/psdk/dxgiformat.idl | 145 +
sdk/include/psdk/wincodec.idl | 137 +
sdk/include/psdk/wincodecsdk.idl | 82 +
sdk/tools/winesync/windowscodecs.cfg | 10 +
68 files changed, 16270 insertions(+), 10425 deletions(-)
diff --git a/dll/win32/windowscodecs/CMakeLists.txt
b/dll/win32/windowscodecs/CMakeLists.txt
index ee7ff716e3b..c8e043b4979 100644
--- a/dll/win32/windowscodecs/CMakeLists.txt
+++ b/dll/win32/windowscodecs/CMakeLists.txt
@@ -1,12 +1,12 @@
add_definitions(
-D__WINESRC__
- -D__ROS_LONG64__
-DENTRY_PREFIX=WIC_
-DPROXY_DELEGATION
-DWINE_REGISTER_DLL)
remove_definitions(-D_WIN32_WINNT=0x502)
+remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS)
add_definitions(-D_WIN32_WINNT=0x600)
include_directories(
@@ -27,13 +27,17 @@ list(APPEND SOURCE
colorcontext.c
colortransform.c
converter.c
+ ddsformat.c
+ decoder.c
+ encoder.c
fliprotate.c
gifformat.c
- icnsformat.c
icoformat.c
imgfactory.c
info.c
- jpegformat.c
+ libjpeg.c
+ libpng.c
+ libtiff.c
main.c
metadatahandler.c
metadataquery.c
@@ -45,8 +49,9 @@ list(APPEND SOURCE
scaler.c
stream.c
tgaformat.c
- tiffformat.c
- ungif.c)
+ ungif.c
+ uuid.c
+ wincodecs_common.c)
if(MSVC)
if(ARCH STREQUAL "i386")
@@ -79,7 +84,7 @@ if(MSVC)
endif()
set_module_type(windowscodecs win32dll)
-target_link_libraries(windowscodecs wine uuid ${PSEH_LIB})
-add_importlibs(windowscodecs ole32 oleaut32 rpcrt4 shlwapi user32 gdi32 advapi32
advapi32_vista propsys msvcrt kernel32 ntdll)
+target_link_libraries(windowscodecs wine uuid ${PSEH_LIB} oldnames)
+add_importlibs(windowscodecs libjpeg libpng libtiff ole32 oleaut32 rpcrt4 shlwapi user32
gdi32 advapi32 advapi32_vista propsys msvcrt kernel32 ntdll)
add_pch(windowscodecs precomp.h "${PCH_SKIP_SOURCE}")
add_cd_file(TARGET windowscodecs DESTINATION reactos/system32 FOR all)
diff --git a/dll/win32/windowscodecs/bitmap.c b/dll/win32/windowscodecs/bitmap.c
index 7959da6911d..dee3f28d5d7 100644
--- a/dll/win32/windowscodecs/bitmap.c
+++ b/dll/win32/windowscodecs/bitmap.c
@@ -17,10 +17,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#ifndef __REACTOS__
-#include "config.h"
-#endif
-
#include <stdarg.h>
#define COBJMACROS
@@ -34,6 +30,9 @@
#include "wine/asm.h"
#include "wine/debug.h"
+#include "initguid.h"
+DEFINE_GUID(IID_CMetaBitmapRenderTarget,
0x0ccd7824,0xdc16,0x4d09,0xbc,0xa8,0x6b,0x09,0xc4,0xef,0x55,0x35);
+
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
/* WARNING: .NET Media Integration Layer (MIL) directly dereferences
@@ -82,11 +81,6 @@ static inline BitmapImpl *impl_from_IMILUnknown1(IMILUnknown1 *iface)
return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown1_iface);
}
-static inline BitmapImpl *impl_from_IMILUnknown2(IMILUnknown2 *iface)
-{
- return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown2_iface);
-}
-
static inline BitmapLockImpl *impl_from_IWICBitmapLock(IWICBitmapLock *iface)
{
return CONTAINING_RECORD(iface, BitmapLockImpl, IWICBitmapLock_iface);
@@ -155,7 +149,7 @@ static ULONG WINAPI BitmapLockImpl_AddRef(IWICBitmapLock *iface)
BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -165,13 +159,13 @@ static ULONG WINAPI BitmapLockImpl_Release(IWICBitmapLock *iface)
BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
BitmapImpl_ReleaseLock(This->parent);
IWICBitmap_Release(&This->parent->IWICBitmap_iface);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This);
}
return ref;
@@ -262,7 +256,10 @@ static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface,
REFIID iid,
}
else
{
- FIXME("unknown interface %s\n", debugstr_guid(iid));
+ if (IsEqualIID(&IID_CMetaBitmapRenderTarget, iid))
+ WARN("Ignoring interface %s\n", debugstr_guid(iid));
+ else
+ FIXME("unknown interface %s\n", debugstr_guid(iid));
*ppv = NULL;
return E_NOINTERFACE;
}
@@ -276,7 +273,7 @@ static ULONG WINAPI BitmapImpl_AddRef(IWICBitmap *iface)
BitmapImpl *This = impl_from_IWICBitmap(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -286,7 +283,7 @@ static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface)
BitmapImpl *This = impl_from_IWICBitmap(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
@@ -296,8 +293,8 @@ static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface)
if (This->view)
UnmapViewOfFile(This->view);
else
- HeapFree(GetProcessHeap(), 0, This->data);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This->data);
+ free(This);
}
return ref;
@@ -378,7 +375,7 @@ static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const WICRect
*prcLock,
BitmapLockImpl *result;
WICRect rc;
- TRACE("(%p,%s,%x,%p)\n", iface, debug_wic_rect(prcLock), flags, ppILock);
+ TRACE("(%p,%s,%lx,%p)\n", iface, debug_wic_rect(prcLock), flags,
ppILock);
if (!(flags & (WICBitmapLockRead|WICBitmapLockWrite)) || !ppILock)
return E_INVALIDARG;
@@ -401,13 +398,13 @@ static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const
WICRect *prcLock,
return E_FAIL;
}
- result = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapLockImpl));
+ result = malloc(sizeof(BitmapLockImpl));
if (!result)
return E_OUTOFMEMORY;
if (!BitmapImpl_AcquireLock(This, flags & WICBitmapLockWrite))
{
- HeapFree(GetProcessHeap(), 0, result);
+ free(result);
return WINCODEC_ERR_ALREADYLOCKED;
}
@@ -605,7 +602,7 @@ static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmap *iface, void
**ppv)
static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmap *iface, const WICRect *rc, DWORD
flags, IWICBitmapLock **lock)
{
BitmapImpl *This = impl_from_IMILBitmap(iface);
- TRACE("(%p,%p,%08x,%p)\n", iface, rc, flags, lock);
+ TRACE("(%p,%p,%08lx,%p)\n", iface, rc, flags, lock);
return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock);
}
@@ -675,7 +672,7 @@ static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface)
return IWICBitmap_Release(&This->IWICBitmap_iface);
}
-DECLSPEC_HIDDEN void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg)
+void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg)
{
FIXME("(%p,%p): stub\n", iface, arg);
}
@@ -686,7 +683,7 @@ static HRESULT WINAPI IMILUnknown1Impl_unknown2(IMILUnknown1 *iface,
void *arg1,
return E_NOTIMPL;
}
-DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void
*arg)
+HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg)
{
FIXME("(%p,%p): stub\n", iface, arg);
return E_NOTIMPL;
@@ -716,7 +713,7 @@ static HRESULT WINAPI IMILUnknown1Impl_unknown7(IMILUnknown1 *iface,
void *arg)
return E_NOTIMPL;
}
-DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface)
+HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface)
{
FIXME("(%p): stub\n", iface);
return E_NOTIMPL;
@@ -808,13 +805,13 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, UINT stride,
UINT datasiz
if (datasize < stride * uiHeight) return WINCODEC_ERR_INSUFFICIENTBUFFER;
if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl));
+ This = malloc(sizeof(BitmapImpl));
if (!This) return E_OUTOFMEMORY;
if (view) data = (BYTE *)view + offset;
- else if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize)))
+ else if (!(data = calloc(1, datasize)))
{
- HeapFree(GetProcessHeap(), 0, This);
+ free(This);
return E_OUTOFMEMORY;
}
@@ -835,7 +832,11 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, UINT stride,
UINT datasiz
This->bpp = bpp;
memcpy(&This->pixelformat, pixelFormat, sizeof(GUID));
This->dpix = This->dpiy = 0.0;
+#ifdef __REACTOS__
InitializeCriticalSection(&This->cs);
+#else
+ InitializeCriticalSectionEx(&This->cs, 0,
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
+#endif
This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
BitmapImpl.lock");
*ppIBitmap = &This->IWICBitmap_iface;
diff --git a/dll/win32/windowscodecs/bmpdecode.c b/dll/win32/windowscodecs/bmpdecode.c
index 5ee4ac38ccb..9eb74b3d7cc 100644
--- a/dll/win32/windowscodecs/bmpdecode.c
+++ b/dll/win32/windowscodecs/bmpdecode.c
@@ -16,8 +16,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "config.h"
-
#include <assert.h>
#include <stdarg.h>
@@ -226,9 +224,9 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface,
int i;
count = 1 << bch->bcBitCount;
- wiccolors = HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor) * count);
+ wiccolors = malloc(sizeof(WICColor) * count);
tablesize = sizeof(RGBTRIPLE) * count;
- bgrcolors = HeapAlloc(GetProcessHeap(), 0, tablesize);
+ bgrcolors = malloc(tablesize);
if (!wiccolors || !bgrcolors)
{
hr = E_OUTOFMEMORY;
@@ -274,7 +272,7 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface,
count = min(This->bih.bV5ClrUsed, 1 <<
This->bih.bV5BitCount);
tablesize = sizeof(WICColor) * count;
- wiccolors = HeapAlloc(GetProcessHeap(), 0, tablesize);
+ wiccolors = malloc(tablesize);
if (!wiccolors)
{
hr = E_OUTOFMEMORY;
@@ -310,8 +308,8 @@ end:
if (SUCCEEDED(hr))
hr = IWICPalette_InitializeCustom(pIPalette, wiccolors, count);
- HeapFree(GetProcessHeap(), 0, wiccolors);
- HeapFree(GetProcessHeap(), 0, bgrcolors);
+ free(wiccolors);
+ free(bgrcolors);
return hr;
}
@@ -388,7 +386,7 @@ static HRESULT BmpFrameDecode_ReadUncompressed(BmpDecoder* This)
bytesperrow = (((width * This->bitsperpixel)+31)/32)*4;
datasize = bytesperrow * height;
- This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
+ This->imagedata = malloc(datasize);
if (!This->imagedata) return E_OUTOFMEMORY;
offbits.QuadPart = This->image_offset;
@@ -411,12 +409,45 @@ static HRESULT BmpFrameDecode_ReadUncompressed(BmpDecoder* This)
return S_OK;
fail:
- HeapFree(GetProcessHeap(), 0, This->imagedata);
+ free(This->imagedata);
This->imagedata = NULL;
if (SUCCEEDED(hr)) hr = E_FAIL;
return hr;
}
+static HRESULT BmpFrameDecode_ReadABGRasBGR(BmpDecoder* This)
+{
+ UINT x, y, width, height;
+ BYTE *pixel;
+ HRESULT hr;
+
+ hr = IWICBitmapFrameDecode_GetSize(&This->IWICBitmapFrameDecode_iface,
&width, &height);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = BmpFrameDecode_ReadUncompressed(This);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ for (y = 0; y < height; y++)
+ {
+ pixel = This->imagedatastart + This->stride * (INT)y;
+
+ for (x = 0; x < width; x++)
+ {
+ pixel[0] = pixel[1];
+ pixel[1] = pixel[2];
+ pixel[2] = pixel[3];
+ pixel[3] = 0;
+ pixel += 4;
+ }
+ }
+ }
+
+ return hr;
+}
+
static HRESULT BmpFrameDecode_ReadRGB8(BmpDecoder* This)
{
HRESULT hr;
@@ -482,7 +513,7 @@ static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
else
palettesize = 4 * 256;
- This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
+ This->imagedata = malloc(datasize);
if (!This->imagedata)
{
hr = E_OUTOFMEMORY;
@@ -578,7 +609,7 @@ end:
return S_OK;
fail:
- HeapFree(GetProcessHeap(), 0, This->imagedata);
+ free(This->imagedata);
This->imagedata = NULL;
if (SUCCEEDED(hr)) hr = E_FAIL;
return hr;
@@ -606,7 +637,7 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
else
palettesize = 4 * 16;
- This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
+ This->imagedata = malloc(datasize);
if (!This->imagedata)
{
hr = E_OUTOFMEMORY;
@@ -718,7 +749,7 @@ end:
return S_OK;
fail:
- HeapFree(GetProcessHeap(), 0, This->imagedata);
+ free(This->imagedata);
This->imagedata = NULL;
if (SUCCEEDED(hr)) hr = E_FAIL;
return hr;
@@ -744,7 +775,7 @@ static const struct bitfields_format bitfields_formats[] = {
{16,0xf800,0x7e0,0x1f,0,&GUID_WICPixelFormat16bppBGR565,BmpFrameDecode_ReadUncompressed},
{32,0xff0000,0xff00,0xff,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadUncompressed},
{32,0xff0000,0xff00,0xff,0xff000000,&GUID_WICPixelFormat32bppBGRA,BmpFrameDecode_ReadUncompressed},
-
{32,0xff000000,0xff0000,0xff00,0xff,&GUID_WICPixelFormat32bppRGBA,BmpFrameDecode_ReadUncompressed},
+
{32,0xff000000,0xff0000,0xff00,0xff,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadABGRasBGR},
{32,0xff,0xff00,0xff0000,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadRGB8},
{0}
};
@@ -861,7 +892,7 @@ static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream
*stream)
}
else /* struct is compatible with BITMAPINFOHEADER */
{
- TRACE("bitmap header=%i compression=%i depth=%i\n",
This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount);
+ TRACE("bitmap header=%li compression=%li depth=%i\n",
This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount);
switch(This->bih.bV5Compression)
{
case BI_RGB:
@@ -935,7 +966,7 @@ static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream
*stream)
{
This->read_data_func = BmpFrameDecode_ReadUncompressed;
This->pixelformat = &GUID_WICPixelFormatUndefined;
- FIXME("unsupported bitfields type depth=%i red=%x green=%x blue=%x
alpha=%x\n",
+ FIXME("unsupported bitfields type depth=%i red=%lx green=%lx
blue=%lx alpha=%lx\n",
This->bih.bV5BitCount, This->bih.bV5RedMask,
This->bih.bV5GreenMask, This->bih.bV5BlueMask, This->bih.bV5AlphaMask);
}
break;
@@ -944,7 +975,7 @@ static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream
*stream)
This->bitsperpixel = 0;
This->read_data_func = BmpFrameDecode_ReadUnsupported;
This->pixelformat = &GUID_WICPixelFormatUndefined;
- FIXME("unsupported bitmap type header=%i compression=%i
depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression,
This->bih.bV5BitCount);
+ FIXME("unsupported bitmap type header=%li compression=%li
depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression,
This->bih.bV5BitCount);
break;
}
}
@@ -999,7 +1030,7 @@ static ULONG WINAPI BmpDecoder_AddRef(IWICBitmapDecoder *iface)
BmpDecoder *This = impl_from_IWICBitmapDecoder(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -1009,15 +1040,15 @@ static ULONG WINAPI BmpDecoder_Release(IWICBitmapDecoder *iface)
BmpDecoder *This = impl_from_IWICBitmapDecoder(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
if (This->stream) IStream_Release(This->stream);
- HeapFree(GetProcessHeap(), 0, This->imagedata);
+ free(This->imagedata);
This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This);
}
return ref;
@@ -1155,7 +1186,7 @@ static HRESULT BmpDecoder_Create(int packed, int icoframe,
BmpDecoder **ppDecode
{
BmpDecoder *This;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpDecoder));
+ This = malloc(sizeof(BmpDecoder));
if (!This) return E_OUTOFMEMORY;
This->IWICBitmapDecoder_iface.lpVtbl = &BmpDecoder_Vtbl;
@@ -1164,7 +1195,11 @@ static HRESULT BmpDecoder_Create(int packed, int icoframe,
BmpDecoder **ppDecode
This->initialized = FALSE;
This->stream = NULL;
This->imagedata = NULL;
+#ifdef __REACTOS__
InitializeCriticalSection(&This->lock);
+#else
+ InitializeCriticalSectionEx(&This->lock, 0,
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
+#endif
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
BmpDecoder.lock");
This->packed = packed;
This->icoframe = icoframe;
@@ -1220,7 +1255,8 @@ void BmpDecoder_FindIconMask(BmpDecoder *This, ULONG *mask_offset,
int *topdown)
if (This->read_data_func == BmpFrameDecode_ReadUncompressed)
{
/* RGB or BITFIELDS data */
- ULONG width, height, bytesperrow, datasize;
+ UINT width, height;
+ ULONG bytesperrow, datasize;
IWICBitmapFrameDecode_GetSize(&This->IWICBitmapFrameDecode_iface,
&width, &height);
bytesperrow = (((width * This->bitsperpixel)+31)/32)*4;
datasize = bytesperrow * height;
diff --git a/dll/win32/windowscodecs/bmpencode.c b/dll/win32/windowscodecs/bmpencode.c
index 3b77517a8d9..28da4a5e6d2 100644
--- a/dll/win32/windowscodecs/bmpencode.c
+++ b/dll/win32/windowscodecs/bmpencode.c
@@ -17,8 +17,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "config.h"
-
#include <stdarg.h>
#define COBJMACROS
@@ -56,10 +54,7 @@ static const struct bmp_pixelformat formats[] = {
{&GUID_WICPixelFormat16bppBGR555, 16, 0, BI_RGB},
{&GUID_WICPixelFormat16bppBGR565, 16, 0, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0},
{&GUID_WICPixelFormat32bppBGR, 32, 0, BI_RGB},
-#if 0
- /* Windows doesn't seem to support this one. */
{&GUID_WICPixelFormat32bppBGRA, 32, 0, BI_BITFIELDS, 0xff0000, 0xff00, 0xff,
0xff000000},
-#endif
{NULL}
};
@@ -79,8 +74,6 @@ typedef struct BmpFrameEncode {
BOOL committed;
} BmpFrameEncode;
-static const WCHAR wszEnableV5Header32bppBGRA[] =
{'E','n','a','b','l','e','V','5','H','e','a','d','e','r','3','2','b','p','p','B','G','R','A',0};
-
static inline BmpFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface)
{
return CONTAINING_RECORD(iface, BmpFrameEncode, IWICBitmapFrameEncode_iface);
@@ -114,7 +107,7 @@ static ULONG WINAPI BmpFrameEncode_AddRef(IWICBitmapFrameEncode
*iface)
BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -124,13 +117,13 @@ static ULONG WINAPI BmpFrameEncode_Release(IWICBitmapFrameEncode
*iface)
BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
if (This->stream) IStream_Release(This->stream);
- HeapFree(GetProcessHeap(), 0, This->bits);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This->bits);
+ free(This);
}
return ref;
@@ -253,7 +246,7 @@ static HRESULT BmpFrameEncode_AllocateBits(BmpFrameEncode *This)
return WINCODEC_ERR_WRONGSTATE;
This->stride = (((This->width * This->format->bpp)+31)/32)*4;
- This->bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->stride *
This->height);
+ This->bits = calloc(This->stride, This->height);
if (!This->bits) return E_OUTOFMEMORY;
}
@@ -316,7 +309,8 @@ static HRESULT WINAPI BmpFrameEncode_WriteSource(IWICBitmapFrameEncode
*iface,
if (SUCCEEDED(hr))
{
hr = write_source(iface, pIBitmapSource, prc,
- This->format->guid, This->format->bpp, This->width,
This->height);
+ This->format->guid, This->format->bpp, !This->colors
&& This->format->colors,
+ This->width, This->height);
}
return hr;
@@ -400,10 +394,16 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode
*iface)
}
static HRESULT WINAPI BmpFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface,
- IWICMetadataQueryWriter **ppIMetadataQueryWriter)
+ IWICMetadataQueryWriter **query_writer)
{
- FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
- return E_NOTIMPL;
+ BmpFrameEncode *encoder = impl_from_IWICBitmapFrameEncode(iface);
+
+ TRACE("iface %p, query_writer %p.\n", iface, query_writer);
+
+ if (!encoder->initialized)
+ return WINCODEC_ERR_NOTINITIALIZED;
+
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
}
static const IWICBitmapFrameEncodeVtbl BmpFrameEncode_Vtbl = {
@@ -463,7 +463,7 @@ static ULONG WINAPI BmpEncoder_AddRef(IWICBitmapEncoder *iface)
BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -473,13 +473,13 @@ static ULONG WINAPI BmpEncoder_Release(IWICBitmapEncoder *iface)
BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
if (This->stream) IStream_Release(This->stream);
if (This->frame)
IWICBitmapFrameEncode_Release(&This->frame->IWICBitmapFrameEncode_iface);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This);
}
return ref;
@@ -563,7 +563,7 @@ static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder
*iface,
HRESULT hr;
static const PROPBAG2 opts[1] =
{
- { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszEnableV5Header32bppBGRA },
+ { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0,
(LPOLESTR)L"EnableV5Header32bppBGRA" },
};
TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
@@ -578,7 +578,7 @@ static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder
*iface,
if (FAILED(hr)) return hr;
}
- encode = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameEncode));
+ encode = malloc(sizeof(BmpFrameEncode));
if (!encode)
{
IPropertyBag2_Release(*ppIEncoderOptions);
@@ -648,7 +648,7 @@ HRESULT BmpEncoder_CreateInstance(REFIID iid, void** ppv)
*ppv = NULL;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpEncoder));
+ This = malloc(sizeof(BmpEncoder));
if (!This) return E_OUTOFMEMORY;
This->IWICBitmapEncoder_iface.lpVtbl = &BmpEncoder_Vtbl;
diff --git a/dll/win32/windowscodecs/clipper.c b/dll/win32/windowscodecs/clipper.c
index 02e0d967f52..b4b2c23ee45 100644
--- a/dll/win32/windowscodecs/clipper.c
+++ b/dll/win32/windowscodecs/clipper.c
@@ -72,7 +72,7 @@ static ULONG WINAPI BitmapClipper_AddRef(IWICBitmapClipper *iface)
BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -82,14 +82,14 @@ static ULONG WINAPI BitmapClipper_Release(IWICBitmapClipper *iface)
BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock);
if (This->source) IWICBitmapSource_Release(This->source);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This);
}
return ref;
@@ -244,13 +244,17 @@ HRESULT BitmapClipper_Create(IWICBitmapClipper **clipper)
{
BitmapClipper *This;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapClipper));
+ This = malloc(sizeof(BitmapClipper));
if (!This) return E_OUTOFMEMORY;
This->IWICBitmapClipper_iface.lpVtbl = &BitmapClipper_Vtbl;
This->ref = 1;
This->source = NULL;
+#ifdef __REACTOS__
InitializeCriticalSection(&This->lock);
+#else
+ InitializeCriticalSectionEx(&This->lock, 0,
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
+#endif
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
BitmapClipper.lock");
*clipper = &This->IWICBitmapClipper_iface;
diff --git a/dll/win32/windowscodecs/clsfactory.c b/dll/win32/windowscodecs/clsfactory.c
index 2de518a00c1..87b77c9c089 100644
--- a/dll/win32/windowscodecs/clsfactory.c
+++ b/dll/win32/windowscodecs/clsfactory.c
@@ -16,8 +16,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "config.h"
-
#include <stdarg.h>
#define COBJMACROS
@@ -27,6 +25,8 @@
#include "winreg.h"
#include "objbase.h"
#include "ocidl.h"
+#include "wincodec.h"
+#include "wincodecsdk.h"
#include "initguid.h"
#include "wincodecs_private.h"
@@ -35,7 +35,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
-extern HRESULT WINAPI WIC_DllGetClassObject(REFCLSID, REFIID, LPVOID *)
DECLSPEC_HIDDEN;
+extern HRESULT WINAPI WIC_DllGetClassObject(REFCLSID, REFIID, LPVOID *);
typedef struct {
REFCLSID classid;
@@ -47,6 +47,7 @@ static const classinfo wic_classes[] = {
{&CLSID_WICImagingFactory2, ImagingFactory_CreateInstance},
{&CLSID_WICBmpDecoder, BmpDecoder_CreateInstance},
{&CLSID_WICPngDecoder, PngDecoder_CreateInstance},
+ {&CLSID_WICPngDecoder2, PngDecoder_CreateInstance},
{&CLSID_WICPngEncoder, PngEncoder_CreateInstance},
{&CLSID_WICBmpEncoder, BmpEncoder_CreateInstance},
{&CLSID_WICGifDecoder, GifDecoder_CreateInstance},
@@ -56,14 +57,17 @@ static const classinfo wic_classes[] = {
{&CLSID_WICJpegEncoder, JpegEncoder_CreateInstance},
{&CLSID_WICTiffDecoder, TiffDecoder_CreateInstance},
{&CLSID_WICTiffEncoder, TiffEncoder_CreateInstance},
- {&CLSID_WICIcnsEncoder, IcnsEncoder_CreateInstance},
+ {&CLSID_WICDdsDecoder, DdsDecoder_CreateInstance},
+ {&CLSID_WICDdsEncoder, DdsEncoder_CreateInstance},
{&CLSID_WICDefaultFormatConverter, FormatConverter_CreateInstance},
{&CLSID_WineTgaDecoder, TgaDecoder_CreateInstance},
{&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance},
{&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance},
{&CLSID_WICPngChrmMetadataReader, PngChrmReader_CreateInstance},
{&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance},
+ {&CLSID_WICPngHistMetadataReader, PngHistReader_CreateInstance},
{&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance},
+ {&CLSID_WICPngTimeMetadataReader, PngTimeReader_CreateInstance},
{&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance},
{&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance},
{&CLSID_WICGCEMetadataReader, GCEReader_CreateInstance},
@@ -110,7 +114,7 @@ static ULONG WINAPI ClassFactoryImpl_AddRef(IClassFactory *iface)
ClassFactoryImpl *This = impl_from_IClassFactory(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -120,10 +124,10 @@ static ULONG WINAPI ClassFactoryImpl_Release(IClassFactory *iface)
ClassFactoryImpl *This = impl_from_IClassFactory(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
- HeapFree(GetProcessHeap(), 0, This);
+ free(This);
return ref;
}
@@ -161,7 +165,7 @@ static HRESULT ClassFactoryImpl_Constructor(const classinfo *info,
REFIID riid,
*ppv = NULL;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassFactoryImpl));
+ This = malloc(sizeof(ClassFactoryImpl));
if (!This) return E_OUTOFMEMORY;
This->IClassFactory_iface.lpVtbl = &ClassFactoryImpl_Vtbl;
@@ -201,11 +205,11 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID
*ppv)
else
ret = WIC_DllGetClassObject(rclsid, iid, ppv);
- TRACE("<-- %08X\n", ret);
+ TRACE("<-- %08lX\n", ret);
return ret;
}
-HRESULT create_instance(CLSID *clsid, const IID *iid, void **ppv)
+HRESULT create_instance(const CLSID *clsid, const IID *iid, void **ppv)
{
int i;
diff --git a/dll/win32/windowscodecs/colorcontext.c
b/dll/win32/windowscodecs/colorcontext.c
index eb13482cf43..a52e4e06eb7 100644
--- a/dll/win32/windowscodecs/colorcontext.c
+++ b/dll/win32/windowscodecs/colorcontext.c
@@ -16,8 +16,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "config.h"
-
#include <stdarg.h>
#define COBJMACROS
@@ -74,7 +72,7 @@ static ULONG WINAPI ColorContext_AddRef(IWICColorContext *iface)
ColorContext *This = impl_from_IWICColorContext(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -84,12 +82,12 @@ static ULONG WINAPI ColorContext_Release(IWICColorContext *iface)
ColorContext *This = impl_from_IWICColorContext(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
- HeapFree(GetProcessHeap(), 0, This->profile);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This->profile);
+ free(This);
}
return ref;
@@ -118,7 +116,7 @@ static HRESULT load_profile(const WCHAR *filename, BYTE **profile,
UINT *len)
CloseHandle(handle);
return E_FAIL;
}
- if (!(*profile = HeapAlloc(GetProcessHeap(), 0, size.u.LowPart)))
+ if (!(*profile = malloc(size.u.LowPart)))
{
CloseHandle(handle);
return E_OUTOFMEMORY;
@@ -126,12 +124,12 @@ static HRESULT load_profile(const WCHAR *filename, BYTE **profile,
UINT *len)
ret = ReadFile(handle, *profile, size.u.LowPart, &count, NULL);
CloseHandle(handle);
if (!ret) {
- HeapFree (GetProcessHeap(),0,*profile);
+ free(*profile);
*profile = NULL;
return HRESULT_FROM_WIN32(GetLastError());
}
if (count != size.u.LowPart) {
- HeapFree (GetProcessHeap(),0,*profile);
+ free(*profile);
*profile = NULL;
return E_FAIL;
}
@@ -156,7 +154,7 @@ static HRESULT WINAPI
ColorContext_InitializeFromFilename(IWICColorContext *ifac
hr = load_profile(wzFilename, &profile, &len);
if (FAILED(hr)) return hr;
- HeapFree(GetProcessHeap(), 0, This->profile);
+ free(This->profile);
This->profile = profile;
This->profile_len = len;
This->type = WICColorContextProfile;
@@ -174,10 +172,10 @@ static HRESULT WINAPI
ColorContext_InitializeFromMemory(IWICColorContext *iface,
if (This->type != WICColorContextUninitialized && This->type !=
WICColorContextProfile)
return WINCODEC_ERR_WRONGSTATE;
- if (!(profile = HeapAlloc(GetProcessHeap(), 0, cbBufferSize))) return
E_OUTOFMEMORY;
+ if (!(profile = malloc(cbBufferSize))) return E_OUTOFMEMORY;
memcpy(profile, pbBuffer, cbBufferSize);
- HeapFree(GetProcessHeap(), 0, This->profile);
+ free(This->profile);
This->profile = profile;
This->profile_len = cbBufferSize;
This->type = WICColorContextProfile;
@@ -261,7 +259,7 @@ HRESULT ColorContext_Create(IWICColorContext **colorcontext)
if (!colorcontext) return E_INVALIDARG;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(ColorContext));
+ This = malloc(sizeof(ColorContext));
if (!This) return E_OUTOFMEMORY;
This->IWICColorContext_iface.lpVtbl = &ColorContext_Vtbl;
diff --git a/dll/win32/windowscodecs/colortransform.c
b/dll/win32/windowscodecs/colortransform.c
index af66c67443d..9a392d6dc0c 100644
--- a/dll/win32/windowscodecs/colortransform.c
+++ b/dll/win32/windowscodecs/colortransform.c
@@ -16,8 +16,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "config.h"
-
#include <stdarg.h>
#define COBJMACROS
@@ -72,7 +70,7 @@ static ULONG WINAPI ColorTransform_AddRef(IWICColorTransform *iface)
ColorTransform *This = impl_from_IWICColorTransform(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -82,12 +80,12 @@ static ULONG WINAPI ColorTransform_Release(IWICColorTransform
*iface)
ColorTransform *This = impl_from_IWICColorTransform(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
if (This->dst) IWICBitmapSource_Release(This->dst);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This);
}
return ref;
@@ -177,7 +175,7 @@ HRESULT ColorTransform_Create(IWICColorTransform **colortransform)
if (!colortransform) return E_INVALIDARG;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(ColorTransform));
+ This = malloc(sizeof(ColorTransform));
if (!This) return E_OUTOFMEMORY;
This->IWICColorTransform_iface.lpVtbl = &ColorTransform_Vtbl;
diff --git a/dll/win32/windowscodecs/converter.c b/dll/win32/windowscodecs/converter.c
index cac2ac1aa5a..2156e0aec8f 100644
--- a/dll/win32/windowscodecs/converter.c
+++ b/dll/win32/windowscodecs/converter.c
@@ -17,8 +17,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "config.h"
-
#include <stdarg.h>
#include <math.h>
@@ -30,7 +28,6 @@
#include "wincodecs_private.h"
-#include "wine/heap.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
@@ -71,6 +68,7 @@ struct pixelformatinfo {
enum pixelformat format;
const WICPixelFormatGUID *guid;
copyfunc copy_function;
+ BOOL is_indexed_format;
};
typedef struct FormatConverter {
@@ -176,7 +174,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = (prc->Width+7)/8;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -205,7 +203,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -243,7 +241,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = (prc->Width+3)/4;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -268,7 +266,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -306,7 +304,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = (prc->Width+1)/2;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -329,7 +327,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -349,7 +347,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -371,7 +369,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -405,7 +403,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -424,7 +422,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -444,7 +442,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = prc->Width * 2;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -467,7 +465,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -487,7 +485,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = 2 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -515,7 +513,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -535,7 +533,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = 2 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -563,7 +561,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -583,7 +581,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = 2 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -611,7 +609,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -631,7 +629,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = 3 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -654,7 +652,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -675,7 +673,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = 3 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -702,7 +700,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -728,7 +726,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
HRESULT res;
res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride,
cbBufferSize, pbBuffer);
if (FAILED(res)) return res;
- convert_rgba_to_bgra(4, pbBuffer, prc->Width, prc->Height, cbStride);
+ reverse_bgr8(4, pbBuffer, prc->Width, prc->Height, cbStride);
}
return S_OK;
case format_32bppBGRA:
@@ -772,7 +770,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = 6 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -796,7 +794,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -816,7 +814,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
srcstride = 8 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -841,7 +839,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This,
const WICRe
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -985,9 +983,9 @@ static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This,
const WICR
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;
+ pbBuffer[cbStride*y+4*x] = (pbBuffer[cbStride*y+4*x] * alpha +
127) / 255;
+ pbBuffer[cbStride*y+4*x+1] = (pbBuffer[cbStride*y+4*x+1] * alpha
+ 127) / 255;
+ pbBuffer[cbStride*y+4*x+2] = (pbBuffer[cbStride*y+4*x+2] * alpha
+ 127) / 255;
}
}
}
@@ -1018,9 +1016,9 @@ static HRESULT copypixels_to_32bppPRGBA(struct FormatConverter
*This, const WICR
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;
+ pbBuffer[cbStride*y+4*x] = (pbBuffer[cbStride*y+4*x] * alpha +
127) / 255;
+ pbBuffer[cbStride*y+4*x+1] = (pbBuffer[cbStride*y+4*x+1] * alpha
+ 127) / 255;
+ pbBuffer[cbStride*y+4*x+2] = (pbBuffer[cbStride*y+4*x+2] * alpha
+ 127) / 255;
}
}
}
@@ -1063,7 +1061,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This,
const WICRec
srcstride = 4 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -1107,7 +1105,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This,
const WICRec
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -1122,7 +1120,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This,
const WICRec
srcstride = 4 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -1149,7 +1147,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This,
const WICRec
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return hr;
}
@@ -1164,7 +1162,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This,
const WICRec
srcstride = 4 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = heap_alloc(srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -1192,7 +1190,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This,
const WICRec
}
}
- heap_free(srcdata);
+ free(srcdata);
return hr;
}
return S_OK;
@@ -1238,7 +1236,7 @@ static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This,
const WICRec
srcstride = 4 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -1265,7 +1263,7 @@ static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This,
const WICRec
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return res;
}
@@ -1343,7 +1341,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This,
const WICRec
srcstride = 4 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride,
srcdatasize, srcdata);
@@ -1365,7 +1363,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This,
const WICRec
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
}
return hr;
@@ -1377,7 +1375,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This,
const WICRec
srcstride = 3 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata,
source_format);
@@ -1403,7 +1401,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This,
const WICRec
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return hr;
}
@@ -1467,7 +1465,7 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter
*This, const WIC
srcstride = 3 * prc->Width;
srcdatasize = srcstride * prc->Height;
- srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ srcdata = malloc(srcdatasize);
if (!srcdata) return E_OUTOFMEMORY;
hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata,
source_format);
@@ -1490,15 +1488,138 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter
*This, const WIC
}
}
- HeapFree(GetProcessHeap(), 0, srcdata);
+ free(srcdata);
return hr;
}
+static HRESULT copypixels_to_16bppBGRA5551(struct FormatConverter *This, const WICRect
*prc,
+ UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
+{
+ switch (source_format)
+ {
+ case format_16bppBGRA5551:
+ if (prc)
+ return IWICBitmapSource_CopyPixels(This->source, prc, cbStride,
cbBufferSize, pbBuffer);
+ return S_OK;
+ case format_32bppBGRA:
+ if(prc)
+ {
+ HRESULT res;
+ INT x, y;
+ BYTE *srcdata;
+ UINT srcstride, srcdatasize;
+ const BYTE *srcrow;
+ const DWORD *srcpixel;
+ BYTE *dstrow;
+ DWORD srcval = 0;
+ WORD *dstpixel;
+
+ int a, r, g, b;
+
+ srcstride = 4 * prc->Width;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = malloc(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 DWORD*)srcrow;
+ dstpixel = (WORD *)dstrow;
+ for(x=0; x<prc->Width; x++) {
+ srcval=*srcpixel++;
+ a = (srcval & 0xff000000) >> 24;
+ r = (srcval & 0x00ff0000) >> 16;
+ g = (srcval & 0x0000ff00) >> 8;
+ b = (srcval & 0x000000ff);
+ a = (a >> 7) << 15;
+ r = (r >> 3) << 10;
+ g = (g >> 3) << 5;
+ b = (b >> 3);
+ *dstpixel++ = (a|r|g|b);
+ }
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+ free(srcdata);
+ }
+ return S_OK;
+ default:
+ FIXME("Unimplemented conversion path! %d\n", source_format);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ }
+}
+
+static HRESULT copypixels_to_64bppRGBA(struct FormatConverter *This, const WICRect
*prc,
+ UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
+{
+ HRESULT hr;
+
+ switch (source_format)
+ {
+ case format_64bppRGBA:
+ if (prc)
+ return IWICBitmapSource_CopyPixels(This->source, prc, cbStride,
cbBufferSize, pbBuffer);
+ return S_OK;
+
+ case format_48bppRGB:
+ {
+ UINT srcstride, srcdatasize;
+ const USHORT *srcpixel;
+ const BYTE *srcrow;
+ USHORT *dstpixel;
+ BYTE *srcdata;
+ BYTE *dstrow;
+ INT x, y;
+
+ if (!prc)
+ return S_OK;
+
+ srcstride = 6 * prc->Width;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = malloc(srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize,
srcdata);
+ if (SUCCEEDED(hr))
+ {
+ srcrow = srcdata;
+ dstrow = pbBuffer;
+ for (y = 0; y < prc->Height; y++)
+ {
+ srcpixel = (USHORT *)srcrow;
+ dstpixel= (USHORT *)dstrow;
+ for (x = 0; x < prc->Width; x++)
+ {
+ *dstpixel++ = *srcpixel++;
+ *dstpixel++ = *srcpixel++;
+ *dstpixel++ = *srcpixel++;
+ *dstpixel++ = 65535;
+ }
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+ free(srcdata);
+ return hr;
+ }
+ default:
+ FIXME("Unimplemented conversion path %d.\n", source_format);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ }
+}
+
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,
copypixels_to_8bppIndexed},
+ {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL, TRUE},
+ {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL, TRUE},
+ {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL, TRUE},
+ {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed,
TRUE},
{format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL},
{format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL},
{format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL},
@@ -1506,7 +1627,7 @@ static const struct pixelformatinfo supported_formats[] = {
{format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL},
{format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL},
{format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL},
- {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, NULL},
+ {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551,
copypixels_to_16bppBGRA5551},
{format_24bppBGR, &GUID_WICPixelFormat24bppBGR, copypixels_to_24bppBGR},
{format_24bppRGB, &GUID_WICPixelFormat24bppRGB, copypixels_to_24bppRGB},
{format_32bppGrayFloat, &GUID_WICPixelFormat32bppGrayFloat,
copypixels_to_32bppGrayFloat},
@@ -1517,7 +1638,7 @@ static const struct pixelformatinfo supported_formats[] = {
{format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA},
{format_32bppPRGBA, &GUID_WICPixelFormat32bppPRGBA, copypixels_to_32bppPRGBA},
{format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL},
- {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL},
+ {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, copypixels_to_64bppRGBA},
{format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL},
{0}
};
@@ -1561,7 +1682,7 @@ static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter
*iface)
FormatConverter *This = impl_from_IWICFormatConverter(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
return ref;
}
@@ -1571,7 +1692,7 @@ static ULONG WINAPI FormatConverter_Release(IWICFormatConverter
*iface)
FormatConverter *This = impl_from_IWICFormatConverter(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) refcount=%u\n", iface, ref);
+ TRACE("(%p) refcount=%lu\n", iface, ref);
if (ref == 0)
{
@@ -1579,7 +1700,7 @@ static ULONG WINAPI FormatConverter_Release(IWICFormatConverter
*iface)
DeleteCriticalSection(&This->lock);
if (This->source) IWICBitmapSource_Release(This->source);
if (This->palette) IWICPalette_Release(This->palette);
- HeapFree(GetProcessHeap(), 0, This);
+ free(This);
}
return ref;
@@ -1638,12 +1759,7 @@ static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter *iface,
if (!This->palette)
{
- HRESULT hr;
- UINT bpp;
-
- hr = get_pixelformat_bpp(This->dst_format->guid, &bpp);
- if (hr != S_OK) return hr;
- if (bpp <= 8) return WINCODEC_ERR_WRONGSTATE;
+ if (This->dst_format->is_indexed_format) return WINCODEC_ERR_WRONGSTATE;
return IWICBitmapSource_CopyPalette(This->source, palette);
}
@@ -1691,6 +1807,13 @@ static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter *iface,
TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source,
debugstr_guid(dstFormat),
dither, palette, alpha_threshold, palette_type);
+ dstinfo = get_formatinfo(dstFormat);
+ if (!dstinfo)
+ {
+ FIXME("Unsupported destination format %s\n",
debugstr_guid(dstFormat));
+ return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+ }
+
if (!palette)
{
UINT bpp;
@@ -1705,18 +1828,21 @@ static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter *iface,
case WICBitmapPaletteTypeCustom:
IWICPalette_Release(palette);
palette = NULL;
- if (bpp <= 8) return E_INVALIDARG;
+
+ /* Indexed types require a palette */
+ if (dstinfo->is_indexed_format)
+ return E_INVALIDARG;
break;
case WICBitmapPaletteTypeMedianCut:
{
- if (bpp <= 8)
+ if (dstinfo->is_indexed_format)
res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp,
FALSE);
break;
}
default:
- if (bpp <= 8)
+ if (dstinfo->is_indexed_format)
res = IWICPalette_InitializePredefined(palette, palette_type, FALSE);
break;
}
@@ -1749,14 +1875,6 @@ static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter *iface,
goto end;
}
- dstinfo = get_formatinfo(dstFormat);
- if (!dstinfo)
- {
- res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
- FIXME("Unsupported destination format %s\n",
debugstr_guid(dstFormat));
- goto end;
- }
-
if (dstinfo->copy_function)
{
IWICBitmapSource_AddRef(source);
@@ -1841,14 +1959,18 @@ HRESULT FormatConverter_CreateInstance(REFIID iid, void** ppv)
*ppv = NULL;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter));
+ This = malloc(sizeof(FormatConverter));
if (!This) return E_OUTOFMEMORY;
This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl;
This->ref = 1;
This->source = NULL;
This->palette = NULL;
+#ifdef __REACTOS__
InitializeCriticalSection(&This->lock);
+#else
+ InitializeCriticalSectionEx(&This->lock, 0,
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
+#endif
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
FormatConverter.lock");
ret = IWICFormatConverter_QueryInterface(&This->IWICFormatConverter_iface,
iid, ppv);
diff --git a/dll/win32/windowscodecs/ddsformat.c b/dll/win32/windowscodecs/ddsformat.c
new file mode 100644
index 00000000000..680febb0d93
--- /dev/null
+++ b/dll/win32/windowscodecs/ddsformat.c
@@ -0,0 +1,2162 @@
+/*
+ * Copyright 2020 Ziqing Hui
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ *
+ * Note:
+ *
+ * Uncompressed image:
+ * For uncompressed formats, a block is equivalent to a pixel.
+ *
+ * Cube map:
+ * A cube map is equivalent to a 2D texture array which has 6 textures.
+ * A cube map array is equivalent to a 2D texture array which has cubeCount*6
textures.
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+#define DDS_MAGIC 0x20534444
+#ifndef MAKEFOURCC
+#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
+ ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
+#endif
+
+#define GET_RGB565_R(color) ((BYTE)(((color) >> 11) & 0x1F))
+#define GET_RGB565_G(color) ((BYTE)(((color) >> 5) & 0x3F))
+#define GET_RGB565_B(color) ((BYTE)(((color) >> 0) & 0x1F))
+#define MAKE_RGB565(r, g, b) ((WORD)(((BYTE)(r) << 11) | ((BYTE)(g) << 5) |
(BYTE)(b)))
+#define MAKE_ARGB(a, r, g, b) (((DWORD)(a) << 24) | ((DWORD)(r) << 16) |
((DWORD)(g) << 8) | (DWORD)(b))
+
+#define DDPF_ALPHAPIXELS 0x00000001
+#define DDPF_ALPHA 0x00000002
+#define DDPF_FOURCC 0x00000004
+#define DDPF_PALETTEINDEXED8 0x00000020
+#define DDPF_RGB 0x00000040
+#define DDPF_LUMINANCE 0x00020000
+#define DDPF_BUMPDUDV 0x00080000
+
+#define DDSCAPS2_CUBEMAP 0x00000200
+#define DDSCAPS2_VOLUME 0x00200000
+
+#define DDS_DIMENSION_TEXTURE1D 2
+#define DDS_DIMENSION_TEXTURE2D 3
+#define DDS_DIMENSION_TEXTURE3D 4
+
+#define DDS_RESOURCE_MISC_TEXTURECUBE 0x00000004
+
+#define DDS_BLOCK_WIDTH 4
+#define DDS_BLOCK_HEIGHT 4
+
+typedef struct {
+ DWORD size;
+ DWORD flags;
+ DWORD fourCC;
+ DWORD rgbBitCount;
+ DWORD rBitMask;
+ DWORD gBitMask;
+ DWORD bBitMask;
+ DWORD aBitMask;
+} DDS_PIXELFORMAT;
+
+typedef struct {
+ DWORD size;
+ DWORD flags;
+ DWORD height;
+ DWORD width;
+ DWORD pitchOrLinearSize;
+ DWORD depth;
+ DWORD mipMapCount;
+ DWORD reserved1[11];
+ DDS_PIXELFORMAT ddspf;
+ DWORD caps;
+ DWORD caps2;
+ DWORD caps3;
+ DWORD caps4;
+ DWORD reserved2;
+} DDS_HEADER;
+
+typedef struct {
+ DWORD dxgiFormat;
+ DWORD resourceDimension;
+ DWORD miscFlag;
+ DWORD arraySize;
+ DWORD miscFlags2;
+} DDS_HEADER_DXT10;
+
+typedef struct dds_info {
+ UINT width;
+ UINT height;
+ UINT depth;
+ UINT mip_levels;
+ UINT array_size;
+ UINT frame_count;
+ UINT data_offset;
+ UINT bytes_per_block; /* for uncompressed format, this means bytes per pixel*/
+ DXGI_FORMAT format;
+ WICDdsDimension dimension;
+ WICDdsAlphaMode alpha_mode;
+ const GUID *pixel_format;
+ UINT pixel_format_bpp;
+} dds_info;
+
+typedef struct dds_frame_info {
+ UINT width;
+ UINT height;
+ DXGI_FORMAT format;
+ UINT bytes_per_block; /* for uncompressed format, this means bytes per pixel*/
+ UINT block_width;
+ UINT block_height;
+ UINT width_in_blocks;
+ UINT height_in_blocks;
+ const GUID *pixel_format;
+ UINT pixel_format_bpp;
+} dds_frame_info;
+
+typedef struct DdsDecoder {
+ IWICBitmapDecoder IWICBitmapDecoder_iface;
+ IWICDdsDecoder IWICDdsDecoder_iface;
+ IWICWineDecoder IWICWineDecoder_iface;
+ LONG ref;
+ BOOL initialized;
+ IStream *stream;
+ CRITICAL_SECTION lock;
+ dds_info info;
+} DdsDecoder;
+
+typedef struct DdsFrameDecode {
+ IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
+ IWICDdsFrameDecode IWICDdsFrameDecode_iface;
+ LONG ref;
+ BYTE *block_data;
+ BYTE *pixel_data;
+ CRITICAL_SECTION lock;
+ dds_frame_info info;
+} DdsFrameDecode;
+
+typedef struct DdsEncoder {
+ IWICBitmapEncoder IWICBitmapEncoder_iface;
+ IWICDdsEncoder IWICDdsEncoder_iface;
+ LONG ref;
+ CRITICAL_SECTION lock;
+ IStream *stream;
+ UINT frame_count;
+ UINT frame_index;
+ BOOL uncommitted_frame;
+ BOOL committed;
+ dds_info info;
+} DdsEncoder;
+
+typedef struct DdsFrameEncode {
+ IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
+ LONG ref;
+ DdsEncoder *parent;
+ BOOL initialized;
+ BOOL frame_created;
+ UINT width;
+ UINT height;
+ double dpi_x;
+ double dpi_y;
+} DdsFrameEncode;
+
+static struct dds_format {
+ DDS_PIXELFORMAT pixel_format;
+ const GUID *wic_format;
+ UINT wic_format_bpp;
+ DXGI_FORMAT dxgi_format;
+} dds_format_table[] = {
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X',
'T', '1'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppPBGRA, 32, DXGI_FORMAT_BC1_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X',
'T', '2'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppPBGRA, 32, DXGI_FORMAT_BC2_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X',
'T', '3'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC2_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X',
'T', '4'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppPBGRA, 32, DXGI_FORMAT_BC3_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X',
'T', '5'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC3_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C',
'4', 'U'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC4_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C',
'4', 'S'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC4_SNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C',
'5', 'U'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC5_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C',
'5', 'S'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC5_SNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('A', 'T',
'I', '1'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC4_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('A', 'T',
'I', '2'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC5_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('R', 'G',
'B', 'G'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bpp4Channels, 32, DXGI_FORMAT_R8G8_B8G8_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('G', 'R',
'G', 'B'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bpp4Channels, 32, DXGI_FORMAT_G8R8_G8B8_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X',
'1', '0'), 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_UNKNOWN },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x24, 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat64bppRGBA, 64, DXGI_FORMAT_R16G16B16A16_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x6E, 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat64bppRGBA, 64, DXGI_FORMAT_R16G16B16A16_SNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x6F, 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat16bppGrayHalf, 16, DXGI_FORMAT_R16_FLOAT },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x70, 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_R16G16_FLOAT },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x71, 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat64bppRGBAHalf, 64, DXGI_FORMAT_R16G16B16A16_FLOAT },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x72, 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat32bppGrayFloat, 32, DXGI_FORMAT_R32_FLOAT },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x73, 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormatUndefined, 32, DXGI_FORMAT_R32G32_FLOAT },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x74, 0, 0, 0, 0, 0 },
+ &GUID_WICPixelFormat128bppRGBAFloat, 128, DXGI_FORMAT_R32G32B32A32_FLOAT },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF,0xFF00,0xFF0000,0xFF000000
},
+ &GUID_WICPixelFormat32bppRGBA, 32, DXGI_FORMAT_R8G8B8A8_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF,0xFF00,0xFF0000,0 },
+ &GUID_WICPixelFormat32bppRGB, 32, DXGI_FORMAT_UNKNOWN },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF0000,0xFF00,0xFF,0xFF000000
},
+ &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_B8G8R8A8_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF0000,0xFF00,0xFF,0 },
+ &GUID_WICPixelFormat32bppBGR, 32, DXGI_FORMAT_B8G8R8X8_UNORM },
+ /* The red and blue masks are swapped for DXGI_FORMAT_R10G10B10A2_UNORM.
+ * For "correct" one, the RGB masks should be 0x3FF,0xFFC00,0x3FF00000.
+ * see:
https://walbourn.github.io/dds-update-and-1010102-problems */
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32,
0x3FF00000,0xFFC00,0x3FF,0xC0000000 },
+ &GUID_WICPixelFormat32bppR10G10B10A2, 32, DXGI_FORMAT_R10G10B10A2_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32,
0x3FF,0xFFC00,0x3FF00000,0xC0000000 },
+ &GUID_WICPixelFormat32bppRGBA1010102, 32, DXGI_FORMAT_R10G10B10A2_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB , 0, 32, 0xFFFF,0xFFFF0000,0,0 },
+ &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_R16G16_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB , 0, 32, 0xFFFFFFFF,0,0,0 },
+ &GUID_WICPixelFormat32bppGrayFloat, 32, DXGI_FORMAT_R32_FLOAT },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB , 0, 24, 0xFF0000,0x00FF00,0x0000FF,0 },
+ &GUID_WICPixelFormat24bppBGR, 24, DXGI_FORMAT_UNKNOWN },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB , 0, 24, 0x0000FF,0x00FF00,0xFF0000,0 },
+ &GUID_WICPixelFormat24bppRGB, 24, DXGI_FORMAT_UNKNOWN },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0xF800,0x7E0,0x1F,0 },
+ &GUID_WICPixelFormat16bppBGR565, 16, DXGI_FORMAT_B5G6R5_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0x7C00,0x3E0,0x1F,0 },
+ &GUID_WICPixelFormat16bppBGR555, 16, DXGI_FORMAT_UNKNOWN },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0x7C00,0x3E0,0x1F,0x8000 },
+ &GUID_WICPixelFormat16bppBGRA5551, 16, DXGI_FORMAT_B5G5R5A1_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0xF00,0xF0,0xF,0xF000 },
+ &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_B4G4R4A4_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_ALPHA, 0, 8, 0,0,0,0xFF },
+ &GUID_WICPixelFormat8bppAlpha, 8, DXGI_FORMAT_A8_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 16, 0xFFFF,0,0,0 },
+ &GUID_WICPixelFormat16bppGray, 16, DXGI_FORMAT_R16_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 16, 0xFF,0,0,0xFF00 },
+ &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_R8G8_UNORM },
+ { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 8, 0xFF,0,0,0 },
+ &GUID_WICPixelFormat8bppGray, 8, DXGI_FORMAT_R8_UNORM },
+ { { 0 }, &GUID_WICPixelFormat8bppAlpha, 8, DXGI_FORMAT_A8_UNORM },
+ { { 0 }, &GUID_WICPixelFormat8bppGray, 8, DXGI_FORMAT_R8_UNORM },
+ { { 0 }, &GUID_WICPixelFormat16bppGray, 16, DXGI_FORMAT_R16_UNORM },
+ { { 0 }, &GUID_WICPixelFormat16bppGrayHalf, 16, DXGI_FORMAT_R16_FLOAT },
+ { { 0 }, &GUID_WICPixelFormat16bppBGR565, 16, DXGI_FORMAT_B5G6R5_UNORM
},
+ { { 0 }, &GUID_WICPixelFormat16bppBGRA5551, 16, DXGI_FORMAT_B5G5R5A1_UNORM
},
+ { { 0 }, &GUID_WICPixelFormat32bppGrayFloat, 32, DXGI_FORMAT_R32_FLOAT },
+ { { 0 }, &GUID_WICPixelFormat32bppRGBA, 32, DXGI_FORMAT_R8G8B8A8_UNORM
},
+ { { 0 }, &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_B8G8R8A8_UNORM
},
+ { { 0 }, &GUID_WICPixelFormat32bppBGR, 32, DXGI_FORMAT_B8G8R8X8_UNORM
},
+ { { 0 }, &GUID_WICPixelFormat32bppR10G10B10A2, 32,
DXGI_FORMAT_R10G10B10A2_UNORM },
+ { { 0 }, &GUID_WICPixelFormat32bppRGBE, 32,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
+ { { 0 }, &GUID_WICPixelFormat32bppRGBA1010102XR, 32,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM },
+ { { 0 }, &GUID_WICPixelFormat64bppRGBA, 64,
DXGI_FORMAT_R16G16B16A16_UNORM },
+ { { 0 }, &GUID_WICPixelFormat64bppRGBAHalf, 64,
DXGI_FORMAT_R16G16B16A16_FLOAT },
+ { { 0 }, &GUID_WICPixelFormat96bppRGBFloat, 96, DXGI_FORMAT_R32G32B32_FLOAT
},
+ { { 0 }, &GUID_WICPixelFormat128bppRGBAFloat, 128,
DXGI_FORMAT_R32G32B32A32_FLOAT },
+ { { 0 }, &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_UNKNOWN }
+};
+
+static DXGI_FORMAT compressed_formats[] = {
+ DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB,
+ DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB,
+ DXGI_FORMAT_BC4_TYPELESS, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM,
+ DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM,
+ DXGI_FORMAT_BC6H_TYPELESS, DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_SF16,
+ DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM_SRGB
+};
+
+static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *, UINT, UINT, UINT,
IWICBitmapFrameDecode **);
+
+static DWORD rgb565_to_argb(WORD color, BYTE alpha)
+{
+ return MAKE_ARGB(alpha, (GET_RGB565_R(color) * 0xFF + 0x0F) / 0x1F,
+ (GET_RGB565_G(color) * 0xFF + 0x1F) / 0x3F,
+ (GET_RGB565_B(color) * 0xFF + 0x0F) / 0x1F);
+}
+
+static inline BOOL has_extended_header(DDS_HEADER *header)
+{
+ return (header->ddspf.flags & DDPF_FOURCC) &&
+ (header->ddspf.fourCC == MAKEFOURCC('D', 'X', '1',
'0'));
+}
+
+static WICDdsDimension get_dimension(DDS_HEADER *header, DDS_HEADER_DXT10
*header_dxt10)
+{
+ if (header_dxt10) {
+ if (header_dxt10->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE) return
WICDdsTextureCube;
+ switch (header_dxt10->resourceDimension)
+ {
+ case DDS_DIMENSION_TEXTURE1D: return WICDdsTexture1D;
+ case DDS_DIMENSION_TEXTURE2D: return WICDdsTexture2D;
+ case DDS_DIMENSION_TEXTURE3D: return WICDdsTexture3D;
+ default: return WICDdsTexture2D;
+ }
+ } else {
+ if (header->caps2 & DDSCAPS2_CUBEMAP) {
+ return WICDdsTextureCube;
+ } else if (header->caps2 & DDSCAPS2_VOLUME) {
+ return WICDdsTexture3D;
+ } else {
+ return WICDdsTexture2D;
+ }
+ }
+}
+
+static struct dds_format *get_dds_format(DDS_PIXELFORMAT *pixel_format)
+{
+ UINT i;
+
+ for (i = 0; i < ARRAY_SIZE(dds_format_table); i++)
+ {
+ if ((pixel_format->flags & dds_format_table[i].pixel_format.flags)
&&
+ (pixel_format->fourCC == dds_format_table[i].pixel_format.fourCC)
&&
+ (pixel_format->rgbBitCount ==
dds_format_table[i].pixel_format.rgbBitCount) &&
+ (pixel_format->rBitMask == dds_format_table[i].pixel_format.rBitMask)
&&
+ (pixel_format->gBitMask == dds_format_table[i].pixel_format.gBitMask)
&&
+ (pixel_format->bBitMask == dds_format_table[i].pixel_format.bBitMask)
&&
+ (pixel_format->aBitMask == dds_format_table[i].pixel_format.aBitMask))
+ return dds_format_table + i;
+ }
+
+ return dds_format_table + ARRAY_SIZE(dds_format_table) - 1;
+}
+
+static WICDdsAlphaMode get_alpha_mode_from_fourcc(DWORD fourcc)
+{
+ switch (fourcc)
+ {
+ case MAKEFOURCC('D', 'X', 'T', '1'):
+ case MAKEFOURCC('D', 'X', 'T', '2'):
+ case MAKEFOURCC('D', 'X', 'T', '4'):
+ return WICDdsAlphaModePremultiplied;
+ default:
+ return WICDdsAlphaModeUnknown;
+ }
+}
+
+static UINT get_bytes_per_block_from_format(DXGI_FORMAT format)
+{
+ /* for uncompressed format, return bytes per pixel*/
+ switch (format)
+ {
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
+ return 1;
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_SINT:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return 2;
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R32_SINT:
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return 4;
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return 8;
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return 12;
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return 16;
+ default:
+ WARN("DXGI format 0x%x is not supported in DDS decoder\n",
format);
+ return 0;
+ }
+}
+
+static UINT get_frame_count(UINT depth, UINT mip_levels, UINT array_size, WICDdsDimension
dimension)
+{
+ UINT frame_count, i;
+
+ if (depth == 1)
+ {
+ frame_count = mip_levels;
+ }
+ else
+ {
+ frame_count = 0;
+ for (i = 0; i < mip_levels; i++)
+ {
+ frame_count += depth;
+ if (depth > 1) depth /= 2;
+ }
+ }
+
+ frame_count *= array_size;
+ if (dimension == WICDdsTextureCube) frame_count *= 6;
+
+ return frame_count;
+}
+
+static void get_frame_dds_index(UINT index, dds_info *info, UINT *array_index, UINT
*mip_level, UINT *slice_index)
+{
+ UINT frame_per_texture, depth;
+
+ if (info->dimension == WICDdsTextureCube)
+ frame_per_texture = info->mip_levels;
+ else
+ frame_per_texture = info->frame_count / info->array_size;
+
+ *array_index = index / frame_per_texture;
+ *slice_index = index % frame_per_texture;
+ depth = info->depth;
+ *mip_level = 0;
+ while (*slice_index >= depth)
+ {
+ *slice_index -= depth;
+ (*mip_level)++;
+ if (depth > 1) depth /= 2;
+ }
+}
+
+static const GUID *dxgi_format_to_wic_format(DXGI_FORMAT dxgi_format)
+{
+ UINT i;
+ for (i = 0; i < ARRAY_SIZE(dds_format_table); i++)
+ {
+ if (dds_format_table[i].pixel_format.size == 0 &&
+ dds_format_table[i].dxgi_format == dxgi_format)
+ return dds_format_table[i].wic_format;
+ }
+ return &GUID_WICPixelFormatUndefined;
+}
+
+static BOOL is_compressed(DXGI_FORMAT format)
+{
+ UINT i;
+
+ for (i = 0; i < ARRAY_SIZE(compressed_formats); i++)
+ {
+ if (format == compressed_formats[i]) return TRUE;
+ }
+ return FALSE;
+}
+
+static void get_dds_info(dds_info* info, DDS_HEADER *header, DDS_HEADER_DXT10
*header_dxt10)
+{
+ struct dds_format *format_info;
+
+ info->width = header->width;
+ info->height = header->height;
+ info->depth = 1;
+ info->mip_levels = 1;
+ info->array_size = 1;
+ if (header->depth) info->depth = header->depth;
+ if (header->mipMapCount) info->mip_levels = header->mipMapCount;
+
+ if (has_extended_header(header)) {
+ if (header_dxt10->arraySize) info->array_size =
header_dxt10->arraySize;
+ info->format = header_dxt10->dxgiFormat;
+ info->dimension = get_dimension(NULL, header_dxt10);
+ info->alpha_mode = header_dxt10->miscFlags2 & 0x00000008;
+ info->data_offset = sizeof(DWORD) + sizeof(*header) + sizeof(*header_dxt10);
+ if (is_compressed(info->format)) {
+ info->pixel_format = (info->alpha_mode == WICDdsAlphaModePremultiplied)
?
+ &GUID_WICPixelFormat32bppPBGRA :
&GUID_WICPixelFormat32bppBGRA;
+ info->pixel_format_bpp = 32;
+ } else {
+ info->pixel_format = dxgi_format_to_wic_format(info->format);
+ info->pixel_format_bpp = get_bytes_per_block_from_format(info->format)
* 8;
+ }
+ } else {
+ format_info = get_dds_format(&header->ddspf);
+ info->format = format_info->dxgi_format;
+ info->dimension = get_dimension(header, NULL);
+ info->alpha_mode = get_alpha_mode_from_fourcc(header->ddspf.fourCC);
+ info->data_offset = sizeof(DWORD) + sizeof(*header);
+ info->pixel_format = format_info->wic_format;
+ info->pixel_format_bpp = format_info->wic_format_bpp;
+ }
+
+ if (header->ddspf.flags & (DDPF_RGB | DDPF_ALPHA | DDPF_LUMINANCE)) {
+ info->bytes_per_block = header->ddspf.rgbBitCount / 8;
+ } else {
+ info->bytes_per_block = get_bytes_per_block_from_format(info->format);
+ }
+
+ info->frame_count = get_frame_count(info->depth, info->mip_levels,
info->array_size, info->dimension);
+}
+
+static void decode_block(const BYTE *block_data, UINT block_count, DXGI_FORMAT format,
+ UINT width, UINT height, DWORD *buffer)
+{
+ const BYTE *block, *color_indices, *alpha_indices, *alpha_table;
+ int i, j, x, y, block_x, block_y, color_index, alpha_index;
+ int block_size, color_offset, color_indices_offset;
+ WORD color[4], color_value = 0;
+ BYTE alpha[8], alpha_value = 0;
+
+ if (format == DXGI_FORMAT_BC1_UNORM) {
+ block_size = 8;
+ color_offset = 0;
+ color_indices_offset = 4;
+ } else {
+ block_size = 16;
+ color_offset = 8;
+ color_indices_offset = 12;
+ }
+ block_x = 0;
+ block_y = 0;
+
+ for (i = 0; i < block_count; i++)
+ {
+ block = block_data + i * block_size;
+
+ color[0] = *((WORD *)(block + color_offset));
+ color[1] = *((WORD *)(block + color_offset + 2));
+ color[2] = MAKE_RGB565(((GET_RGB565_R(color[0]) * 2 + GET_RGB565_R(color[1]) + 1)
/ 3),
+ ((GET_RGB565_G(color[0]) * 2 + GET_RGB565_G(color[1]) + 1)
/ 3),
+ ((GET_RGB565_B(color[0]) * 2 + GET_RGB565_B(color[1]) + 1)
/ 3));
+ color[3] = MAKE_RGB565(((GET_RGB565_R(color[0]) + GET_RGB565_R(color[1]) * 2 + 1)
/ 3),
+ ((GET_RGB565_G(color[0]) + GET_RGB565_G(color[1]) * 2 + 1)
/ 3),
+ ((GET_RGB565_B(color[0]) + GET_RGB565_B(color[1]) * 2 + 1)
/ 3));
+
+ switch (format)
+ {
+ case DXGI_FORMAT_BC1_UNORM:
+ if (color[0] <= color[1]) {
+ color[2] = MAKE_RGB565(((GET_RGB565_R(color[0]) +
GET_RGB565_R(color[1]) + 1) / 2),
+ ((GET_RGB565_G(color[0]) +
GET_RGB565_G(color[1]) + 1) / 2),
+ ((GET_RGB565_B(color[0]) +
GET_RGB565_B(color[1]) + 1) / 2));
+ color[3] = 0;
+ }
+ break;
+ case DXGI_FORMAT_BC2_UNORM:
+ alpha_table = block;
+ break;
+ case DXGI_FORMAT_BC3_UNORM:
+ alpha[0] = *block;
+ alpha[1] = *(block + 1);
+ if (alpha[0] > alpha[1]) {
+ for (j = 2; j < 8; j++)
+ {
+ alpha[j] = (BYTE)((alpha[0] * (8 - j) + alpha[1] * (j - 1) + 3) /
7);
+ }
+ } else {
+ for (j = 2; j < 6; j++)
+ {
+ alpha[j] = (BYTE)((alpha[0] * (6 - j) + alpha[1] * (j - 1) + 2) /
5);
+ }
+ alpha[6] = 0;
+ alpha[7] = 0xFF;
+ }
+ alpha_indices = block + 2;
+ break;
+ default:
+ break;
+ }
+
+ color_indices = block + color_indices_offset;
+ for (j = 0; j < 16; j++)
+ {
+ x = block_x + j % 4;
+ y = block_y + j / 4;
+ if (x >= width || y >= height) continue;
+
+ color_index = (color_indices[j / 4] >> ((j % 4) * 2)) & 0x3;
+ color_value = color[color_index];
+
+ switch (format)
+ {
+ case DXGI_FORMAT_BC1_UNORM:
+ if ((color[0] <= color[1]) && !color_value) {
+ color_value = 0;
+ alpha_value = 0;
+ } else {
+ alpha_value = 0xFF;
+ }
+ break;
+ case DXGI_FORMAT_BC2_UNORM:
+ alpha_value = (alpha_table[j / 2] >> (j % 2) * 4) & 0xF;
+ alpha_value = (BYTE)((alpha_value * 0xFF + 0x7)/ 0xF);
+ break;
+ case DXGI_FORMAT_BC3_UNORM:
+ alpha_index = (*((DWORD *)(alpha_indices + (j / 8) * 3)) >> ((j
% 8) * 3)) & 0x7;
+ alpha_value = alpha[alpha_index];
+ break;
+ default:
+ break;
+ }
+ buffer[x + y * width] = rgb565_to_argb(color_value, alpha_value);
+ }
+
+ block_x += DDS_BLOCK_WIDTH;
+ if (block_x >= width) {
+ block_x = 0;
+ block_y += DDS_BLOCK_HEIGHT;
+ }
+ }
+}
+
+static inline DdsDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
+{
+ return CONTAINING_RECORD(iface, DdsDecoder, IWICBitmapDecoder_iface);
+}
+
+static inline DdsDecoder *impl_from_IWICDdsDecoder(IWICDdsDecoder *iface)
+{
+ return CONTAINING_RECORD(iface, DdsDecoder, IWICDdsDecoder_iface);
+}
+
+static inline DdsDecoder *impl_from_IWICWineDecoder(IWICWineDecoder *iface)
+{
+ return CONTAINING_RECORD(iface, DdsDecoder, IWICWineDecoder_iface);
+}
+
+static inline DdsFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode
*iface)
+{
+ return CONTAINING_RECORD(iface, DdsFrameDecode, IWICBitmapFrameDecode_iface);
+}
+
+static inline DdsFrameDecode *impl_from_IWICDdsFrameDecode(IWICDdsFrameDecode *iface)
+{
+ return CONTAINING_RECORD(iface, DdsFrameDecode, IWICDdsFrameDecode_iface);
+}
+
+static inline DdsEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
+{
+ return CONTAINING_RECORD(iface, DdsEncoder, IWICBitmapEncoder_iface);
+}
+
+static inline DdsEncoder *impl_from_IWICDdsEncoder(IWICDdsEncoder *iface)
+{
+ return CONTAINING_RECORD(iface, DdsEncoder, IWICDdsEncoder_iface);
+}
+
+static inline DdsFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface)
+{
+ return CONTAINING_RECORD(iface, DdsFrameEncode, IWICBitmapFrameEncode_iface);
+}
+
+static HRESULT WINAPI DdsFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID
iid,
+ void **ppv)
+{
+ DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapSource, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameDecode, iid)) {
+ *ppv = &This->IWICBitmapFrameDecode_iface;
+ } else if (IsEqualGUID(&IID_IWICDdsFrameDecode, iid)) {
+ *ppv = &This->IWICDdsFrameDecode_iface;
+ } else {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI DdsFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
+{
+ DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI DdsFrameDecode_Release(IWICBitmapFrameDecode *iface)
+{
+ DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ if (ref == 0) {
+ if (This->pixel_data != This->block_data) free(This->pixel_data);
+ free(This->block_data);
+ free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI DdsFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
+ UINT *puiWidth, UINT *puiHeight)
+{
+ DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ if (!puiWidth || !puiHeight) return E_INVALIDARG;
+
+ *puiWidth = This->info.width;
+ *puiHeight = This->info.height;
+
+ TRACE("(%p) -> (%d,%d)\n", iface, *puiWidth, *puiHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DdsFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ if (!pPixelFormat) return E_INVALIDARG;
+
+ *pPixelFormat = *This->info.pixel_format;
+
+ TRACE("(%p) -> %s\n", iface, debugstr_guid(pPixelFormat));
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DdsFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
+ double *pDpiX, double *pDpiY)
+{
+ FIXME("(%p,%p,%p): stub.\n", iface, pDpiX, pDpiY);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
+ IWICPalette *pIPalette)
+{
+ FIXME("(%p,%p): stub.\n", iface, pIPalette);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
+ const WICRect *prc, UINT cbStride, UINT
cbBufferSize, BYTE *pbBuffer)
+{
+ DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
+ UINT bpp, frame_stride, frame_size;
+ INT x, y, width, height;
+ HRESULT hr;
+
+ TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride,
cbBufferSize, pbBuffer);
+
+ if (!pbBuffer) return E_INVALIDARG;
+
+ bpp = This->info.pixel_format_bpp;
+ if (!bpp) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+
+ frame_stride = This->info.width * bpp / 8;
+ frame_size = frame_stride * This->info.height;
+ if (!prc) {
+ if (cbStride < frame_stride) return E_INVALIDARG;
+ if (cbBufferSize < frame_size) return WINCODEC_ERR_INSUFFICIENTBUFFER;
+ } else {
+ x = prc->X;
+ y = prc->Y;
+ width = prc->Width;
+ height = prc->Height;
+ if (x < 0 || y < 0 || width <= 0 || height <= 0 ||
+ x + width > This->info.width ||
+ y + height > This->info.height) {
+ return E_INVALIDARG;
+ }
+ if (cbStride < width * bpp / 8) return E_INVALIDARG;
+ if (cbBufferSize < cbStride * height) return
WINCODEC_ERR_INSUFFICIENTBUFFER;
+ }
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->pixel_data) {
+ if (is_compressed(This->info.format)) {
+ This->pixel_data = malloc(frame_size);
+ if (!This->pixel_data) {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+ decode_block(This->block_data, This->info.width_in_blocks *
This->info.height_in_blocks, This->info.format,
+ This->info.width, This->info.height, (DWORD
*)This->pixel_data);
+ } else {
+ This->pixel_data = This->block_data;
+ }
+ }
+
+ hr = copy_pixels(bpp, This->pixel_data, This->info.width, This->info.height,
frame_stride,
+ prc, cbStride, cbBufferSize, pbBuffer);
+
+end:
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface,
+ IWICMetadataQueryReader
**ppIMetadataQueryReader)
+{
+ FIXME("(%p,%p): stub.\n", iface, ppIMetadataQueryReader);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
+ UINT cCount, IWICColorContext
**ppIColorContexts, UINT *pcActualCount)
+{
+ FIXME("(%p,%u,%p,%p): stub.\n", iface, cCount, ppIColorContexts,
pcActualCount);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ FIXME("(%p,%p): stub.\n", iface, ppIThumbnail);
+
+ return E_NOTIMPL;
+}
+
+static const IWICBitmapFrameDecodeVtbl DdsFrameDecode_Vtbl = {
+ DdsFrameDecode_QueryInterface,
+ DdsFrameDecode_AddRef,
+ DdsFrameDecode_Release,
+ DdsFrameDecode_GetSize,
+ DdsFrameDecode_GetPixelFormat,
+ DdsFrameDecode_GetResolution,
+ DdsFrameDecode_CopyPalette,
+ DdsFrameDecode_CopyPixels,
+ DdsFrameDecode_GetMetadataQueryReader,
+ DdsFrameDecode_GetColorContexts,
+ DdsFrameDecode_GetThumbnail
+};
+
+static HRESULT WINAPI DdsFrameDecode_Dds_QueryInterface(IWICDdsFrameDecode *iface,
+ REFIID iid, void **ppv)
+{
+ DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
+ return DdsFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid,
ppv);
+}
+
+static ULONG WINAPI DdsFrameDecode_Dds_AddRef(IWICDdsFrameDecode *iface)
+{
+ DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
+ return DdsFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
+}
+
+static ULONG WINAPI DdsFrameDecode_Dds_Release(IWICDdsFrameDecode *iface)
+{
+ DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
+ return DdsFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
+}
+
+static HRESULT WINAPI DdsFrameDecode_Dds_GetSizeInBlocks(IWICDdsFrameDecode *iface,
+ UINT *widthInBlocks, UINT
*heightInBlocks)
+{
+ DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
+
+ if (!widthInBlocks || !heightInBlocks) return E_INVALIDARG;
+
+ *widthInBlocks = This->info.width_in_blocks;
+ *heightInBlocks = This->info.height_in_blocks;
+
+ TRACE("(%p,%p,%p) -> (%d,%d)\n", iface, widthInBlocks, heightInBlocks,
*widthInBlocks, *heightInBlocks);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DdsFrameDecode_Dds_GetFormatInfo(IWICDdsFrameDecode *iface,
+ WICDdsFormatInfo *formatInfo)
+{
+ DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
+
+ if (!formatInfo) return E_INVALIDARG;
+
+ formatInfo->DxgiFormat = This->info.format;
+ formatInfo->BytesPerBlock = This->info.bytes_per_block;
+ formatInfo->BlockWidth = This->info.block_width;
+ formatInfo->BlockHeight = This->info.block_height;
+
+ TRACE("(%p,%p) -> (0x%x,%d,%d,%d)\n", iface, formatInfo,
+ formatInfo->DxgiFormat, formatInfo->BytesPerBlock,
formatInfo->BlockWidth, formatInfo->BlockHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DdsFrameDecode_Dds_CopyBlocks(IWICDdsFrameDecode *iface,
+ const WICRect *boundsInBlocks, UINT
stride, UINT bufferSize,
+ BYTE *buffer)
+{
+ DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface);
+ int x, y, width, height;
+ UINT bytes_per_block, frame_stride, frame_size;
+
+ TRACE("(%p,%p,%u,%u,%p)\n", iface, boundsInBlocks, stride, bufferSize,
buffer);
+
+ if (!buffer) return E_INVALIDARG;
+
+ bytes_per_block = This->info.bytes_per_block;
+ frame_stride = This->info.width_in_blocks * bytes_per_block;
+ frame_size = frame_stride * This->info.height_in_blocks;
+
+ if (!boundsInBlocks) {
+ if (stride < frame_stride) return E_INVALIDARG;
+ if (bufferSize < frame_size) return E_INVALIDARG;
+ } else {
+ x = boundsInBlocks->X;
+ y = boundsInBlocks->Y;
+ width = boundsInBlocks->Width;
+ height = boundsInBlocks->Height;
+ if (x < 0 || y < 0 || width <= 0 || height <= 0 ||
+ x + width > This->info.width_in_blocks ||
+ y + height > This->info.height_in_blocks) {
+ return E_INVALIDARG;
+ }
+ if (stride < width * bytes_per_block) return E_INVALIDARG;
+ if (bufferSize < stride * height) return E_INVALIDARG;
+ }
+
+ return copy_pixels(This->info.bytes_per_block * 8, This->block_data,
This->info.width_in_blocks,
+ This->info.height_in_blocks, frame_stride, boundsInBlocks,
stride, bufferSize, buffer);
+}
+
+static const IWICDdsFrameDecodeVtbl DdsFrameDecode_Dds_Vtbl = {
+ DdsFrameDecode_Dds_QueryInterface,
+ DdsFrameDecode_Dds_AddRef,
+ DdsFrameDecode_Dds_Release,
+ DdsFrameDecode_Dds_GetSizeInBlocks,
+ DdsFrameDecode_Dds_GetFormatInfo,
+ DdsFrameDecode_Dds_CopyBlocks
+};
+
+static HRESULT DdsFrameDecode_CreateInstance(DdsFrameDecode **frame_decode)
+{
+ DdsFrameDecode *result;
+
+ result = malloc(sizeof(*result));
+ if (!result) return E_OUTOFMEMORY;
+
+ result->IWICBitmapFrameDecode_iface.lpVtbl = &DdsFrameDecode_Vtbl;
+ result->IWICDdsFrameDecode_iface.lpVtbl = &DdsFrameDecode_Dds_Vtbl;
+ result->ref = 1;
+#ifdef __REACTOS__
+ InitializeCriticalSection(&result->lock);
+#else
+ InitializeCriticalSectionEx(&result->lock, 0,
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
+#endif
+ result->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
DdsFrameDecode.lock");
+
+ *frame_decode = result;
+ return S_OK;
+}
+
+static HRESULT WINAPI DdsDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
+ void **ppv)
+{
+ DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapDecoder, iid)) {
+ *ppv = &This->IWICBitmapDecoder_iface;
+ } else if (IsEqualIID(&IID_IWICDdsDecoder, iid)) {
+ *ppv = &This->IWICDdsDecoder_iface;
+ } else if (IsEqualIID(&IID_IWICWineDecoder, iid)) {
+ *ppv = &This->IWICWineDecoder_iface;
+ } else {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI DdsDecoder_AddRef(IWICBitmapDecoder *iface)
+{
+ DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI DdsDecoder_Release(IWICBitmapDecoder *iface)
+{
+ DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ if (ref == 0)
+ {
+ This->lock.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&This->lock);
+ if (This->stream) IStream_Release(This->stream);
+ free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI DdsDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream
*stream,
+ DWORD *capability)
+{
+ FIXME("(%p,%p,%p): stub.\n", iface, stream, capability);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsDecoder_Initialize(IWICBitmapDecoder *iface, IStream
*pIStream,
+ WICDecodeOptions cacheOptions)
+{
+ DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
+
+ EnterCriticalSection(&This->lock);
+
+ hr = IWICWineDecoder_Initialize(&This->IWICWineDecoder_iface, pIStream,
cacheOptions);
+ if (FAILED(hr)) goto end;
+
+ if (This->info.dimension == WICDdsTextureCube ||
+ (This->info.format != DXGI_FORMAT_BC1_UNORM &&
+ This->info.format != DXGI_FORMAT_BC2_UNORM &&
+ This->info.format != DXGI_FORMAT_BC3_UNORM)) {
+ IStream_Release(pIStream);
+ This->stream = NULL;
+ This->initialized = FALSE;
+ hr = WINCODEC_ERR_BADHEADER;
+ }
+
+end:
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
+ GUID *pguidContainerFormat)
+{
+ TRACE("(%p,%p)\n", iface, pguidContainerFormat);
+
+ memcpy(pguidContainerFormat, &GUID_ContainerFormatDds, sizeof(GUID));
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DdsDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
+ IWICBitmapDecoderInfo **ppIDecoderInfo)
+{
+ TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
+
+ return get_decoder_info(&CLSID_WICDdsDecoder, ppIDecoderInfo);
+}
+
+static HRESULT WINAPI DdsDecoder_CopyPalette(IWICBitmapDecoder *iface,
+ IWICPalette *pIPalette)
+{
+ TRACE("(%p,%p)\n", iface, pIPalette);
+
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
+}
+
+static HRESULT WINAPI DdsDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
+ IWICMetadataQueryReader
**ppIMetadataQueryReader)
+{
+ if (!ppIMetadataQueryReader) return E_INVALIDARG;
+
+ FIXME("(%p,%p)\n", iface, ppIMetadataQueryReader);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsDecoder_GetPreview(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIBitmapSource)
+{
+ TRACE("(%p,%p)\n", iface, ppIBitmapSource);
+
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI DdsDecoder_GetColorContexts(IWICBitmapDecoder *iface,
+ UINT cCount, IWICColorContext
**ppDdslorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppDdslorContexts, pcActualCount);
+
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI DdsDecoder_GetThumbnail(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static HRESULT WINAPI DdsDecoder_GetFrameCount(IWICBitmapDecoder *iface,
+ UINT *pCount)
+{
+ DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
+
+ if (!pCount) return E_INVALIDARG;
+ if (!This->initialized) return WINCODEC_ERR_WRONGSTATE;
+
+ EnterCriticalSection(&This->lock);
+
+ *pCount = This->info.frame_count;
+
+ LeaveCriticalSection(&This->lock);
+
+ TRACE("(%p) -> %d\n", iface, *pCount);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DdsDecoder_GetFrame(IWICBitmapDecoder *iface,
+ UINT index, IWICBitmapFrameDecode
**ppIBitmapFrame)
+{
+ DdsDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ UINT array_index, mip_level, slice_index;
+
+ TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
+
+ if (!ppIBitmapFrame) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->initialized) {
+ LeaveCriticalSection(&This->lock);
+ return WINCODEC_ERR_WRONGSTATE;
+ }
+
+ get_frame_dds_index(index, &This->info, &array_index, &mip_level,
&slice_index);
+
+ LeaveCriticalSection(&This->lock);
+
+ return DdsDecoder_Dds_GetFrame(&This->IWICDdsDecoder_iface, array_index,
mip_level, slice_index, ppIBitmapFrame);
+}
+
+static const IWICBitmapDecoderVtbl DdsDecoder_Vtbl = {
+ DdsDecoder_QueryInterface,
+ DdsDecoder_AddRef,
+ DdsDecoder_Release,
+ DdsDecoder_QueryCapability,
+ DdsDecoder_Initialize,
+ DdsDecoder_GetContainerFormat,
+ DdsDecoder_GetDecoderInfo,
+ DdsDecoder_CopyPalette,
+ DdsDecoder_GetMetadataQueryReader,
+ DdsDecoder_GetPreview,
+ DdsDecoder_GetColorContexts,
+ DdsDecoder_GetThumbnail,
+ DdsDecoder_GetFrameCount,
+ DdsDecoder_GetFrame
+};
+
+static HRESULT WINAPI DdsDecoder_Dds_QueryInterface(IWICDdsDecoder *iface,
+ REFIID iid, void **ppv)
+{
+ DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
+ return DdsDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
+}
+
+static ULONG WINAPI DdsDecoder_Dds_AddRef(IWICDdsDecoder *iface)
+{
+ DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
+ return DdsDecoder_AddRef(&This->IWICBitmapDecoder_iface);
+}
+
+static ULONG WINAPI DdsDecoder_Dds_Release(IWICDdsDecoder *iface)
+{
+ DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
+ return DdsDecoder_Release(&This->IWICBitmapDecoder_iface);
+}
+
+static HRESULT WINAPI DdsDecoder_Dds_GetParameters(IWICDdsDecoder *iface,
+ WICDdsParameters *parameters)
+{
+ DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
+ HRESULT hr;
+
+ if (!parameters) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->initialized) {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ goto end;
+ }
+
+ parameters->Width = This->info.width;
+ parameters->Height = This->info.height;
+ parameters->Depth = This->info.depth;
+ parameters->MipLevels = This->info.mip_levels;
+ parameters->ArraySize = This->info.array_size;
+ parameters->DxgiFormat = This->info.format;
+ parameters->Dimension = This->info.dimension;
+ parameters->AlphaMode = This->info.alpha_mode;
+
+ TRACE("(%p) -> (%dx%d depth=%d mipLevels=%d arraySize=%d dxgiFormat=0x%x
dimension=0x%x alphaMode=0x%x)\n",
+ iface, parameters->Width, parameters->Height, parameters->Depth,
parameters->MipLevels,
+ parameters->ArraySize, parameters->DxgiFormat, parameters->Dimension,
parameters->AlphaMode);
+
+ hr = S_OK;
+
+end:
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface,
+ UINT arrayIndex, UINT mipLevel, UINT
sliceIndex,
+ IWICBitmapFrameDecode **bitmapFrame)
+{
+ DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
+ HRESULT hr;
+ LARGE_INTEGER seek;
+ UINT width, height, depth, block_width, block_height, width_in_blocks,
height_in_blocks, size;
+ UINT frame_width = 0, frame_height = 0, frame_width_in_blocks = 0,
frame_height_in_blocks = 0, frame_size = 0;
+ UINT bytes_per_block, i;
+ DWORD bytesread;
+ DdsFrameDecode *frame_decode = NULL;
+
+ TRACE("(%p,%u,%u,%u,%p)\n", iface, arrayIndex, mipLevel, sliceIndex,
bitmapFrame);
+
+ if (!bitmapFrame) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->initialized) {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ goto end;
+ }
+
+ if ((arrayIndex >= This->info.array_size && This->info.dimension !=
WICDdsTextureCube) ||
+ (arrayIndex >= This->info.array_size * 6) ||
+ (mipLevel >= This->info.mip_levels) ||
+ (sliceIndex >= This->info.depth)) {
+ hr = E_INVALIDARG;
+ goto end;
+ }
+
+ if (is_compressed(This->info.format)) {
+ block_width = DDS_BLOCK_WIDTH;
+ block_height = DDS_BLOCK_HEIGHT;
+ } else {
+ block_width = 1;
+ block_height = 1;
+ }
+ bytes_per_block = This->info.bytes_per_block;
+ seek.QuadPart = This->info.data_offset;
+
+ width = This->info.width;
+ height = This->info.height;
+ depth = This->info.depth;
+ for (i = 0; i < This->info.mip_levels; i++)
+ {
+ width_in_blocks = (width + block_width - 1) / block_width;
+ height_in_blocks = (height + block_height - 1) / block_height;
+ size = width_in_blocks * height_in_blocks * bytes_per_block;
+
+ if (i < mipLevel) {
+ seek.QuadPart += size * depth;
+ } else if (i == mipLevel){
+ seek.QuadPart += size * sliceIndex;
+ frame_width = width;
+ frame_height = height;
+ frame_width_in_blocks = width_in_blocks;
+ frame_height_in_blocks = height_in_blocks;
+ frame_size = frame_width_in_blocks * frame_height_in_blocks *
bytes_per_block;
+ if (arrayIndex == 0) break;
+ }
+ seek.QuadPart += arrayIndex * size * depth;
+
+ if (width > 1) width /= 2;
+ if (height > 1) height /= 2;
+ if (depth > 1) depth /= 2;
+ }
+
+ hr = DdsFrameDecode_CreateInstance(&frame_decode);
+ if (hr != S_OK) goto end;
+ frame_decode->info.width = frame_width;
+ frame_decode->info.height = frame_height;
+ frame_decode->info.format = This->info.format;
+ frame_decode->info.bytes_per_block = bytes_per_block;
+ frame_decode->info.block_width = block_width;
+ frame_decode->info.block_height = block_height;
+ frame_decode->info.width_in_blocks = frame_width_in_blocks;
+ frame_decode->info.height_in_blocks = frame_height_in_blocks;
+ frame_decode->info.pixel_format = This->info.pixel_format;
+ frame_decode->info.pixel_format_bpp = This->info.pixel_format_bpp;
+ frame_decode->block_data = malloc(frame_size);
+ frame_decode->pixel_data = NULL;
+ hr = IStream_Seek(This->stream, seek, SEEK_SET, NULL);
+ if (hr != S_OK) goto end;
+ hr = IStream_Read(This->stream, frame_decode->block_data, frame_size,
&bytesread);
+ if (hr != S_OK || bytesread != frame_size) {
+ hr = WINCODEC_ERR_STREAMREAD;
+ goto end;
+ }
+ *bitmapFrame = &frame_decode->IWICBitmapFrameDecode_iface;
+
+ hr = S_OK;
+
+end:
+ LeaveCriticalSection(&This->lock);
+
+ if (hr != S_OK && frame_decode)
DdsFrameDecode_Release(&frame_decode->IWICBitmapFrameDecode_iface);
+
+ return hr;
+}
+
+static const IWICDdsDecoderVtbl DdsDecoder_Dds_Vtbl = {
+ DdsDecoder_Dds_QueryInterface,
+ DdsDecoder_Dds_AddRef,
+ DdsDecoder_Dds_Release,
+ DdsDecoder_Dds_GetParameters,
+ DdsDecoder_Dds_GetFrame
+};
+
+static HRESULT WINAPI DdsDecoder_Wine_QueryInterface(IWICWineDecoder *iface, REFIID iid,
void **ppv)
+{
+ DdsDecoder *This = impl_from_IWICWineDecoder(iface);
+ return DdsDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
+}
+
+static ULONG WINAPI DdsDecoder_Wine_AddRef(IWICWineDecoder *iface)
+{
+ DdsDecoder *This = impl_from_IWICWineDecoder(iface);
+ return DdsDecoder_AddRef(&This->IWICBitmapDecoder_iface);
+}
+
+static ULONG WINAPI DdsDecoder_Wine_Release(IWICWineDecoder *iface)
+{
+ DdsDecoder *This = impl_from_IWICWineDecoder(iface);
+ return DdsDecoder_Release(&This->IWICBitmapDecoder_iface);
+}
+
+static HRESULT WINAPI DdsDecoder_Wine_Initialize(IWICWineDecoder *iface, IStream *stream,
WICDecodeOptions options)
+{
+ DdsDecoder *This = impl_from_IWICWineDecoder(iface);
+ DDS_HEADER_DXT10 header_dxt10;
+ LARGE_INTEGER seek;
+ DDS_HEADER header;
+ ULONG bytesread;
+ DWORD magic;
+ HRESULT hr;
+
+ TRACE("(This %p, stream %p, options %#x)\n", iface, stream, options);
+
+ EnterCriticalSection(&This->lock);
+
+ if (This->initialized) {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ goto end;
+ }
+
+ seek.QuadPart = 0;
+ hr = IStream_Seek(stream, seek, SEEK_SET, NULL);
+ if (FAILED(hr)) goto end;
+
+ hr = IStream_Read(stream, &magic, sizeof(magic), &bytesread);
+ if (FAILED(hr)) goto end;
+ if (bytesread != sizeof(magic)) {
+ hr = WINCODEC_ERR_STREAMREAD;
+ goto end;
+ }
+ if (magic != DDS_MAGIC) {
+ hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT;
+ goto end;
+ }
+
+ hr = IStream_Read(stream, &header, sizeof(header), &bytesread);
+ if (FAILED(hr)) goto end;
+ if (bytesread != sizeof(header)) {
+ hr = WINCODEC_ERR_STREAMREAD;
+ goto end;
+ }
+ if (header.size != sizeof(header)) {
+ hr = WINCODEC_ERR_BADHEADER;
+ goto end;
+ }
+
+ if (has_extended_header(&header)) {
+ hr = IStream_Read(stream, &header_dxt10, sizeof(header_dxt10),
&bytesread);
+ if (FAILED(hr)) goto end;
+ if (bytesread != sizeof(header_dxt10)) {
+ hr = WINCODEC_ERR_STREAMREAD;
+ goto end;
+ }
+ }
+
+ get_dds_info(&This->info, &header, &header_dxt10);
+
+ This->initialized = TRUE;
+ This->stream = stream;
+ IStream_AddRef(stream);
+
+end:
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static const IWICWineDecoderVtbl DdsDecoder_Wine_Vtbl = {
+ DdsDecoder_Wine_QueryInterface,
+ DdsDecoder_Wine_AddRef,
+ DdsDecoder_Wine_Release,
+ DdsDecoder_Wine_Initialize
+};
+
+static HRESULT WINAPI DdsFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID
iid, void **ppv)
+{
+ DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
+ {
+ *ppv = &This->IWICBitmapFrameEncode_iface;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI DdsFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
+{
+ DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI DdsFrameEncode_Release(IWICBitmapFrameEncode *iface)
+{
+ DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ if (ref == 0)
+ {
+ IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface);
+ free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI DdsFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
+ IPropertyBag2 *encoderOptions)
+{
+ DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, encoderOptions);
+ if (encoderOptions) FIXME("encoder options are not supported for
DDS.\n");
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (This->initialized)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ }
+ else
+ {
+ This->initialized = TRUE;
+ hr = S_OK;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
+ UINT width, UINT height)
+{
+ DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%u,%u)\n", iface, width, height);
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (!This->initialized || This->frame_created)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ }
+ else
+ {
+ This->width = width;
+ This->height = height;
+ hr = S_OK;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
+ double dpiX, double dpiY)
+{
+ DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (!This->initialized || This->frame_created)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ }
+ else
+ {
+ This->dpi_x = dpiX;
+ This->dpi_y = dpiY;
+ hr = S_OK;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
+ WICPixelFormatGUID *pixelFormat)
+{
+ DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%s)\n", iface, debugstr_guid(pixelFormat));
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (!This->initialized)
+ {
+ hr = WINCODEC_ERR_NOTINITIALIZED;
+ }
+ else if (This->frame_created)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ }
+ else
+ {
+ *pixelFormat = GUID_WICPixelFormat32bppBGRA;
+ hr = S_OK;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
+ UINT count, IWICColorContext
**colorContext)
+{
+ FIXME("(%p,%u,%p): stub\n", iface, count, colorContext);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
+ IWICPalette *palette)
+{
+ FIXME("(%p,%p): stub\n", iface, palette);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
+ IWICBitmapSource *thumbnail)
+{
+ TRACE("(%p,%p)\n", iface, thumbnail);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI DdsFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
+ UINT lineCount, UINT stride, UINT
bufferSize, BYTE *pixels)
+{
+ FIXME("(%p,%u,%u,%u,%p): stub\n", iface, lineCount, stride, bufferSize,
pixels);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
+ IWICBitmapSource *bitmapSource, WICRect
*rc)
+{
+ FIXME("(%p,%p,%s): stub\n", iface, bitmapSource, debug_wic_rect(rc));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameEncode_Commit(IWICBitmapFrameEncode *iface)
+{
+ FIXME("(%p): stub\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface,
+ IWICMetadataQueryWriter
**metadataQueryWriter)
+{
+ FIXME("(%p,%p): stub\n", iface, metadataQueryWriter);
+ return E_NOTIMPL;
+}
+
+static const IWICBitmapFrameEncodeVtbl DdsFrameEncode_Vtbl = {
+ DdsFrameEncode_QueryInterface,
+ DdsFrameEncode_AddRef,
+ DdsFrameEncode_Release,
+ DdsFrameEncode_Initialize,
+ DdsFrameEncode_SetSize,
+ DdsFrameEncode_SetResolution,
+ DdsFrameEncode_SetPixelFormat,
+ DdsFrameEncode_SetColorContexts,
+ DdsFrameEncode_SetPalette,
+ DdsFrameEncode_SetThumbnail,
+ DdsFrameEncode_WritePixels,
+ DdsFrameEncode_WriteSource,
+ DdsFrameEncode_Commit,
+ DdsFrameEncode_GetMetadataQueryWriter
+};
+
+HRESULT DdsDecoder_CreateInstance(REFIID iid, void** ppv)
+{
+ DdsDecoder *This;
+ HRESULT ret;
+
+ TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
+
+ *ppv = NULL;
+
+ This = malloc(sizeof(DdsDecoder));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->IWICBitmapDecoder_iface.lpVtbl = &DdsDecoder_Vtbl;
+ This->IWICDdsDecoder_iface.lpVtbl = &DdsDecoder_Dds_Vtbl;
+ This->IWICWineDecoder_iface.lpVtbl = &DdsDecoder_Wine_Vtbl;
+ This->ref = 1;
+ This->initialized = FALSE;
+ This->stream = NULL;
+#ifdef __REACTOS__
+ InitializeCriticalSection(&This->lock);
+#else
+ InitializeCriticalSectionEx(&This->lock, 0,
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
+#endif
+ This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
DdsDecoder.lock");
+
+ ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid,
ppv);
+ IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
+
+ return ret;
+}
+
+static HRESULT WINAPI DdsEncoder_Dds_QueryInterface(IWICDdsEncoder *iface, REFIID iid,
+ void **ppv)
+{
+ DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
+ return IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid,
ppv);
+}
+
+static ULONG WINAPI DdsEncoder_Dds_AddRef(IWICDdsEncoder *iface)
+{
+ DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
+ return IWICBitmapEncoder_AddRef(&This->IWICBitmapEncoder_iface);
+}
+
+static ULONG WINAPI DdsEncoder_Dds_Release(IWICDdsEncoder *iface)
+{
+ DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
+ return IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
+}
+
+static HRESULT WINAPI DdsEncoder_Dds_SetParameters(IWICDdsEncoder *iface,
+ WICDdsParameters *parameters)
+{
+ DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, parameters);
+
+ if (!parameters) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->stream)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ goto end;
+ }
+
+ This->info.width = parameters->Width;
+ This->info.height = parameters->Height;
+ This->info.depth = parameters->Depth;
+ This->info.mip_levels = parameters->MipLevels;
+ This->info.array_size = parameters->ArraySize;
+ This->info.format = parameters->DxgiFormat;
+ This->info.dimension = parameters->Dimension;
+ This->info.alpha_mode = parameters->AlphaMode;
+
+ This->info.bytes_per_block =
get_bytes_per_block_from_format(This->info.format);
+ This->info.frame_count = get_frame_count(This->info.depth,
This->info.mip_levels,
+ This->info.array_size,
This->info.dimension);
+
+ hr = S_OK;
+
+end:
+ LeaveCriticalSection(&This->lock);
+ return hr;
+}
+
+static HRESULT WINAPI DdsEncoder_Dds_GetParameters(IWICDdsEncoder *iface,
+ WICDdsParameters *parameters)
+{
+ DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, parameters);
+
+ if (!parameters) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->stream)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ goto end;
+ }
+
+ parameters->Width = This->info.width;
+ parameters->Height = This->info.height;
+ parameters->Depth = This->info.depth;
+ parameters->MipLevels = This->info.mip_levels;
+ parameters->ArraySize = This->info.array_size;
+ parameters->DxgiFormat = This->info.format;
+ parameters->Dimension = This->info.dimension;
+ parameters->AlphaMode = This->info.alpha_mode;
+
+ TRACE("(%p,%p) -> (%dx%d depth=%u mipLevels=%u arraySize=%u dxgiFormat=%#x
dimension=%#x alphaMode=%#x)\n",
+ iface, parameters, parameters->Width, parameters->Height,
parameters->Depth, parameters->MipLevels,
+ parameters->ArraySize, parameters->DxgiFormat, parameters->Dimension,
parameters->AlphaMode);
+
+ hr = S_OK;
+
+end:
+ LeaveCriticalSection(&This->lock);
+ return hr;
+}
+
+static HRESULT WINAPI DdsEncoder_Dds_CreateNewFrame(IWICDdsEncoder *iface,
+ IWICBitmapFrameEncode
**frameEncode,
+ UINT *arrayIndex, UINT *mipLevel,
UINT *sliceIndex)
+{
+ DdsEncoder *This = impl_from_IWICDdsEncoder(iface);
+ UINT array_index, mip_level, slice_index;
+ DdsFrameEncode *result;
+ HRESULT hr;
+
+ TRACE("(%p,%p,%p,%p,%p)\n", iface, frameEncode, arrayIndex, mipLevel,
sliceIndex);
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->stream || This->committed || This->uncommitted_frame)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ goto end;
+ }
+
+ result = malloc(sizeof(*result));
+ if (!result)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ get_frame_dds_index(This->frame_index, &This->info, &array_index,
&mip_level, &slice_index);
+ if (arrayIndex) *arrayIndex = array_index;
+ if (mipLevel) *mipLevel = mip_level;
+ if (sliceIndex) *sliceIndex = slice_index;
+
+ This->frame_index++;
+ result->IWICBitmapFrameEncode_iface.lpVtbl = &DdsFrameEncode_Vtbl;
+ result->ref = 1;
+ result->parent = This;
+ result->parent->uncommitted_frame = TRUE;
+ result->initialized = FALSE;
+ result->frame_created = FALSE;
+ IWICDdsEncoder_AddRef(iface);
+
+ *frameEncode = &result->IWICBitmapFrameEncode_iface;
+ hr = S_OK;
+
+end:
+ LeaveCriticalSection(&This->lock);
+ return hr;
+}
+
+static const IWICDdsEncoderVtbl DdsEncoder_Dds_Vtbl =
+{
+ DdsEncoder_Dds_QueryInterface,
+ DdsEncoder_Dds_AddRef,
+ DdsEncoder_Dds_Release,
+ DdsEncoder_Dds_SetParameters,
+ DdsEncoder_Dds_GetParameters,
+ DdsEncoder_Dds_CreateNewFrame
+};
+
+static HRESULT WINAPI DdsEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
+ void **ppv)
+{
+ DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
+ FIXME("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapEncoder, iid)) {
+ *ppv = &This->IWICBitmapEncoder_iface;
+ } else if (IsEqualIID(&IID_IWICDdsEncoder, iid)) {
+ *ppv = &This->IWICDdsEncoder_iface;
+ } else {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI DdsEncoder_AddRef(IWICBitmapEncoder *iface)
+{
+ DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI DdsEncoder_Release(IWICBitmapEncoder *iface)
+{
+ DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ if (ref == 0) {
+ This->lock.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&This->lock);
+ if (This->stream) IStream_Release(This->stream);
+ free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI DdsEncoder_Initialize(IWICBitmapEncoder *iface,
+ IStream *stream, WICBitmapEncoderCacheOption
cacheOption)
+{
+ DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p,%u)\n", iface, stream, cacheOption);
+
+ if (cacheOption != WICBitmapEncoderNoCache)
+ FIXME("Cache option %#x is not supported.\n", cacheOption);
+
+ if (!stream) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+
+ if (This->stream)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ goto end;
+ }
+
+ This->stream = stream;
+ IStream_AddRef(stream);
+
+ This->info.width = 1;
+ This->info.height = 1;
+ This->info.depth = 1;
+ This->info.mip_levels = 1;
+ This->info.array_size = 1;
+ This->info.frame_count = 1;
+ This->info.data_offset = 0;
+ This->info.bytes_per_block =
get_bytes_per_block_from_format(DXGI_FORMAT_BC3_UNORM);
+ This->info.format = DXGI_FORMAT_BC3_UNORM;
+ This->info.dimension = WICDdsTexture2D;
+ This->info.alpha_mode = WICDdsAlphaModeUnknown;
+ This->info.pixel_format = &GUID_WICPixelFormatUndefined;
+ This->info.pixel_format_bpp = 0;
+
+ hr = S_OK;
+
+end:
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID
*format)
+{
+ TRACE("(%p,%p)\n", iface, format);
+
+ if (!format)
+ return E_INVALIDARG;
+
+ memcpy(format, &GUID_ContainerFormatDds, sizeof(*format));
+ return S_OK;
+}
+
+static HRESULT WINAPI DdsEncoder_GetEncoderInfo(IWICBitmapEncoder *iface,
IWICBitmapEncoderInfo **info)
+{
+ IWICComponentInfo *comp_info;
+ HRESULT hr;
+
+ TRACE("%p,%p\n", iface, info);
+
+ if (!info) return E_INVALIDARG;
+
+ hr = CreateComponentInfo(&CLSID_WICDdsEncoder, &comp_info);
+ if (hr == S_OK) {
+ hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo,
(void **)info);
+ IWICComponentInfo_Release(comp_info);
+ }
+ return hr;
+}
+
+static HRESULT WINAPI DdsEncoder_SetColorContexts(IWICBitmapEncoder *iface,
+ UINT cCount, IWICColorContext
**ppIColorContext)
+{
+ FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette
*palette)
+{
+ DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, palette);
+
+ EnterCriticalSection(&This->lock);
+
+ hr = This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION :
WINCODEC_ERR_NOTINITIALIZED;
+
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI DdsEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource
*pIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, pIThumbnail);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI DdsEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource
*pIPreview)
+{
+ TRACE("(%p,%p)\n", iface, pIPreview);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI DdsEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
+ IWICBitmapFrameEncode **frameEncode,
IPropertyBag2 **encoderOptions)
+{
+ DdsEncoder *This = impl_from_IWICBitmapEncoder(iface);
+
+ TRACE("(%p,%p,%p)\n", iface, frameEncode, encoderOptions);
+
+ return IWICDdsEncoder_CreateNewFrame(&This->IWICDdsEncoder_iface, frameEncode,
NULL, NULL, NULL);
+}
+
+static HRESULT WINAPI DdsEncoder_Commit(IWICBitmapEncoder *iface)
+{
+ FIXME("(%p): stub\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DdsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
+ IWICMetadataQueryWriter
**ppIMetadataQueryWriter)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
+ return E_NOTIMPL;
+}
+
+static const IWICBitmapEncoderVtbl DdsEncoder_Vtbl = {
+ DdsEncoder_QueryInterface,
+ DdsEncoder_AddRef,
+ DdsEncoder_Release,
+ DdsEncoder_Initialize,
+ DdsEncoder_GetContainerFormat,
+ DdsEncoder_GetEncoderInfo,
+ DdsEncoder_SetColorContexts,
+ DdsEncoder_SetPalette,
+ DdsEncoder_SetThumbnail,
+ DdsEncoder_SetPreview,
+ DdsEncoder_CreateNewFrame,
+ DdsEncoder_Commit,
+ DdsEncoder_GetMetadataQueryWriter
+};
+
+HRESULT DdsEncoder_CreateInstance( REFIID iid, void **ppv)
+{
+ DdsEncoder *This;
+ HRESULT ret;
+
+ TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
+
+ *ppv = NULL;
+
+ This = malloc(sizeof(DdsEncoder));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->IWICBitmapEncoder_iface.lpVtbl = &DdsEncoder_Vtbl;
+ This->IWICDdsEncoder_iface.lpVtbl = &DdsEncoder_Dds_Vtbl;
+ This->ref = 1;
+ This->stream = NULL;
+ This->frame_count = 0;
+ This->frame_index = 0;
+ This->uncommitted_frame = FALSE;
+ This->committed = FALSE;
+#ifdef __REACTOS__
+ InitializeCriticalSection(&This->lock);
+#else
+ InitializeCriticalSectionEx(&This->lock, 0,
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
+#endif
+ This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
DdsEncoder.lock");
+
+ ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid,
ppv);
+ IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
+
+ return ret;
+}
diff --git a/dll/win32/windowscodecs/decoder.c b/dll/win32/windowscodecs/decoder.c
new file mode 100644
index 00000000000..08fe23e1bf0
--- /dev/null
+++ b/dll/win32/windowscodecs/decoder.c
@@ -0,0 +1,811 @@
+/*
+ * Copyright 2020 Esme Povirk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+typedef struct {
+ IWICBitmapDecoder IWICBitmapDecoder_iface;
+ LONG ref;
+ CRITICAL_SECTION lock; /* must be held when stream or decoder is accessed */
+ IStream *stream;
+ struct decoder *decoder;
+ struct decoder_info decoder_info;
+ struct decoder_stat file_info;
+ WICDecodeOptions cache_options;
+} CommonDecoder;
+
+static inline CommonDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
+{
+ return CONTAINING_RECORD(iface, CommonDecoder, IWICBitmapDecoder_iface);
+}
+
+static HRESULT WINAPI CommonDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID
iid,
+ void **ppv)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder,
iid))
+ {
+ *ppv = &This->IWICBitmapDecoder_iface;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI CommonDecoder_AddRef(IWICBitmapDecoder *iface)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI CommonDecoder_Release(IWICBitmapDecoder *iface)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ if (ref == 0)
+ {
+ if (This->stream)
+ IStream_Release(This->stream);
+ This->lock.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&This->lock);
+ decoder_destroy(This->decoder);
+ free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI CommonDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream
*stream,
+ DWORD *capability)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p,%p)\n", iface, stream, capability);
+
+ if (!stream || !capability) return E_INVALIDARG;
+
+ hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
+ if (hr != S_OK) return hr;
+
+ *capability = (This->file_info.flags & DECODER_FLAGS_CAPABILITY_MASK);
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoder_Initialize(IWICBitmapDecoder *iface, IStream
*pIStream,
+ WICDecodeOptions cacheOptions)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ HRESULT hr=S_OK;
+
+ TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
+
+ EnterCriticalSection(&This->lock);
+
+ if (This->stream)
+ hr = WINCODEC_ERR_WRONGSTATE;
+
+ if (SUCCEEDED(hr))
+ hr = decoder_initialize(This->decoder, pIStream, &This->file_info);
+
+ if (SUCCEEDED(hr))
+ {
+ This->cache_options = cacheOptions;
+ This->stream = pIStream;
+ IStream_AddRef(This->stream);
+ }
+
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
+ GUID *pguidContainerFormat)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ memcpy(pguidContainerFormat, &This->decoder_info.container_format,
sizeof(GUID));
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
+ IWICBitmapDecoderInfo **ppIDecoderInfo)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
+
+ return get_decoder_info(&This->decoder_info.clsid, ppIDecoderInfo);
+}
+
+static HRESULT WINAPI CommonDecoder_CopyPalette(IWICBitmapDecoder *iface,
+ IWICPalette *palette)
+{
+ TRACE("(%p,%p)\n", iface, palette);
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
+}
+
+static HRESULT WINAPI CommonDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
+ IWICMetadataQueryReader **reader)
+{
+ TRACE("(%p,%p)\n", iface, reader);
+
+ if (!reader) return E_INVALIDARG;
+
+ *reader = NULL;
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI CommonDecoder_GetPreview(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIBitmapSource)
+{
+ TRACE("(%p,%p)\n", iface, ppIBitmapSource);
+
+ if (!ppIBitmapSource) return E_INVALIDARG;
+
+ *ppIBitmapSource = NULL;
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI CommonDecoder_GetColorContexts(IWICBitmapDecoder *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI CommonDecoder_GetThumbnail(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+
+ if (!ppIThumbnail) return E_INVALIDARG;
+
+ *ppIThumbnail = NULL;
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static HRESULT WINAPI CommonDecoder_GetFrameCount(IWICBitmapDecoder *iface,
+ UINT *pCount)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ if (!pCount) return E_INVALIDARG;
+
+ if (This->stream)
+ *pCount = This->file_info.frame_count;
+ else
+ *pCount = 0;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface,
+ UINT index, IWICBitmapFrameDecode **ppIBitmapFrame);
+
+static const IWICBitmapDecoderVtbl CommonDecoder_Vtbl = {
+ CommonDecoder_QueryInterface,
+ CommonDecoder_AddRef,
+ CommonDecoder_Release,
+ CommonDecoder_QueryCapability,
+ CommonDecoder_Initialize,
+ CommonDecoder_GetContainerFormat,
+ CommonDecoder_GetDecoderInfo,
+ CommonDecoder_CopyPalette,
+ CommonDecoder_GetMetadataQueryReader,
+ CommonDecoder_GetPreview,
+ CommonDecoder_GetColorContexts,
+ CommonDecoder_GetThumbnail,
+ CommonDecoder_GetFrameCount,
+ CommonDecoder_GetFrame
+};
+
+typedef struct {
+ IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
+ IWICMetadataBlockReader IWICMetadataBlockReader_iface;
+ LONG ref;
+ CommonDecoder *parent;
+ DWORD frame;
+ struct decoder_frame decoder_frame;
+ BOOL metadata_initialized;
+ UINT metadata_count;
+ struct decoder_block* metadata_blocks;
+} CommonDecoderFrame;
+
+static inline CommonDecoderFrame *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode
*iface)
+{
+ return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICBitmapFrameDecode_iface);
+}
+
+static inline CommonDecoderFrame
*impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
+{
+ return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICMetadataBlockReader_iface);
+}
+
+static HRESULT WINAPI CommonDecoderFrame_QueryInterface(IWICBitmapFrameDecode *iface,
REFIID iid,
+ void **ppv)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapSource, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
+ {
+ *ppv = &This->IWICBitmapFrameDecode_iface;
+ }
+ else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid) &&
+ (This->parent->file_info.flags &
WICBitmapDecoderCapabilityCanEnumerateMetadata))
+ {
+ *ppv = &This->IWICMetadataBlockReader_iface;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI CommonDecoderFrame_AddRef(IWICBitmapFrameDecode *iface)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI CommonDecoderFrame_Release(IWICBitmapFrameDecode *iface)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ if (ref == 0)
+ {
+ IWICBitmapDecoder_Release(&This->parent->IWICBitmapDecoder_iface);
+ free(This->metadata_blocks);
+ free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetSize(IWICBitmapFrameDecode *iface,
+ UINT *puiWidth, UINT *puiHeight)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ TRACE("(%p,%p,%p)\n", This, puiWidth, puiHeight);
+
+ if (!puiWidth || !puiHeight)
+ return E_POINTER;
+
+ *puiWidth = This->decoder_frame.width;
+ *puiHeight = This->decoder_frame.height;
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetPixelFormat(IWICBitmapFrameDecode *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ TRACE("(%p,%p)\n", This, pPixelFormat);
+
+ if (!pPixelFormat)
+ return E_POINTER;
+
+ *pPixelFormat = This->decoder_frame.pixel_format;
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetResolution(IWICBitmapFrameDecode *iface,
+ double *pDpiX, double *pDpiY)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ TRACE("(%p,%p,%p)\n", This, pDpiX, pDpiY);
+
+ if (!pDpiX || !pDpiY)
+ return E_POINTER;
+
+ *pDpiX = This->decoder_frame.dpix;
+ *pDpiY = This->decoder_frame.dpiy;
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_CopyPalette(IWICBitmapFrameDecode *iface,
+ IWICPalette *pIPalette)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ HRESULT hr=S_OK;
+
+ TRACE("(%p,%p)\n", iface, pIPalette);
+
+ if (This->decoder_frame.num_colors)
+ {
+ hr = IWICPalette_InitializeCustom(pIPalette, This->decoder_frame.palette,
This->decoder_frame.num_colors);
+ }
+ else
+ {
+ hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_CopyPixels(IWICBitmapFrameDecode *iface,
+ const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ HRESULT hr;
+ UINT bytesperrow;
+ WICRect rect;
+
+ TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride,
cbBufferSize, pbBuffer);
+
+ if (!pbBuffer)
+ return E_POINTER;
+
+ if (!prc)
+ {
+ rect.X = 0;
+ rect.Y = 0;
+ rect.Width = This->decoder_frame.width;
+ rect.Height = This->decoder_frame.height;
+ prc = ▭
+ }
+ else
+ {
+ if (prc->X < 0 || prc->Y < 0 ||
+ prc->X+prc->Width > This->decoder_frame.width ||
+ prc->Y+prc->Height > This->decoder_frame.height)
+ return E_INVALIDARG;
+ }
+
+ bytesperrow = ((This->decoder_frame.bpp * prc->Width)+7)/8;
+
+ if (cbStride < bytesperrow)
+ return E_INVALIDARG;
+
+ if ((cbStride * (prc->Height-1)) + bytesperrow > cbBufferSize)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&This->parent->lock);
+
+ hr = decoder_copy_pixels(This->parent->decoder, This->frame,
+ prc, cbStride, cbBufferSize, pbBuffer);
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface,
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ IWICComponentFactory* factory;
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
+
+ if (!ppIMetadataQueryReader)
+ return E_INVALIDARG;
+
+ if (!(This->parent->file_info.flags &
WICBitmapDecoderCapabilityCanEnumerateMetadata))
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+
+ hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory,
(void**)&factory);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory,
&This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader);
+ IWICComponentFactory_Release(factory);
+ }
+
+ if (FAILED(hr))
+ *ppIMetadataQueryReader = NULL;
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetColorContexts(IWICBitmapFrameDecode *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ HRESULT hr=S_OK;
+ UINT i;
+ BYTE *profile;
+ DWORD profile_len;
+
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+
+ if (!pcActualCount) return E_INVALIDARG;
+
+ if (This->parent->file_info.flags &
DECODER_FLAGS_UNSUPPORTED_COLOR_CONTEXT)
+ {
+ FIXME("not supported for %s\n",
wine_dbgstr_guid(&This->parent->decoder_info.clsid));
+ *pcActualCount = 0;
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ }
+
+ *pcActualCount = This->decoder_frame.num_color_contexts;
+
+ if (This->decoder_frame.num_color_contexts && cCount &&
ppIColorContexts)
+ {
+ if (cCount >= This->decoder_frame.num_color_contexts)
+ {
+ EnterCriticalSection(&This->parent->lock);
+
+ for (i=0; i<This->decoder_frame.num_color_contexts; i++)
+ {
+ hr = decoder_get_color_context(This->parent->decoder,
This->frame, i,
+ &profile, &profile_len);
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICColorContext_InitializeFromMemory(ppIColorContexts[i],
profile, profile_len);
+
+ free(profile);
+ }
+
+ if (FAILED(hr))
+ break;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetThumbnail(IWICBitmapFrameDecode *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+
+ if (!ppIThumbnail) return E_INVALIDARG;
+
+ *ppIThumbnail = NULL;
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static const IWICBitmapFrameDecodeVtbl CommonDecoderFrameVtbl = {
+ CommonDecoderFrame_QueryInterface,
+ CommonDecoderFrame_AddRef,
+ CommonDecoderFrame_Release,
+ CommonDecoderFrame_GetSize,
+ CommonDecoderFrame_GetPixelFormat,
+ CommonDecoderFrame_GetResolution,
+ CommonDecoderFrame_CopyPalette,
+ CommonDecoderFrame_CopyPixels,
+ CommonDecoderFrame_GetMetadataQueryReader,
+ CommonDecoderFrame_GetColorContexts,
+ CommonDecoderFrame_GetThumbnail
+};
+
+static HRESULT WINAPI CommonDecoderFrame_Block_QueryInterface(IWICMetadataBlockReader
*iface, REFIID iid,
+ void **ppv)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ return
IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid,
ppv);
+}
+
+static ULONG WINAPI CommonDecoderFrame_Block_AddRef(IWICMetadataBlockReader *iface)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
+}
+
+static ULONG WINAPI CommonDecoderFrame_Block_Release(IWICMetadataBlockReader *iface)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
+}
+
+static HRESULT WINAPI CommonDecoderFrame_Block_GetContainerFormat(IWICMetadataBlockReader
*iface,
+ GUID *pguidContainerFormat)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ if (!pguidContainerFormat) return E_INVALIDARG;
+ *pguidContainerFormat = This->parent->decoder_info.block_format;
+ return S_OK;
+}
+
+static HRESULT CommonDecoderFrame_InitializeMetadata(CommonDecoderFrame *This)
+{
+ HRESULT hr=S_OK;
+
+ if (This->metadata_initialized)
+ return S_OK;
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (!This->metadata_initialized)
+ {
+ hr = decoder_get_metadata_blocks(This->parent->decoder, This->frame,
&This->metadata_count, &This->metadata_blocks);
+ if (SUCCEEDED(hr))
+ This->metadata_initialized = TRUE;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_Block_GetCount(IWICMetadataBlockReader *iface,
+ UINT *pcCount)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ HRESULT hr;
+
+ TRACE("%p,%p\n", iface, pcCount);
+
+ if (!pcCount) return E_INVALIDARG;
+
+ hr = CommonDecoderFrame_InitializeMetadata(This);
+ if (SUCCEEDED(hr))
+ *pcCount = This->metadata_count;
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_Block_GetReaderByIndex(IWICMetadataBlockReader
*iface,
+ UINT nIndex, IWICMetadataReader **ppIMetadataReader)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ HRESULT hr;
+ IWICComponentFactory* factory = NULL;
+ IWICStream* stream;
+
+ TRACE("%p,%d,%p\n", iface, nIndex, ppIMetadataReader);
+
+ if (!ppIMetadataReader)
+ return E_INVALIDARG;
+
+ hr = CommonDecoderFrame_InitializeMetadata(This);
+
+ if (SUCCEEDED(hr) && nIndex >= This->metadata_count)
+ hr = E_INVALIDARG;
+
+ if (SUCCEEDED(hr))
+ hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory,
(void**)&factory);
+
+ if (SUCCEEDED(hr))
+ hr = IWICComponentFactory_CreateStream(factory, &stream);
+
+ if (SUCCEEDED(hr))
+ {
+ if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_FULL_STREAM)
+ {
+ LARGE_INTEGER offset;
+ offset.QuadPart = This->metadata_blocks[nIndex].offset;
+
+ hr = IWICStream_InitializeFromIStream(stream, This->parent->stream);
+
+ if (SUCCEEDED(hr))
+ hr = IWICStream_Seek(stream, offset, STREAM_SEEK_SET, NULL);
+ }
+ else
+ {
+ ULARGE_INTEGER offset, length;
+
+ offset.QuadPart = This->metadata_blocks[nIndex].offset;
+ length.QuadPart = This->metadata_blocks[nIndex].length;
+
+ hr = IWICStream_InitializeFromIStreamRegion(stream,
This->parent->stream,
+ offset, length);
+ }
+
+ if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_READER_CLSID)
+ {
+ IWICMetadataReader *reader;
+ IWICPersistStream *persist;
+ if (SUCCEEDED(hr))
+ {
+ hr =
create_instance(&This->metadata_blocks[nIndex].reader_clsid,
+ &IID_IWICMetadataReader, (void**)&reader);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICMetadataReader_QueryInterface(reader,
&IID_IWICPersistStream, (void**)&persist);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICPersistStream_LoadEx(persist, (IStream*)stream, NULL,
+ This->metadata_blocks[nIndex].options &
DECODER_BLOCK_OPTION_MASK);
+
+ IWICPersistStream_Release(persist);
+ }
+
+ if (SUCCEEDED(hr))
+ *ppIMetadataReader = reader;
+ else
+ IWICMetadataReader_Release(reader);
+ }
+ }
+ else
+ {
+ hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
+ &This->parent->decoder_info.block_format, NULL,
+ This->metadata_blocks[nIndex].options &
DECODER_BLOCK_OPTION_MASK,
+ (IStream*)stream, ppIMetadataReader);
+ }
+
+ IWICStream_Release(stream);
+ }
+
+ if (factory) IWICComponentFactory_Release(factory);
+
+ if (FAILED(hr))
+ *ppIMetadataReader = NULL;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_Block_GetEnumerator(IWICMetadataBlockReader
*iface,
+ IEnumUnknown **ppIEnumMetadata)
+{
+ FIXME("%p,%p\n", iface, ppIEnumMetadata);
+ return E_NOTIMPL;
+}
+
+static const IWICMetadataBlockReaderVtbl CommonDecoderFrame_BlockVtbl = {
+ CommonDecoderFrame_Block_QueryInterface,
+ CommonDecoderFrame_Block_AddRef,
+ CommonDecoderFrame_Block_Release,
+ CommonDecoderFrame_Block_GetContainerFormat,
+ CommonDecoderFrame_Block_GetCount,
+ CommonDecoderFrame_Block_GetReaderByIndex,
+ CommonDecoderFrame_Block_GetEnumerator,
+};
+
+static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface,
+ UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ HRESULT hr=S_OK;
+ CommonDecoderFrame *result;
+
+ TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
+
+ if (!ppIBitmapFrame)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->stream || index >= This->file_info.frame_count)
+ hr = WINCODEC_ERR_FRAMEMISSING;
+
+ if (SUCCEEDED(hr))
+ {
+ result = malloc(sizeof(*result));
+ if (!result)
+ hr = E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ result->IWICBitmapFrameDecode_iface.lpVtbl = &CommonDecoderFrameVtbl;
+ result->IWICMetadataBlockReader_iface.lpVtbl =
&CommonDecoderFrame_BlockVtbl;
+ result->ref = 1;
+ result->parent = This;
+ result->frame = index;
+ result->metadata_initialized = FALSE;
+ result->metadata_count = 0;
+ result->metadata_blocks = NULL;
+
+ hr = decoder_get_frame_info(This->decoder, index,
&result->decoder_frame);
+
+ if (SUCCEEDED(hr) && This->cache_options ==
WICDecodeMetadataCacheOnLoad)
+ hr = CommonDecoderFrame_InitializeMetadata(result);
+
+ if (FAILED(hr))
+ free(result);
+ }
+
+ LeaveCriticalSection(&This->lock);
+
+ if (SUCCEEDED(hr))
+ {
+ TRACE("-> %ux%u, %u-bit pixelformat=%s res=%f,%f colors=%lu
contexts=%lu\n",
+ result->decoder_frame.width, result->decoder_frame.height,
+ result->decoder_frame.bpp,
wine_dbgstr_guid(&result->decoder_frame.pixel_format),
+ result->decoder_frame.dpix, result->decoder_frame.dpiy,
+ result->decoder_frame.num_colors,
result->decoder_frame.num_color_contexts);
+ IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
+ *ppIBitmapFrame = &result->IWICBitmapFrameDecode_iface;
+ }
+ else
+ {
+ *ppIBitmapFrame = NULL;
+ }
+
+ return hr;
+}
+
+HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
+ const struct decoder_info *decoder_info, REFIID iid, void** ppv)
+{
+ CommonDecoder *This;
+ HRESULT hr;
+
+ TRACE("(%s,%s,%p)\n", debugstr_guid(&decoder_info->clsid),
debugstr_guid(iid), ppv);
+
+ This = malloc(sizeof(*This));
+ if (!This)
+ {
+ decoder_destroy(decoder);
+ return E_OUTOFMEMORY;
+ }
+
+ This->IWICBitmapDecoder_iface.lpVtbl = &CommonDecoder_Vtbl;
+ This->ref = 1;
+ This->stream = NULL;
+ This->decoder = decoder;
+ This->decoder_info = *decoder_info;
+#ifdef __REACTOS__
+ InitializeCriticalSection(&This->lock);
+#else
+ InitializeCriticalSectionEx(&This->lock, 0,
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
+#endif
+ This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ":
CommonDecoder.lock");
+
+ hr = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid,
ppv);
+ IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
+
+ return hr;
+}
diff --git a/dll/win32/windowscodecs/encoder.c b/dll/win32/windowscodecs/encoder.c
new file mode 100644
index 00000000000..b2be1f12e1c
--- /dev/null
+++ b/dll/win32/windowscodecs/encoder.c
@@ -0,0 +1,903 @@
+/*
+ * Copyright 2020 Esme Povirk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+static const PROPBAG2 encoder_option_properties[ENCODER_OPTION_END] = {
+ { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)L"InterlaceOption" },
+ { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)L"FilterOption" },
+ { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)L"TiffCompressionMethod"
},
+ { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)L"CompressionQuality" },
+ { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)L"ImageQuality"
},
+ { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)L"BitmapTransform"
},
+ { PROPBAG2_TYPE_DATA, VT_I4 | VT_ARRAY, 0, 0, (LPOLESTR)L"Luminance" },
+ { PROPBAG2_TYPE_DATA, VT_I4 | VT_ARRAY, 0, 0, (LPOLESTR)L"Chrominance" },
+ { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0,
(LPOLESTR)L"JpegYCrCbSubsampling" },
+ { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)L"SuppressApp0" }
+};
+
+typedef struct CommonEncoder {
+ IWICBitmapEncoder IWICBitmapEncoder_iface;
+ LONG ref;
+ CRITICAL_SECTION lock; /* must be held when stream or encoder is accessed */
+ IStream *stream;
+ struct encoder *encoder;
+ struct encoder_info encoder_info;
+ UINT frame_count;
+ BOOL uncommitted_frame;
+ BOOL committed;
+} CommonEncoder;
+
+typedef struct CommonEncoderFrame {
+ IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
+ IWICMetadataBlockWriter IWICMetadataBlockWriter_iface;
+ LONG ref;
+ CommonEncoder *parent;
+ struct encoder_frame encoder_frame;
+ BOOL initialized;
+ BOOL frame_created;
+ UINT lines_written;
+ BOOL committed;
+} CommonEncoderFrame;
+
+static inline CommonEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
+{
+ return CONTAINING_RECORD(iface, CommonEncoder, IWICBitmapEncoder_iface);
+}
+
+static inline CommonEncoderFrame *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface)
+{
+ return CONTAINING_RECORD(iface, CommonEncoderFrame, IWICBitmapFrameEncode_iface);
+}
+
+static inline CommonEncoderFrame
*impl_from_IWICMetadataBlockWriter(IWICMetadataBlockWriter *iface)
+{
+ return CONTAINING_RECORD(iface, CommonEncoderFrame, IWICMetadataBlockWriter_iface);
+}
+
+static HRESULT WINAPI CommonEncoderFrame_QueryInterface(IWICBitmapFrameEncode *iface,
REFIID iid,
+ void **ppv)
+{
+ CommonEncoderFrame *object = impl_from_IWICBitmapFrameEncode(iface);
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
+ {
+ *ppv = &object->IWICBitmapFrameEncode_iface;
+ }
+ else if (object->parent->encoder_info.flags &
ENCODER_FLAGS_SUPPORTS_METADATA
+ && IsEqualIID(&IID_IWICMetadataBlockWriter, iid))
+ {
+ *ppv = &object->IWICMetadataBlockWriter_iface;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI CommonEncoderFrame_AddRef(IWICBitmapFrameEncode *iface)
+{
+ CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI CommonEncoderFrame_Release(IWICBitmapFrameEncode *iface)
+{
+ CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%lu\n", iface, ref);
+
+ if (ref == 0)
+ {
+ IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface);
+ free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI CommonEncoderFrame_Initialize(IWICBitmapFrameEncode *iface,
+ IPropertyBag2 *pIEncoderOptions)
+{
+ CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr=S_OK;
+ struct encoder_frame options = {{0}};
+ PROPBAG2 opts[7]= {{0}};
+ VARIANT opt_values[7];
+ HRESULT opt_hres[7];
+ DWORD num_opts, i;
+
+ TRACE("(%p,%p)\n", iface, pIEncoderOptions);
+
+ if (pIEncoderOptions)
+ {
+ for (i=0; This->parent->encoder_info.encoder_options[i] !=
ENCODER_OPTION_END; i++)
+ opts[i] =
encoder_option_properties[This->parent->encoder_info.encoder_options[i]];
+ num_opts = i;
+
+ hr = IPropertyBag2_Read(pIEncoderOptions, num_opts, opts, NULL, opt_values,
opt_hres);
+
+ if (FAILED(hr))
+ return hr;
+
+ for (i=0; This->parent->encoder_info.encoder_options[i] !=
ENCODER_OPTION_END; i++)
+ {
+ VARIANT *val = &opt_values[i];
+
+ switch (This->parent->encoder_info.encoder_options[i])
+ {
+ case ENCODER_OPTION_INTERLACE:
+ if (V_VT(val) == VT_EMPTY)
+ options.interlace = FALSE;
+ else
+ options.interlace = (V_BOOL(val) != 0);
+ break;
+ case ENCODER_OPTION_FILTER:
+ options.filter = V_UI1(val);
+ if (options.filter > WICPngFilterAdaptive)
+ {
+ WARN("Unrecognized filter option value %lu.\n",
options.filter);
+ options.filter = WICPngFilterUnspecified;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ options.interlace = FALSE;
+ options.filter = WICPngFilterUnspecified;
+ }
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (This->initialized)
+ hr = WINCODEC_ERR_WRONGSTATE;
+ else
+ {
+ This->encoder_frame = options;
+ This->initialized = TRUE;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonEncoderFrame_SetSize(IWICBitmapFrameEncode *iface,
+ UINT uiWidth, UINT uiHeight)
+{
+ CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (This->parent->encoder_info.flags & ENCODER_FLAGS_ICNS_SIZE)
+ {
+ if (uiWidth != uiHeight)
+ {
+ WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth,
uiHeight);
+ hr = E_INVALIDARG;
+ goto end;
+ }
+
+ switch (uiWidth)
+ {
+ case 16:
+ case 32:
+ case 48:
+ case 128:
+ case 256:
+ case 512:
+ break;
+ default:
+ WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth,
uiHeight);
+ hr = E_INVALIDARG;
+ goto end;
+ }
+ }
+
+ if (!This->initialized || This->frame_created)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ }
+ else
+ {
+ This->encoder_frame.width = uiWidth;
+ This->encoder_frame.height = uiHeight;
+ hr = S_OK;
+ }
+
+end:
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonEncoderFrame_SetResolution(IWICBitmapFrameEncode *iface,
+ double dpiX, double dpiY)
+{
+ CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (!This->initialized || This->frame_created)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ }
+ else
+ {
+ This->encoder_frame.dpix = dpiX;
+ This->encoder_frame.dpiy = dpiY;
+ hr = S_OK;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonEncoderFrame_SetPixelFormat(IWICBitmapFrameEncode *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+ GUID pixel_format;
+ DWORD bpp;
+ BOOL indexed;
+
+ TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (!This->initialized || This->frame_created)
+ {
+ hr = WINCODEC_ERR_WRONGSTATE;
+ }
+ else
+ {
+ pixel_format = *pPixelFormat;
+ hr = encoder_get_supported_format(This->parent->encoder, &pixel_format,
&bpp, &indexed);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ TRACE("<-- %s bpp=%li indexed=%i\n",
wine_dbgstr_guid(&pixel_format), bpp, indexed);
+ *pPixelFormat = pixel_format;
... 33002 lines suppressed ...