diff --git a/reactos/dll/win32/windowscodecs/CMakeLists.txt b/reactos/dll/win32/windowscodecs/CMakeLists.txt index 52737379e08..88f6e7e7225 100644 --- a/reactos/dll/win32/windowscodecs/CMakeLists.txt +++ b/reactos/dll/win32/windowscodecs/CMakeLists.txt @@ -23,7 +23,6 @@ spec2def(windowscodecs.dll windowscodecs.spec ADD_IMPORTLIB) add_rpcproxy_files(windowscodecs_wincodec.idl) list(APPEND SOURCE - bitmap.c bmpdecode.c bmpencode.c clipper.c @@ -40,6 +39,7 @@ list(APPEND SOURCE jpegformat.c main.c metadatahandler.c + metadataquery.c palette.c pngformat.c propertybag.c @@ -52,8 +52,17 @@ list(APPEND SOURCE ungif.c wincodecs_private.h) -add_library(windowscodecs SHARED - ${SOURCE} +if(MSVC) + if(ARCH STREQUAL "i386") + list(APPEND SOURCE msvc-thiscall.c) + endif() + set_source_files_properties(bitmap.c PROPERTIES COMPILE_FLAGS "/FImsvc.h") + list(APPEND ADDITIONAL_SOURCE bitmap.c) +else() + list(APPEND SOURCE bitmap.c) +endif() + +list(APPEND ADDITIONAL_SOURCE guid.c version.rc ${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c @@ -61,6 +70,10 @@ add_library(windowscodecs SHARED ${CMAKE_CURRENT_BINARY_DIR}/windowscodecs.def ${CMAKE_CURRENT_BINARY_DIR}/windowscodecs_wincodec_p.c) +add_library(windowscodecs SHARED + ${SOURCE} + ${ADDITIONAL_SOURCE}) + 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 msvcrt kernel32 ntdll) diff --git a/reactos/dll/win32/windowscodecs/bitmap.c b/reactos/dll/win32/windowscodecs/bitmap.c index dfd7dda89fa..843c7e73b34 100644 --- a/reactos/dll/win32/windowscodecs/bitmap.c +++ b/reactos/dll/win32/windowscodecs/bitmap.c @@ -31,6 +31,7 @@ typedef struct BitmapImpl { int palette_set; LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */ BYTE *data; + BOOL is_section; /* TRUE if data is a section created by an application */ UINT width, height; UINT stride; UINT bpp; @@ -121,6 +122,7 @@ static HRESULT WINAPI BitmapLockImpl_QueryInterface(IWICBitmapLock *iface, REFII } else { + FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -234,12 +236,14 @@ static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid, { *ppv = &This->IWICBitmap_iface; } - else if (IsEqualIID(&IID_IMILBitmapSource, iid)) + else if (IsEqualIID(&IID_IMILBitmap, iid) || + IsEqualIID(&IID_IMILBitmapSource, iid)) { *ppv = &This->IMILBitmapSource_iface; } else { + FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -270,7 +274,10 @@ static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface) if (This->palette) IWICPalette_Release(This->palette); This->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->cs); - HeapFree(GetProcessHeap(), 0, This->data); + if (This->is_section) + UnmapViewOfFile(This->data); + else + HeapFree(GetProcessHeap(), 0, This->data); HeapFree(GetProcessHeap(), 0, This); } @@ -465,13 +472,22 @@ static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmapSource *iface, REF if (!ppv) return E_INVALIDARG; if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IMILBitmap, iid) || IsEqualIID(&IID_IMILBitmapSource, iid)) { IUnknown_AddRef(&This->IMILBitmapSource_iface); *ppv = &This->IMILBitmapSource_iface; return S_OK; } + else if (IsEqualIID(&IID_IWICBitmap, iid) || + IsEqualIID(&IID_IWICBitmapSource, iid)) + { + IUnknown_AddRef(&This->IWICBitmap_iface); + *ppv = &This->IWICBitmap_iface; + return S_OK; + } + FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -492,6 +508,7 @@ static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmapSource *iface, UINT *width, UINT *height) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); + TRACE("(%p,%p,%p)\n", iface, width, height); return IWICBitmap_GetSize(&This->IWICBitmap_iface, width, height); } @@ -545,6 +562,7 @@ static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmapSource *iface, } } + TRACE("=> %u\n", *format); return S_OK; } @@ -552,6 +570,7 @@ static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmapSource *iface, double *dpix, double *dpiy) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); + TRACE("(%p,%p,%p)\n", iface, dpix, dpiy); return IWICBitmap_GetResolution(&This->IWICBitmap_iface, dpix, dpiy); } @@ -559,6 +578,7 @@ static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmapSource *iface, IWICPalette *palette) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); + TRACE("(%p,%p)\n", iface, palette); return IWICBitmap_CopyPalette(&This->IWICBitmap_iface, palette); } @@ -566,10 +586,11 @@ static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmapSource *iface, const WICRect *rc, UINT stride, UINT size, BYTE *buffer) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); + TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer); return IWICBitmap_CopyPixels(&This->IWICBitmap_iface, rc, stride, size, buffer); } -static HRESULT WINAPI IMILBitmapImpl_UnknownMethod1(IMILBitmapSource *iface, void **ppv) +static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmapSource *iface, void **ppv) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); @@ -577,12 +598,46 @@ static HRESULT WINAPI IMILBitmapImpl_UnknownMethod1(IMILBitmapSource *iface, voi if (!ppv) return E_INVALIDARG; - IUnknown_AddRef(&This->IMILUnknown1_iface); + /* reference count is not incremented here */ *ppv = &This->IMILUnknown1_iface; return S_OK; } +static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmapSource *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock) +{ + BitmapImpl *This = impl_from_IMILBitmapSource(iface); + TRACE("(%p,%p,%08x,%p)\n", iface, rc, flags, lock); + return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock); +} + +static HRESULT WINAPI IMILBitmapImpl_Unlock(IMILBitmapSource *iface, IWICBitmapLock *lock) +{ + TRACE("(%p,%p)\n", iface, lock); + IWICBitmapLock_Release(lock); + return S_OK; +} + +static HRESULT WINAPI IMILBitmapImpl_SetPalette(IMILBitmapSource *iface, IWICPalette *palette) +{ + BitmapImpl *This = impl_from_IMILBitmapSource(iface); + TRACE("(%p,%p)\n", iface, palette); + return IWICBitmap_SetPalette(&This->IWICBitmap_iface, palette); +} + +static HRESULT WINAPI IMILBitmapImpl_SetResolution(IMILBitmapSource *iface, double dpix, double dpiy) +{ + BitmapImpl *This = impl_from_IMILBitmapSource(iface); + TRACE("(%p,%f,%f)\n", iface, dpix, dpiy); + return IWICBitmap_SetResolution(&This->IWICBitmap_iface, dpix, dpiy); +} + +static HRESULT WINAPI IMILBitmapImpl_AddDirtyRect(IMILBitmapSource *iface, const WICRect *rc) +{ + FIXME("(%p,%p): stub\n", iface, rc); + return E_NOTIMPL; +} + static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl = { IMILBitmapImpl_QueryInterface, @@ -593,26 +648,20 @@ static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl = IMILBitmapImpl_GetResolution, IMILBitmapImpl_CopyPalette, IMILBitmapImpl_CopyPixels, - IMILBitmapImpl_UnknownMethod1, + IMILBitmapImpl_unknown1, + IMILBitmapImpl_Lock, + IMILBitmapImpl_Unlock, + IMILBitmapImpl_SetPalette, + IMILBitmapImpl_SetResolution, + IMILBitmapImpl_AddDirtyRect }; static HRESULT WINAPI IMILUnknown1Impl_QueryInterface(IMILUnknown1 *iface, REFIID iid, void **ppv) { - BitmapImpl *This = impl_from_IMILUnknown1(iface); - - TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); - - if (!ppv) return E_INVALIDARG; - - if (IsEqualIID(&IID_IUnknown, iid)) - { - IUnknown_AddRef(&This->IMILUnknown1_iface); - *ppv = iface; - return S_OK; - } - - return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv); + FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv); + *ppv = NULL; + return E_NOINTERFACE; } static ULONG WINAPI IMILUnknown1Impl_AddRef(IMILUnknown1 *iface) @@ -627,47 +676,108 @@ static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface) return IWICBitmap_Release(&This->IWICBitmap_iface); } +DECLSPEC_HIDDEN void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg) +{ + FIXME("(%p,%p): stub\n", iface, arg); +} + +static HRESULT WINAPI IMILUnknown1Impl_unknown2(IMILUnknown1 *iface, void *arg1, void *arg2) +{ + FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); + return E_NOTIMPL; +} + +DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg) +{ + FIXME("(%p,%p): stub\n", iface, arg); + return E_NOTIMPL; +} + +static HRESULT WINAPI IMILUnknown1Impl_unknown4(IMILUnknown1 *iface, void *arg) +{ + FIXME("(%p,%p): stub\n", iface, arg); + return E_NOTIMPL; +} + +static HRESULT WINAPI IMILUnknown1Impl_unknown5(IMILUnknown1 *iface, void *arg) +{ + FIXME("(%p,%p): stub\n", iface, arg); + return E_NOTIMPL; +} + +static HRESULT WINAPI IMILUnknown1Impl_unknown6(IMILUnknown1 *iface, DWORD64 arg) +{ + FIXME("(%p,%s): stub\n", iface, wine_dbgstr_longlong(arg)); + return E_NOTIMPL; +} + +static HRESULT WINAPI IMILUnknown1Impl_unknown7(IMILUnknown1 *iface, void *arg) +{ + FIXME("(%p,%p): stub\n", iface, arg); + return E_NOTIMPL; +} + +DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface) +{ + FIXME("(%p): stub\n", iface); + return E_NOTIMPL; +} + +DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown1, 8) +DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown3, 8) +DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown8, 4) + static const IMILUnknown1Vtbl IMILUnknown1Impl_Vtbl = { IMILUnknown1Impl_QueryInterface, IMILUnknown1Impl_AddRef, IMILUnknown1Impl_Release, + THISCALL(IMILUnknown1Impl_unknown1), + IMILUnknown1Impl_unknown2, + THISCALL(IMILUnknown1Impl_unknown3), + IMILUnknown1Impl_unknown4, + IMILUnknown1Impl_unknown5, + IMILUnknown1Impl_unknown6, + IMILUnknown1Impl_unknown7, + THISCALL(IMILUnknown1Impl_unknown8) }; static HRESULT WINAPI IMILUnknown2Impl_QueryInterface(IMILUnknown2 *iface, REFIID iid, void **ppv) { - BitmapImpl *This = impl_from_IMILUnknown2(iface); - - TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); - - if (!ppv) return E_INVALIDARG; - - if (IsEqualIID(&IID_IUnknown, iid)) - { - IUnknown_AddRef(&This->IMILUnknown2_iface); - *ppv = iface; - return S_OK; - } - - return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv); + FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv); + *ppv = NULL; + return E_NOINTERFACE; } static ULONG WINAPI IMILUnknown2Impl_AddRef(IMILUnknown2 *iface) { - BitmapImpl *This = impl_from_IMILUnknown2(iface); - return IWICBitmap_AddRef(&This->IWICBitmap_iface); + FIXME("(%p): stub\n", iface); + return 0; } static ULONG WINAPI IMILUnknown2Impl_Release(IMILUnknown2 *iface) { - BitmapImpl *This = impl_from_IMILUnknown2(iface); - return IWICBitmap_Release(&This->IWICBitmap_iface); + FIXME("(%p): stub\n", iface); + return 0; } -static HRESULT WINAPI IMILUnknown2Impl_UnknownMethod1(IMILUnknown2 *iface, void *arg1, void *arg2) +static HRESULT WINAPI IMILUnknown2Impl_unknown1(IMILUnknown2 *iface, void *arg1, void **arg2) { FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); + if (arg2) *arg2 = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI IMILUnknown2Impl_unknown2(IMILUnknown2 *iface, void *arg1, void *arg2) +{ + FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); + return E_NOTIMPL; +} + +static HRESULT WINAPI IMILUnknown2Impl_unknown3(IMILUnknown2 *iface, void *arg1) +{ + FIXME("(%p,%p): stub\n", iface, arg1); return E_NOTIMPL; } @@ -676,17 +786,18 @@ static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl = IMILUnknown2Impl_QueryInterface, IMILUnknown2Impl_AddRef, IMILUnknown2Impl_Release, - IMILUnknown2Impl_UnknownMethod1, + IMILUnknown2Impl_unknown1, + IMILUnknown2Impl_unknown2, + IMILUnknown2Impl_unknown3 }; HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, - UINT stride, UINT datasize, BYTE *bits, + UINT stride, UINT datasize, BYTE *data, REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option, IWICBitmap **ppIBitmap) { HRESULT hr; BitmapImpl *This; - BYTE *data; UINT bpp; hr = get_pixelformat_bpp(pixelFormat, &bpp); @@ -699,14 +810,20 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG; This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl)); - data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize); - if (!This || !data) + if (!This) return E_OUTOFMEMORY; + + if (!data) { - HeapFree(GetProcessHeap(), 0, This); - HeapFree(GetProcessHeap(), 0, data); - return E_OUTOFMEMORY; + data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize); + if (!data) + { + HeapFree(GetProcessHeap(), 0, This); + return E_OUTOFMEMORY; + } + This->is_section = FALSE; } - if (bits) memcpy(data, bits, datasize); + else + This->is_section = TRUE; This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl; This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl; diff --git a/reactos/dll/win32/windowscodecs/converter.c b/reactos/dll/win32/windowscodecs/converter.c index 1dcff39fc38..cc45eb6130f 100644 --- a/reactos/dll/win32/windowscodecs/converter.c +++ b/reactos/dll/win32/windowscodecs/converter.c @@ -1,5 +1,6 @@ /* * Copyright 2009 Vincent Povirk + * Copyright 2016 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,6 +19,8 @@ #include "wincodecs_private.h" +#include + struct FormatConverter; enum pixelformat { @@ -35,6 +38,7 @@ enum pixelformat { format_16bppBGRA5551, format_24bppBGR, format_24bppRGB, + format_32bppGrayFloat, format_32bppBGR, format_32bppBGRA, format_32bppPBGRA, @@ -63,6 +67,55 @@ typedef struct FormatConverter { CRITICAL_SECTION lock; /* must be held when initialized */ } FormatConverter; +/* https://www.w3.org/Graphics/Color/srgb */ +static inline float from_sRGB_component(float f) +{ + if (f <= 0.04045f) return f / 12.92f; + return powf((f + 0.055f) / 1.055f, 2.4f); +} + +static inline float to_sRGB_component(float f) +{ + if (f <= 0.0031308f) return 12.92f * f; + return 1.055f * powf(f, 1.0f/2.4f) - 0.055f; +} + +#if 0 /* FIXME: enable once needed */ +static void from_sRGB(BYTE *bgr) +{ + float r, g, b; + + r = bgr[2] / 255.0f; + g = bgr[1] / 255.0f; + b = bgr[0] / 255.0f; + + r = from_sRGB_component(r); + g = from_sRGB_component(g); + g = from_sRGB_component(b); + + bgr[2] = (BYTE)(r * 255.0f); + bgr[1] = (BYTE)(g * 255.0f); + bgr[0] = (BYTE)(b * 255.0f); +} + +static void to_sRGB(BYTE *bgr) +{ + float r, g, b; + + r = bgr[2] / 255.0f; + g = bgr[1] / 255.0f; + b = bgr[0] / 255.0f; + + r = to_sRGB_component(r); + g = to_sRGB_component(g); + g = to_sRGB_component(b); + + bgr[2] = (BYTE)(r * 255.0f); + bgr[1] = (BYTE)(g * 255.0f); + bgr[0] = (BYTE)(b * 255.0f); +} +#endif + static inline FormatConverter *impl_from_IWICFormatConverter(IWICFormatConverter *iface) { return CONTAINING_RECORD(iface, FormatConverter, IWICFormatConverter_iface); @@ -903,6 +956,49 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec return res; } return S_OK; + + case format_32bppGrayFloat: + if (prc) + { + BYTE *srcdata; + UINT srcstride, srcdatasize; + + srcstride = 4 * prc->Width; + srcdatasize = srcstride * prc->Height; + + srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); + + if (SUCCEEDED(hr)) + { + INT x, y; + BYTE *src = srcdata, *dst = pbBuffer; + + for (y = 0; y < prc->Height; y++) + { + float *gray_float = (float *)src; + BYTE *bgr = dst; + + for (x = 0; x < prc->Width; x++) + { + BYTE gray = (BYTE)floorf(to_sRGB_component(gray_float[x]) * 255.0f + 0.51f); + *bgr++ = gray; + *bgr++ = gray; + *bgr++ = gray; + } + src += srcstride; + dst += cbStride; + } + } + + HeapFree(GetProcessHeap(), 0, srcdata); + + return hr; + } + return S_OK; + default: FIXME("Unimplemented conversion path!\n"); return WINCODEC_ERR_UNSUPPORTEDOPERATION; @@ -979,6 +1075,102 @@ static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This, const WICRec } } +static HRESULT copypixels_to_32bppGrayFloat(struct FormatConverter *This, const WICRect *prc, + UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) +{ + HRESULT hr; + + switch (source_format) + { + case format_32bppBGR: + case format_32bppBGRA: + case format_32bppPBGRA: + case format_32bppGrayFloat: + if (prc) + { + hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + break; + } + return S_OK; + + default: + hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); + break; + } + + if (SUCCEEDED(hr) && prc && source_format != format_32bppGrayFloat) + { + INT x, y; + BYTE *p = pbBuffer; + + for (y = 0; y < prc->Height; y++) + { + BYTE *bgr = p; + for (x = 0; x < prc->Width; x++) + { + float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f; + *(float *)bgr = gray; + bgr += 4; + } + p += cbStride; + } + } + return hr; +} + +static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRect *prc, + UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) +{ + HRESULT hr; + BYTE *srcdata; + UINT srcstride, srcdatasize; + + if (source_format == format_8bppGray) + { + if (prc) + return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + + return S_OK; + } + + srcstride = 3 * prc->Width; + srcdatasize = srcstride * prc->Height; + + srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format); + if (SUCCEEDED(hr) && prc) + { + INT x, y; + BYTE *src = srcdata, *dst = pbBuffer; + + for (y = 0; y < prc->Height; y++) + { + BYTE *bgr = src; + + for (x = 0; x < prc->Width; x++) + { + float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f; + + /* conversion from 32bppGrayFloat to 24bppBGR has already applied sRGB gamma */ + if (source_format == format_32bppGrayFloat) + gray *= 255.0f; + else + gray = to_sRGB_component(gray) * 255.0f; + + dst[x] = (BYTE)floorf(gray + 0.51f); + bgr += 3; + } + src += srcstride; + dst += cbStride; + } + } + + HeapFree(GetProcessHeap(), 0, srcdata); + return hr; +} + static const struct pixelformatinfo supported_formats[] = { {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL}, {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL}, @@ -987,13 +1179,14 @@ static const struct pixelformatinfo supported_formats[] = { {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL}, {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL}, {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL}, - {format_8bppGray, &GUID_WICPixelFormat8bppGray, NULL}, + {format_8bppGray, &GUID_WICPixelFormat8bppGray, copypixels_to_8bppGray}, {format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL}, {format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL}, {format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL}, {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, NULL}, {format_24bppBGR, &GUID_WICPixelFormat24bppBGR, copypixels_to_24bppBGR}, {format_24bppRGB, &GUID_WICPixelFormat24bppRGB, copypixels_to_24bppRGB}, + {format_32bppGrayFloat, &GUID_WICPixelFormat32bppGrayFloat, copypixels_to_32bppGrayFloat}, {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR}, {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA}, {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA}, diff --git a/reactos/dll/win32/windowscodecs/gifformat.c b/reactos/dll/win32/windowscodecs/gifformat.c index 03385cf417c..18bc99cabd8 100644 --- a/reactos/dll/win32/windowscodecs/gifformat.c +++ b/reactos/dll/win32/windowscodecs/gifformat.c @@ -236,7 +236,7 @@ static HRESULT load_GCE_metadata(IStream *stream, const GUID *vendor, DWORD opti MetadataItem **items, DWORD *count) { #include "pshpack1.h" - struct graphic_control_extenstion + struct graphic_control_extension { BYTE packed; /* reservred: 3; @@ -314,7 +314,7 @@ static HRESULT load_APE_metadata(IStream *stream, const GUID *vendor, DWORD opti MetadataItem **items, DWORD *count) { #include "pshpack1.h" - struct application_extenstion + struct application_extension { BYTE extension_introducer; BYTE extension_label; @@ -421,7 +421,7 @@ static HRESULT load_GifComment_metadata(IStream *stream, const GUID *vendor, DWO MetadataItem **items, DWORD *count) { #include "pshpack1.h" - struct gif_extenstion + struct gif_extension { BYTE extension_introducer; BYTE extension_label; @@ -801,8 +801,14 @@ static HRESULT WINAPI GifFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, static HRESULT WINAPI GifFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, IWICMetadataQueryReader **ppIMetadataQueryReader) { + GifFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader); - return WINCODEC_ERR_UNSUPPORTEDOPERATION; + + if (!ppIMetadataQueryReader) + return E_INVALIDARG; + + return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader); } static HRESULT WINAPI GifFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface, diff --git a/reactos/dll/win32/windowscodecs/guid.c b/reactos/dll/win32/windowscodecs/guid.c index b3e54f12e44..e6774d20af2 100644 --- a/reactos/dll/win32/windowscodecs/guid.c +++ b/reactos/dll/win32/windowscodecs/guid.c @@ -16,6 +16,11 @@ DEFINE_GUID(CLSID_WineTgaDecoder, 0xb11fc79a,0x67cc,0x43e6,0xa9,0xce,0xe3,0xd5,0 DEFINE_GUID(CLSID_WICIcnsEncoder, 0x312fb6f1,0xb767,0x409d,0x8a,0x6d,0x0f,0xc1,0x54,0xd4,0xf0,0x5c); DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47,0x3f,0xc1,0x7c,0xd3,0x22); DEFINE_GUID(GUID_VendorWine, 0xddf46da1,0x7dc1,0x404e,0x98,0xf2,0xef,0xa4,0x8d,0xfc,0x95,0x0a); -DEFINE_GUID(IID_IMILBitmapSource,0x7543696a,0xbc8d,0x46b0,0x5f,0x81,0x8d,0x95,0x72,0x89,0x72,0xbe); +DEFINE_GUID(IID_IMILBitmap, 0xb1784d3f,0x8115,0x4763,0x13,0xaa,0x32,0xed,0xdb,0x68,0x29,0x4a); +DEFINE_GUID(IID_IMILBitmapSource, 0x7543696a,0xbc8d,0x46b0,0x5f,0x81,0x8d,0x95,0x72,0x89,0x72,0xbe); +DEFINE_GUID(IID_IMILBitmapLock, 0xa67b2b53,0x8fa1,0x4155,0x8f,0x64,0x0c,0x24,0x7a,0x8f,0x84,0xcd); +DEFINE_GUID(IID_IMILBitmapScaler, 0xa767b0f0,0x1c8c,0x4aef,0x56,0x8f,0xad,0xf9,0x6d,0xcf,0xd5,0xcb); +DEFINE_GUID(IID_IMILFormatConverter, 0x7e2a746f,0x25c5,0x4851,0xb3,0xaf,0x44,0x3b,0x79,0x63,0x9e,0xc0); +DEFINE_GUID(IID_IMILPalette, 0xca8e206f,0xf22c,0x4af7,0x6f,0xba,0x7b,0xed,0x5e,0xb1,0xc9,0x2f); /* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */ diff --git a/reactos/dll/win32/windowscodecs/imgfactory.c b/reactos/dll/win32/windowscodecs/imgfactory.c index 1b36d29eecf..8692b7720db 100644 --- a/reactos/dll/win32/windowscodecs/imgfactory.c +++ b/reactos/dll/win32/windowscodecs/imgfactory.c @@ -579,12 +579,36 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromMemory(IWICComponentFacto UINT width, UINT height, REFWICPixelFormatGUID format, UINT stride, UINT size, BYTE *buffer, IWICBitmap **bitmap) { + HRESULT hr; + TRACE("(%p,%u,%u,%s,%u,%u,%p,%p\n", iface, width, height, debugstr_guid(format), stride, size, buffer, bitmap); if (!stride || !size || !buffer || !bitmap) return E_INVALIDARG; - return BitmapImpl_Create(width, height, stride, size, buffer, format, WICBitmapCacheOnLoad, bitmap); + hr = BitmapImpl_Create(width, height, stride, size, NULL, format, WICBitmapCacheOnLoad, bitmap); + if (SUCCEEDED(hr)) + { + IWICBitmapLock *lock; + + hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); + if (SUCCEEDED(hr)) + { + UINT buffersize; + BYTE *data; + + IWICBitmapLock_GetDataPointer(lock, &buffersize, &data); + memcpy(data, buffer, buffersize); + + IWICBitmapLock_Release(lock); + } + else + { + IWICBitmap_Release(*bitmap); + *bitmap = NULL; + } + } + return hr; } static BOOL get_16bpp_format(HBITMAP hbm, WICPixelFormatGUID *format) @@ -1080,8 +1104,12 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICCompon static HRESULT WINAPI ComponentFactory_CreateQueryReaderFromBlockReader(IWICComponentFactory *iface, IWICMetadataBlockReader *block_reader, IWICMetadataQueryReader **query_reader) { - FIXME("%p,%p,%p: stub\n", iface, block_reader, query_reader); - return E_NOTIMPL; + TRACE("%p,%p,%p\n", iface, block_reader, query_reader); + + if (!block_reader || !query_reader) + return E_INVALIDARG; + + return MetadataQueryReader_CreateInstance(block_reader, query_reader); } static HRESULT WINAPI ComponentFactory_CreateQueryWriterFromBlockWriter(IWICComponentFactory *iface, @@ -1156,3 +1184,50 @@ HRESULT ComponentFactory_CreateInstance(REFIID iid, void** ppv) return ret; } + +HRESULT WINAPI WICCreateBitmapFromSectionEx(UINT width, UINT height, + REFWICPixelFormatGUID format, HANDLE section, UINT stride, + UINT offset, WICSectionAccessLevel wicaccess, IWICBitmap **bitmap) +{ + DWORD access; + void *buffer; + HRESULT hr; + + TRACE("%u,%u,%s,%p,%u,%#x,%#x,%p\n", width, height, debugstr_guid(format), + section, stride, offset, wicaccess, bitmap); + + if (!width || !height || !section || !bitmap) return E_INVALIDARG; + + switch (wicaccess) + { + case WICSectionAccessLevelReadWrite: + access = FILE_MAP_READ | FILE_MAP_WRITE; + break; + + case WICSectionAccessLevelRead: + access = FILE_MAP_READ; + break; + + default: + FIXME("unsupported access %#x\n", wicaccess); + return E_INVALIDARG; + } + + buffer = MapViewOfFile(section, access, 0, offset, 0); + if (!buffer) return HRESULT_FROM_WIN32(GetLastError()); + + hr = BitmapImpl_Create(width, height, stride, 0, buffer, format, WICBitmapCacheOnLoad, bitmap); + if (FAILED(hr)) UnmapViewOfFile(buffer); + return hr; +} + +HRESULT WINAPI WICCreateBitmapFromSection(UINT width, UINT height, + REFWICPixelFormatGUID format, HANDLE section, + UINT stride, UINT offset, IWICBitmap **bitmap) +{ + TRACE("%u,%u,%s,%p,%u,%u,%p\n", width, height, debugstr_guid(format), + section, stride, offset, bitmap); + + return WICCreateBitmapFromSectionEx(width, height, format, section, + stride, offset, WICSectionAccessLevelRead, bitmap); +} diff --git a/reactos/dll/win32/windowscodecs/jpegformat.c b/reactos/dll/win32/windowscodecs/jpegformat.c index fb315326403..074907453b2 100644 --- a/reactos/dll/win32/windowscodecs/jpegformat.c +++ b/reactos/dll/win32/windowscodecs/jpegformat.c @@ -121,6 +121,7 @@ static void emit_message_fn(j_common_ptr cinfo, int msg_level) typedef struct { IWICBitmapDecoder IWICBitmapDecoder_iface; IWICBitmapFrameDecode IWICBitmapFrameDecode_iface; + IWICMetadataBlockReader IWICMetadataBlockReader_iface; LONG ref; BOOL initialized; BOOL cinfo_initialized; @@ -148,6 +149,11 @@ static inline JpegDecoder *decoder_from_decompress(j_decompress_ptr decompress) return CONTAINING_RECORD(decompress, JpegDecoder, cinfo); } +static inline JpegDecoder *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface) +{ + return CONTAINING_RECORD(iface, JpegDecoder, IWICMetadataBlockReader_iface); +} + static HRESULT WINAPI JpegDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, void **ppv) { @@ -664,8 +670,14 @@ static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface, static HRESULT WINAPI JpegDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, IWICMetadataQueryReader **ppIMetadataQueryReader) { - FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); - return WINCODEC_ERR_UNSUPPORTEDOPERATION; + JpegDecoder *This = impl_from_IWICBitmapFrameDecode(iface); + + TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader); + + if (!ppIMetadataQueryReader) + return E_INVALIDARG; + + return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader); } static HRESULT WINAPI JpegDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *iface, @@ -696,6 +708,73 @@ static const IWICBitmapFrameDecodeVtbl JpegDecoder_Frame_Vtbl = { JpegDecoder_Frame_GetThumbnail }; +static HRESULT WINAPI JpegDecoder_Block_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid, + void **ppv) +{ + JpegDecoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv); +} + +static ULONG WINAPI JpegDecoder_Block_AddRef(IWICMetadataBlockReader *iface) +{ + JpegDecoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface); +} + +static ULONG WINAPI JpegDecoder_Block_Release(IWICMetadataBlockReader *iface) +{ + JpegDecoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); +} + +static HRESULT WINAPI JpegDecoder_Block_GetContainerFormat(IWICMetadataBlockReader *iface, + GUID *pguidContainerFormat) +{ + TRACE("%p,%p\n", iface, pguidContainerFormat); + + if (!pguidContainerFormat) return E_INVALIDARG; + + memcpy(pguidContainerFormat, &GUID_ContainerFormatJpeg, sizeof(GUID)); + + return S_OK; +} + +static HRESULT WINAPI JpegDecoder_Block_GetCount(IWICMetadataBlockReader *iface, + UINT *pcCount) +{ + FIXME("%p,%p\n", iface, pcCount); + + if (!pcCount) return E_INVALIDARG; + + *pcCount = 0; + + return S_OK; +} + +static HRESULT WINAPI JpegDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader *iface, + UINT nIndex, IWICMetadataReader **ppIMetadataReader) +{ + FIXME("%p,%d,%p\n", iface, nIndex, ppIMetadataReader); + return E_INVALIDARG; +} + +static HRESULT WINAPI JpegDecoder_Block_GetEnumerator(IWICMetadataBlockReader *iface, + IEnumUnknown **ppIEnumMetadata) +{ + FIXME("%p,%p\n", iface, ppIEnumMetadata); + return E_NOTIMPL; +} + +static const IWICMetadataBlockReaderVtbl JpegDecoder_Block_Vtbl = { + JpegDecoder_Block_QueryInterface, + JpegDecoder_Block_AddRef, + JpegDecoder_Block_Release, + JpegDecoder_Block_GetContainerFormat, + JpegDecoder_Block_GetCount, + JpegDecoder_Block_GetReaderByIndex, + JpegDecoder_Block_GetEnumerator, +}; + HRESULT JpegDecoder_CreateInstance(REFIID iid, void** ppv) { JpegDecoder *This; @@ -716,6 +795,7 @@ HRESULT JpegDecoder_CreateInstance(REFIID iid, void** ppv) This->IWICBitmapDecoder_iface.lpVtbl = &JpegDecoder_Vtbl; This->IWICBitmapFrameDecode_iface.lpVtbl = &JpegDecoder_Frame_Vtbl; + This->IWICMetadataBlockReader_iface.lpVtbl = &JpegDecoder_Block_Vtbl; This->ref = 1; This->initialized = FALSE; This->cinfo_initialized = FALSE; diff --git a/reactos/dll/win32/windowscodecs/metadataquery.c b/reactos/dll/win32/windowscodecs/metadataquery.c new file mode 100644 index 00000000000..4fdd29c2b1d --- /dev/null +++ b/reactos/dll/win32/windowscodecs/metadataquery.c @@ -0,0 +1,136 @@ +/* + * Copyright 2016 Andrew Eikum for CodeWeavers + * + * 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 "wincodecs_private.h" + +typedef struct { + IWICMetadataQueryReader IWICMetadataQueryReader_iface; + + LONG ref; + + IWICMetadataBlockReader *block; +} QueryReader; + +static inline QueryReader *impl_from_IWICMetadataQueryReader(IWICMetadataQueryReader *iface) +{ + return CONTAINING_RECORD(iface, QueryReader, IWICMetadataQueryReader_iface); +} + +static HRESULT WINAPI mqr_QueryInterface(IWICMetadataQueryReader *iface, REFIID riid, + void **ppvObject) +{ + QueryReader *This = impl_from_IWICMetadataQueryReader(iface); + + TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppvObject); + + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IWICMetadataQueryReader)) + *ppvObject = &This->IWICMetadataQueryReader_iface; + else + *ppvObject = NULL; + + if (*ppvObject) + { + IUnknown_AddRef((IUnknown*)*ppvObject); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI mqr_AddRef(IWICMetadataQueryReader *iface) +{ + QueryReader *This = impl_from_IWICMetadataQueryReader(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) refcount=%u\n", This, ref); + return ref; +} + +static ULONG WINAPI mqr_Release(IWICMetadataQueryReader *iface) +{ + QueryReader *This = impl_from_IWICMetadataQueryReader(iface); + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p) refcount=%u\n", This, ref); + if (!ref) + { + IWICMetadataBlockReader_Release(This->block); + HeapFree(GetProcessHeap(), 0, This); + } + return ref; +} + +static HRESULT WINAPI mqr_GetContainerFormat(IWICMetadataQueryReader *iface, + GUID *pguidContainerFormat) +{ + QueryReader *This = impl_from_IWICMetadataQueryReader(iface); + FIXME("(%p,%p)\n", This, pguidContainerFormat); + return E_NOTIMPL; +} + +static HRESULT WINAPI mqr_GetLocation(IWICMetadataQueryReader *iface, + UINT cchMaxLength, WCHAR *wzNamespace, UINT *pcchActualLength) +{ + QueryReader *This = impl_from_IWICMetadataQueryReader(iface); + FIXME("(%p,%u,%p,%p)\n", This, cchMaxLength, wzNamespace, pcchActualLength); + return E_NOTIMPL; +} + +static HRESULT WINAPI mqr_GetMetadataByName(IWICMetadataQueryReader *iface, + LPCWSTR wzName, PROPVARIANT *pvarValue) +{ + QueryReader *This = impl_from_IWICMetadataQueryReader(iface); + FIXME("(%p,%s,%p)\n", This, wine_dbgstr_w(wzName), pvarValue); + return E_NOTIMPL; +} + +static HRESULT WINAPI mqr_GetEnumerator(IWICMetadataQueryReader *iface, + IEnumString **ppIEnumString) +{ + QueryReader *This = impl_from_IWICMetadataQueryReader(iface); + FIXME("(%p,%p)\n", This, ppIEnumString); + return E_NOTIMPL; +} + +static IWICMetadataQueryReaderVtbl mqr_vtbl = { + mqr_QueryInterface, + mqr_AddRef, + mqr_Release, + mqr_GetContainerFormat, + mqr_GetLocation, + mqr_GetMetadataByName, + mqr_GetEnumerator +}; + +HRESULT MetadataQueryReader_CreateInstance(IWICMetadataBlockReader *mbr, IWICMetadataQueryReader **out) +{ + QueryReader *obj; + + obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj)); + if (!obj) + return E_OUTOFMEMORY; + + obj->IWICMetadataQueryReader_iface.lpVtbl = &mqr_vtbl; + obj->ref = 1; + + IWICMetadataBlockReader_AddRef(mbr); + obj->block = mbr; + + *out = &obj->IWICMetadataQueryReader_iface; + + return S_OK; +} diff --git a/reactos/dll/win32/windowscodecs/msvc-thiscall.c b/reactos/dll/win32/windowscodecs/msvc-thiscall.c new file mode 100644 index 00000000000..7b2490841f7 --- /dev/null +++ b/reactos/dll/win32/windowscodecs/msvc-thiscall.c @@ -0,0 +1,16 @@ +#include "wincodecs_private.h" + +#define DEFINE_THISCALL_WRAPPER(func,args) \ + typedef struct {int x[args/4];} _tag_##func; \ + void __stdcall func(_tag_##func p1); \ + __declspec(naked) void __stdcall __thiscall_##func(_tag_##func p1) \ + { \ + __asm pop eax \ + __asm push ecx \ + __asm push eax \ + __asm jmp func \ + } + +DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown1, 8) +DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown3, 8) +DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown8, 4) diff --git a/reactos/dll/win32/windowscodecs/msvc.h b/reactos/dll/win32/windowscodecs/msvc.h new file mode 100644 index 00000000000..a694b8601bb --- /dev/null +++ b/reactos/dll/win32/windowscodecs/msvc.h @@ -0,0 +1,18 @@ + +#define __ASM_STDCALL_FUNC(name,args,code) + +#define typeof(X_) __typeof_ ## X_ + +struct IMILUnknown1; + +#define WINAPI __stdcall +#define HRESULT int +#define IMILUnknown1 struct IMILUnknown1 + +typedef void (WINAPI typeof(IMILUnknown1Impl_unknown1))(IMILUnknown1 *iface, void *arg); +typedef HRESULT (WINAPI typeof(IMILUnknown1Impl_unknown3))(IMILUnknown1 *iface, void *arg); +typedef HRESULT (WINAPI typeof(IMILUnknown1Impl_unknown8))(IMILUnknown1 *iface); + +#undef WINAPI +#undef HRESULT +#undef IMILUnknown1 diff --git a/reactos/dll/win32/windowscodecs/pngformat.c b/reactos/dll/win32/windowscodecs/pngformat.c index e9973ef1411..ed22b770667 100644 --- a/reactos/dll/win32/windowscodecs/pngformat.c +++ b/reactos/dll/win32/windowscodecs/pngformat.c @@ -515,7 +515,7 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p } This->end_info = ppng_create_info_struct(This->png_ptr); - if (!This->info_ptr) + if (!This->end_info) { ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, NULL); This->png_ptr = NULL; @@ -647,7 +647,7 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p /* read the image data */ This->width = ppng_get_image_width(This->png_ptr, This->info_ptr); This->height = ppng_get_image_height(This->png_ptr, This->info_ptr); - This->stride = This->width * This->bpp; + This->stride = (This->width * This->bpp + 7) / 8; image_size = This->stride * This->height; This->image_bits = HeapAlloc(GetProcessHeap(), 0, image_size); @@ -1001,8 +1001,14 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface, static HRESULT WINAPI PngDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, IWICMetadataQueryReader **ppIMetadataQueryReader) { - FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); - return E_NOTIMPL; + PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface); + + TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader); + + if (!ppIMetadataQueryReader) + return E_INVALIDARG; + + return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader); } static HRESULT WINAPI PngDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *iface, diff --git a/reactos/dll/win32/windowscodecs/regsvr.c b/reactos/dll/win32/windowscodecs/regsvr.c index b8d4740ea64..b56295948c4 100644 --- a/reactos/dll/win32/windowscodecs/regsvr.c +++ b/reactos/dll/win32/windowscodecs/regsvr.c @@ -1435,6 +1435,7 @@ static GUID const * const converter_formats[] = { &GUID_WICPixelFormat32bppBGR, &GUID_WICPixelFormat32bppBGRA, &GUID_WICPixelFormat32bppPBGRA, + &GUID_WICPixelFormat32bppGrayFloat, &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat64bppRGBA, &GUID_WICPixelFormat32bppCMYK, diff --git a/reactos/dll/win32/windowscodecs/scaler.c b/reactos/dll/win32/windowscodecs/scaler.c index 8e267e314a2..a7c2447f538 100644 --- a/reactos/dll/win32/windowscodecs/scaler.c +++ b/reactos/dll/win32/windowscodecs/scaler.c @@ -21,6 +21,7 @@ typedef struct BitmapScaler { IWICBitmapScaler IWICBitmapScaler_iface; LONG ref; + IMILBitmapScaler IMILBitmapScaler_iface; IWICBitmapSource *source; UINT width, height; UINT src_width, src_height; @@ -36,6 +37,11 @@ static inline BitmapScaler *impl_from_IWICBitmapScaler(IWICBitmapScaler *iface) return CONTAINING_RECORD(iface, BitmapScaler, IWICBitmapScaler_iface); } +static inline BitmapScaler *impl_from_IMILBitmapScaler(IMILBitmapScaler *iface) +{ + return CONTAINING_RECORD(iface, BitmapScaler, IMILBitmapScaler_iface); +} + static HRESULT WINAPI BitmapScaler_QueryInterface(IWICBitmapScaler *iface, REFIID iid, void **ppv) { @@ -50,8 +56,13 @@ static HRESULT WINAPI BitmapScaler_QueryInterface(IWICBitmapScaler *iface, REFII { *ppv = &This->IWICBitmapScaler_iface; } + else if (IsEqualIID(&IID_IMILBitmapScaler, iid)) + { + *ppv = &This->IMILBitmapScaler_iface; + } else { + FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -360,6 +371,163 @@ static const IWICBitmapScalerVtbl BitmapScaler_Vtbl = { BitmapScaler_Initialize }; +static HRESULT WINAPI IMILBitmapScaler_QueryInterface(IMILBitmapScaler *iface, REFIID iid, + void **ppv) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IMILBitmapScaler, iid) || + IsEqualIID(&IID_IMILBitmapSource, iid)) + { + IUnknown_AddRef(&This->IMILBitmapScaler_iface); + *ppv = &This->IMILBitmapScaler_iface; + return S_OK; + } + else if (IsEqualIID(&IID_IWICBitmapScaler, iid) || + IsEqualIID(&IID_IWICBitmapSource, iid)) + { + IUnknown_AddRef(&This->IWICBitmapScaler_iface); + *ppv = &This->IWICBitmapScaler_iface; + return S_OK; + } + + FIXME("unknown interface %s\n", debugstr_guid(iid)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI IMILBitmapScaler_AddRef(IMILBitmapScaler *iface) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + return IWICBitmapScaler_AddRef(&This->IWICBitmapScaler_iface); +} + +static ULONG WINAPI IMILBitmapScaler_Release(IMILBitmapScaler *iface) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + return IWICBitmapScaler_Release(&This->IWICBitmapScaler_iface); +} + +static HRESULT WINAPI IMILBitmapScaler_GetSize(IMILBitmapScaler *iface, + UINT *width, UINT *height) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + + TRACE("(%p,%p,%p)\n", iface, width, height); + + if (!This->source) + return WINCODEC_ERR_NOTINITIALIZED; + + return IWICBitmapScaler_GetSize(&This->IWICBitmapScaler_iface, width, height); +} + +static HRESULT WINAPI IMILBitmapScaler_GetPixelFormat(IMILBitmapScaler *iface, + int *format) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + IMILBitmapSource *source; + HRESULT hr; + + TRACE("(%p,%p)\n", iface, format); + + if (!format) return E_INVALIDARG; + + if (!This->source) + return WINCODEC_ERR_NOTINITIALIZED; + + hr = IWICBitmapSource_QueryInterface(This->source, &IID_IMILBitmapSource, (void **)&source); + if (hr == S_OK) + { + hr = source->lpVtbl->GetPixelFormat(source, format); + source->lpVtbl->Release(source); + } + return hr; +} + +static HRESULT WINAPI IMILBitmapScaler_GetResolution(IMILBitmapScaler *iface, + double *dpix, double *dpiy) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + + TRACE("(%p,%p,%p)\n", iface, dpix, dpiy); + + if (!This->source) + return WINCODEC_ERR_NOTINITIALIZED; + + return IWICBitmapScaler_GetResolution(&This->IWICBitmapScaler_iface, dpix, dpiy); +} + +static HRESULT WINAPI IMILBitmapScaler_CopyPalette(IMILBitmapScaler *iface, + IWICPalette *palette) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + + TRACE("(%p,%p)\n", iface, palette); + + if (!This->source) + return WINCODEC_ERR_NOTINITIALIZED; + + return IWICBitmapScaler_CopyPalette(&This->IWICBitmapScaler_iface, palette); +} + +static HRESULT WINAPI IMILBitmapScaler_CopyPixels(IMILBitmapScaler *iface, + const WICRect *rc, UINT stride, UINT size, BYTE *buffer) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + + TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer); + + if (!This->source) + return WINCODEC_ERR_NOTINITIALIZED; + + return IWICBitmapScaler_CopyPixels(&This->IWICBitmapScaler_iface, rc, stride, size, buffer); +} + +static HRESULT WINAPI IMILBitmapScaler_unknown1(IMILBitmapScaler *iface, void **ppv) +{ + TRACE("(%p,%p)\n", iface, ppv); + return E_NOINTERFACE; +} + +static HRESULT WINAPI IMILBitmapScaler_Initialize(IMILBitmapScaler *iface, + IMILBitmapSource *mil_source, UINT width, UINT height, + WICBitmapInterpolationMode mode) +{ + BitmapScaler *This = impl_from_IMILBitmapScaler(iface); + IWICBitmapSource *wic_source; + HRESULT hr; + + TRACE("(%p,%p,%u,%u,%u)\n", iface, mil_source, width, height, mode); + + if (!mil_source) return E_INVALIDARG; + + hr = mil_source->lpVtbl->QueryInterface(mil_source, &IID_IWICBitmapSource, (void **)&wic_source); + if (hr == S_OK) + { + hr = IWICBitmapScaler_Initialize(&This->IWICBitmapScaler_iface, wic_source, width, height, mode); + IWICBitmapSource_Release(wic_source); + } + return hr; +} + +static const IMILBitmapScalerVtbl IMILBitmapScaler_Vtbl = { + IMILBitmapScaler_QueryInterface, + IMILBitmapScaler_AddRef, + IMILBitmapScaler_Release, + IMILBitmapScaler_GetSize, + IMILBitmapScaler_GetPixelFormat, + IMILBitmapScaler_GetResolution, + IMILBitmapScaler_CopyPalette, + IMILBitmapScaler_CopyPixels, + IMILBitmapScaler_unknown1, + IMILBitmapScaler_Initialize +}; + HRESULT BitmapScaler_Create(IWICBitmapScaler **scaler) { BitmapScaler *This; @@ -368,6 +536,7 @@ HRESULT BitmapScaler_Create(IWICBitmapScaler **scaler) if (!This) return E_OUTOFMEMORY; This->IWICBitmapScaler_iface.lpVtbl = &BitmapScaler_Vtbl; + This->IMILBitmapScaler_iface.lpVtbl = &IMILBitmapScaler_Vtbl; This->ref = 1; This->source = NULL; This->width = 0; diff --git a/reactos/dll/win32/windowscodecs/tiffformat.c b/reactos/dll/win32/windowscodecs/tiffformat.c index 86fd89cb7d5..db3ea19c5e2 100644 --- a/reactos/dll/win32/windowscodecs/tiffformat.c +++ b/reactos/dll/win32/windowscodecs/tiffformat.c @@ -1150,8 +1150,14 @@ static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, static HRESULT WINAPI TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, IWICMetadataQueryReader **ppIMetadataQueryReader) { - FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); - return E_NOTIMPL; + TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + + TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader); + + if (!ppIMetadataQueryReader) + return E_INVALIDARG; + + return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader); } static HRESULT WINAPI TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface, diff --git a/reactos/dll/win32/windowscodecs/wincodecs_private.h b/reactos/dll/win32/windowscodecs/wincodecs_private.h index e47aca89a56..6b874e706cb 100644 --- a/reactos/dll/win32/windowscodecs/wincodecs_private.h +++ b/reactos/dll/win32/windowscodecs/wincodecs_private.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,13 @@ DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47 DEFINE_GUID(GUID_VendorWine, 0xddf46da1,0x7dc1,0x404e,0x98,0xf2,0xef,0xa4,0x8d,0xfc,0x95,0x0a); +DEFINE_GUID(IID_IMILBitmap,0xb1784d3f,0x8115,0x4763,0x13,0xaa,0x32,0xed,0xdb,0x68,0x29,0x4a); DEFINE_GUID(IID_IMILBitmapSource,0x7543696a,0xbc8d,0x46b0,0x5f,0x81,0x8d,0x95,0x72,0x89,0x72,0xbe); +DEFINE_GUID(IID_IMILBitmapLock,0xa67b2b53,0x8fa1,0x4155,0x8f,0x64,0x0c,0x24,0x7a,0x8f,0x84,0xcd); +DEFINE_GUID(IID_IMILBitmapScaler,0xa767b0f0,0x1c8c,0x4aef,0x56,0x8f,0xad,0xf9,0x6d,0xcf,0xd5,0xcb); +DEFINE_GUID(IID_IMILFormatConverter,0x7e2a746f,0x25c5,0x4851,0xb3,0xaf,0x44,0x3b,0x79,0x63,0x9e,0xc0); +DEFINE_GUID(IID_IMILPalette,0xca8e206f,0xf22c,0x4af7,0x6f,0xba,0x7b,0xed,0x5e,0xb1,0xc9,0x2f); + #define INTERFACE IMILBitmapSource DECLARE_INTERFACE_(IMILBitmapSource,IUnknown) { @@ -62,16 +69,58 @@ DECLARE_INTERFACE_(IMILBitmapSource,IUnknown) STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IWICBitmapSource methods ***/ + STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE; + STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE; + STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; + STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; + STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; /*** IMILBitmapSource methods ***/ - STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *); - STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *); - STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *); - STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *); - STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *); - STDMETHOD_(HRESULT,UnknownMethod1)(THIS_ void **); + STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE; + STDMETHOD_(HRESULT,Lock)(THIS_ const WICRect *,DWORD,IWICBitmapLock **) PURE; + STDMETHOD_(HRESULT,Unlock)(THIS_ IWICBitmapLock *) PURE; + STDMETHOD_(HRESULT,SetPalette)(THIS_ IWICPalette *) PURE; + STDMETHOD_(HRESULT,SetResolution)(THIS_ double,double) PURE; + STDMETHOD_(HRESULT,AddDirtyRect)(THIS_ const WICRect *) PURE; }; #undef INTERFACE +#define INTERFACE IMILBitmapScaler +DECLARE_INTERFACE_(IMILBitmapScaler,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IWICBitmapSource methods ***/ + STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE; + STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE; + STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; + STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; + STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; + /*** IMILBitmapScaler methods ***/ + STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE; + STDMETHOD_(HRESULT,Initialize)(THIS_ IMILBitmapSource *,UINT,UINT,WICBitmapInterpolationMode); +}; +#undef INTERFACE + +#ifdef __i386__ /* thiscall functions are i386-specific */ + +#define THISCALL(func) __thiscall_ ## func +#define DEFINE_THISCALL_WRAPPER(func,args) \ + extern typeof(func) THISCALL(func); \ + __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \ + "popl %eax\n\t" \ + "pushl %ecx\n\t" \ + "pushl %eax\n\t" \ + "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) +#else /* __i386__ */ + +#define THISCALL(func) func +#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ + +#endif /* __i386__ */ + #define INTERFACE IMILUnknown1 DECLARE_INTERFACE_(IMILUnknown1,IUnknown) { @@ -79,6 +128,19 @@ DECLARE_INTERFACE_(IMILUnknown1,IUnknown) STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** thiscall method ***/ + STDMETHOD_(void,unknown1)(THIS_ void*) PURE; + /*** stdcall ***/ + STDMETHOD_(HRESULT,unknown2)(THIS_ void*, void*) PURE; + /*** thiscall method ***/ + STDMETHOD_(HRESULT,unknown3)(THIS_ void*) PURE; + /*** stdcall ***/ + STDMETHOD_(HRESULT,unknown4)(THIS_ void*) PURE; + STDMETHOD_(HRESULT,unknown5)(THIS_ void*) PURE; + STDMETHOD_(HRESULT,unknown6)(THIS_ DWORD64) PURE; + STDMETHOD_(HRESULT,unknown7)(THIS_ void*) PURE; + /*** thiscall method ***/ + STDMETHOD_(HRESULT,unknown8)(THIS) PURE; }; #undef INTERFACE @@ -90,7 +152,9 @@ DECLARE_INTERFACE_(IMILUnknown2,IUnknown) STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE; /*** unknown methods ***/ - STDMETHOD_(HRESULT,UnknownMethod1)(THIS_ void *, void *) PURE; + STDMETHOD_(HRESULT,unknown1)(THIS_ void *,void **) PURE; + STDMETHOD_(HRESULT,unknown2)(THIS_ void *,void *) PURE; + STDMETHOD_(HRESULT,unknown3)(THIS_ void *) PURE; }; #undef INTERFACE @@ -186,6 +250,8 @@ extern HRESULT GCEReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN; extern HRESULT APEReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN; extern HRESULT GifCommentReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN; +extern HRESULT MetadataQueryReader_CreateInstance(IWICMetadataBlockReader *mbr, IWICMetadataQueryReader **out) DECLSPEC_HIDDEN; + extern HRESULT stream_initialize_from_filehandle(IWICStream *iface, HANDLE hfile) DECLSPEC_HIDDEN; #endif /* WINCODECS_PRIVATE_H */ diff --git a/reactos/dll/win32/windowscodecs/windowscodecs.spec b/reactos/dll/win32/windowscodecs/windowscodecs.spec index 289525c32a8..2c39ac399c9 100644 --- a/reactos/dll/win32/windowscodecs/windowscodecs.spec +++ b/reactos/dll/win32/windowscodecs/windowscodecs.spec @@ -105,7 +105,8 @@ @ stdcall IWICStream_InitializeFromIStream_Proxy(ptr ptr) IWICStream_InitializeFromIStream_Proxy_W @ stdcall IWICStream_InitializeFromMemory_Proxy(ptr ptr long) IWICStream_InitializeFromMemory_Proxy_W @ stdcall WICConvertBitmapSource(ptr ptr ptr) -@ stub WICCreateBitmapFromSection +@ stdcall WICCreateBitmapFromSection(long long ptr long long long ptr) +@ stdcall WICCreateBitmapFromSectionEx(long long ptr long long long long ptr) @ stdcall WICCreateColorContext_Proxy(ptr ptr) @ stdcall WICCreateImagingFactory_Proxy(long ptr) @ stub WICGetMetadataContentSize diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index e74ab1bd108..27d6b5fd21e 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -200,7 +200,7 @@ reactos/dll/win32/version # Synced to WineStaging-1.9.11 reactos/dll/win32/vssapi # Synced to WineStaging-1.9.4 reactos/dll/win32/wbemdisp # Synced to WineStaging-1.9.4 reactos/dll/win32/wbemprox # Synced to WineStaging-1.9.11 -reactos/dll/win32/windowscodecs # Synced to WineStaging-1.9.4 +reactos/dll/win32/windowscodecs # Synced to WineStaging-1.9.11 reactos/dll/win32/windowscodecsext # Synced to WineStaging-1.9.4 reactos/dll/win32/winemp3.acm # Synced to WineStaging-1.9.4 reactos/dll/win32/wing32 # Synced to WineStaging-1.9.4