Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windowscodecs/tests/Makefile.in | 3 +- dlls/windowscodecs/tests/wmpformat.c | 162 +++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 dlls/windowscodecs/tests/wmpformat.c
diff --git a/dlls/windowscodecs/tests/Makefile.in b/dlls/windowscodecs/tests/Makefile.in index 315e975a09c..3d1e9e8a84e 100644 --- a/dlls/windowscodecs/tests/Makefile.in +++ b/dlls/windowscodecs/tests/Makefile.in @@ -15,4 +15,5 @@ C_SRCS = \ pngformat.c \ propertybag.c \ stream.c \ - tiffformat.c + tiffformat.c \ + wmpformat.c diff --git a/dlls/windowscodecs/tests/wmpformat.c b/dlls/windowscodecs/tests/wmpformat.c new file mode 100644 index 00000000000..f43b4f216b3 --- /dev/null +++ b/dlls/windowscodecs/tests/wmpformat.c @@ -0,0 +1,162 @@ +/* + * 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 + */ + +#define COBJMACROS + +#include "objbase.h" +#include "wincodec.h" +#include "wine/test.h" + +/* generated with JxrEncApp -i image.bmp -o image.jxr -q 1 -c 22 */ +unsigned char wmp_imagedata[] = { + 0x49, 0x49, 0xbc, 0x01, 0x20, 0x00, 0x00, 0x00, 0x24, 0xc3, 0xdd, 0x6f, + 0x03, 0x4e, 0xfe, 0x4b, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0xbc, + 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xbc, + 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbc, + 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x81, 0xbc, + 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x82, 0xbc, + 0x0b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x42, 0x83, 0xbc, + 0x0b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x42, 0xc0, 0xbc, + 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0xc1, 0xbc, + 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xc2, 0xbc, + 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00, 0xc3, 0xbc, + 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x57, 0x4d, 0x50, 0x48, 0x4f, 0x54, 0x4f, 0x00, 0x11, 0x45, + 0xc0, 0x71, 0x00, 0x00, 0x00, 0x04, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x26, 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x51, 0x40, 0xc2, + 0x51, 0x88, 0x00, 0x00, 0x01, 0x02, 0x02, 0x10, 0x08, 0x62, 0x18, 0x84, + 0x21, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x18, 0x00, 0x00, 0x80, 0x40, 0x30, 0x00, 0x00, 0x00, 0x01, 0x03, 0x19, + 0x0d, 0x34, 0xd2, 0x77, 0x06, 0x62, 0xe8, 0x89, 0x8b, 0xa2, 0x26, 0x2f, + 0x11, 0xba, 0xbc, 0x46, 0xea, 0xa3, 0x6e, 0xdd, 0x72, 0x23, 0x75, 0x86, + 0xcd, 0x48, 0x73, 0xae, 0x43, 0xb9, 0x67, 0x8d, 0xfd, 0x98, 0xb0, 0xd5, + 0x52, 0x1d, 0xcb, 0x0d, 0x81, 0x06, 0xb4, 0x7d, 0xb8, 0x92, 0x5f, 0xf3, + 0x75, 0xc0, 0x3b, 0xd5, 0x07, 0xcb, 0xd0, 0xec, 0xde, 0x54, 0x1f, 0x7a, + 0x9a, 0x21, 0x8e, 0xcd, 0xe5, 0x4c, 0xdc, 0xce, 0xb8, 0x3e, 0xfa, 0x1d, + 0x8d, 0xca, 0x32, 0x94, 0xd2, 0x93, 0x2c, 0x76, 0x37, 0x2a, 0x63, 0x77, + 0x72, 0xd4, 0xd7, 0x66, 0x5a, 0xdb, 0x66, 0xed, 0x60, 0x00, 0x57, 0x4d, + 0x50, 0x48, 0x4f, 0x54, 0x4f, 0x00, 0x11, 0x45, 0xc0, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x80, 0x20, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x13, 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x91, 0xe2, 0x00, + 0x00, 0x01, 0x02, 0x00, 0x86, 0x00, 0x00, 0x20, 0x10, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x03, 0xad, 0xcf, 0xf4, 0x6b, 0x64, 0x45, 0xe1, 0x91, + 0x17, 0x8e, 0x9a, 0x51, 0x32, 0x1f, 0xe2, 0x02, 0xfa, 0x69, 0x44, 0x3b, + 0xfc, 0x7b, 0xab, 0x20, 0xfe, 0x9d, 0x35, 0xd4, 0xda, 0xb7, 0xcb, 0x77, + 0x5f, 0x4d, 0xe5, 0x0e, 0xee, 0x39, 0x97, 0x6f, 0xb9, 0x99, 0x6b, 0x6d, + 0xcc, 0xb9, 0x60}; + +static void test_decode(void) +{ + IWICBitmapDecoder *decoder; + IWICBitmapFrameDecode *framedecode; + IWICImagingFactory *factory; + IWICPalette *palette; + HRESULT hr; + HGLOBAL hwmpdata; + char *wmpdata; + IStream *wmpstream; + GUID format; + UINT count = 0, width = 0, height = 0; + BYTE imagedata[5 * 4] = {1}; + UINT i; + + const BYTE expected_imagedata[5 * 4] = { + 0x6d, 0xb0, 0xfc, 0x00, 0x6d, 0xb0, 0xfc, 0x00, 0x6d, 0xb0, + 0xfc, 0x00, 0x6d, 0xb0, 0xfc, 0x00, 0x6d, 0xb0, 0xfc, 0x00, + }; + + hr = CoCreateInstance(&CLSID_WICWmpDecoder, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapDecoder, (void **)&decoder); + todo_wine ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + if (FAILED(hr)) return; + + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICImagingFactory, (void **)&factory); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + + hwmpdata = GlobalAlloc(GMEM_MOVEABLE, sizeof(wmp_imagedata)); + ok(hwmpdata != 0, "GlobalAlloc failed\n"); + + wmpdata = GlobalLock(hwmpdata); + memcpy(wmpdata, wmp_imagedata, sizeof(wmp_imagedata)); + GlobalUnlock(hwmpdata); + + hr = CreateStreamOnHGlobal(hwmpdata, FALSE, &wmpstream); + ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr); + + hr = IWICBitmapDecoder_Initialize(decoder, wmpstream, WICDecodeMetadataCacheOnLoad); + ok(hr == S_OK, "Initialize failed, hr=%x\n", hr); + + hr = IWICBitmapDecoder_GetContainerFormat(decoder, &format); + ok(SUCCEEDED(hr), "GetContainerFormat failed, hr=%x\n", hr); + ok(IsEqualGUID(&format, &GUID_ContainerFormatWmp), + "unexpected container format\n"); + + hr = IWICBitmapDecoder_GetFrameCount(decoder, &count); + ok(SUCCEEDED(hr), "GetFrameCount failed, hr=%x\n", hr); + ok(count == 1, "unexpected count %u\n", count); + + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode); + ok(SUCCEEDED(hr), "GetFrame failed, hr=%x\n", hr); + + hr = IWICBitmapFrameDecode_GetSize(framedecode, &width, &height); + ok(SUCCEEDED(hr), "GetSize failed, hr=%x\n", hr); + ok(width == 1, "expected width=1, got %u\n", width); + ok(height == 5, "expected height=5, got %u\n", height); + + hr = IWICBitmapFrameDecode_GetPixelFormat(framedecode, &format); + ok(SUCCEEDED(hr), "GetPixelFormat failed, hr=%x\n", hr); + ok(IsEqualGUID(&format, &GUID_WICPixelFormat32bppBGRA), + "unexpected pixel format: %s\n", wine_dbgstr_guid(&format)); + + for (i = 2; i > 0; --i) + { + hr = IWICBitmapFrameDecode_CopyPixels( + framedecode, NULL, 4, sizeof(imagedata), imagedata); + ok(SUCCEEDED(hr), "CopyPixels failed, hr=%x\n", hr); + ok(!memcmp(imagedata, expected_imagedata, sizeof(imagedata)), + "unexpected image data\n"); + } + + hr = IWICImagingFactory_CreatePalette(factory, &palette); + ok(SUCCEEDED(hr), "CreatePalette failed, hr=%x\n", hr); + + hr = IWICBitmapDecoder_CopyPalette(decoder, palette); + ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "Unexpected hr %#x.\n", hr); + + hr = IWICBitmapFrameDecode_CopyPalette(framedecode, palette); + ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "Unexpected hr %#x.\n", hr); + + IWICPalette_Release(palette); + + IWICBitmapFrameDecode_Release(framedecode); + IStream_Release(wmpstream); + GlobalFree(hwmpdata); + + IWICBitmapDecoder_Release(decoder); + IWICImagingFactory_Release(factory); +} + +START_TEST(wmpformat) +{ + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + test_decode(); + + CoUninitialize(); +}
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windowscodecs/regsvr.c | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 00be59c98f3..38c252c2760 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1192,6 +1192,48 @@ static struct decoder_pattern const jpeg_patterns[] = { {0} };
+static const BYTE wmp_magic_v0[] = {0x49, 0x49, 0xbc, 0x00}; +static const BYTE wmp_magic_v1[] = {0x49, 0x49, 0xbc, 0x01}; + +static GUID const * const wmp_formats[] = { + &GUID_WICPixelFormat128bppRGBAFixedPoint, + &GUID_WICPixelFormat128bppRGBAFloat, + &GUID_WICPixelFormat128bppRGBFloat, + &GUID_WICPixelFormat16bppBGR555, + &GUID_WICPixelFormat16bppBGR565, + &GUID_WICPixelFormat16bppGray, + &GUID_WICPixelFormat16bppGrayFixedPoint, + &GUID_WICPixelFormat16bppGrayHalf, + &GUID_WICPixelFormat24bppBGR, + &GUID_WICPixelFormat24bppRGB, + &GUID_WICPixelFormat32bppBGR, + &GUID_WICPixelFormat32bppBGR101010, + &GUID_WICPixelFormat32bppBGRA, + &GUID_WICPixelFormat32bppCMYK, + &GUID_WICPixelFormat32bppGrayFixedPoint, + &GUID_WICPixelFormat32bppGrayFloat, + &GUID_WICPixelFormat32bppRGBE, + &GUID_WICPixelFormat40bppCMYKAlpha, + &GUID_WICPixelFormat48bppRGB, + &GUID_WICPixelFormat48bppRGBFixedPoint, + &GUID_WICPixelFormat48bppRGBHalf, + &GUID_WICPixelFormat64bppCMYK, + &GUID_WICPixelFormat64bppRGBA, + &GUID_WICPixelFormat64bppRGBAFixedPoint, + &GUID_WICPixelFormat64bppRGBAHalf, + &GUID_WICPixelFormat80bppCMYKAlpha, + &GUID_WICPixelFormat8bppGray, + &GUID_WICPixelFormat96bppRGBFixedPoint, + &GUID_WICPixelFormatBlackWhite, + NULL +}; + +static struct decoder_pattern const wmp_patterns[] = { + {4,0,wmp_magic_v0,mask_all,0}, + {4,0,wmp_magic_v1,mask_all,0}, + {0} +}; + static const BYTE png_magic[] = {137,80,78,71,13,10,26,10};
static GUID const * const png_formats[] = { @@ -1336,6 +1378,17 @@ static struct regsvr_decoder const decoder_list[] = { jpeg_formats, jpeg_patterns }, + { &CLSID_WICWmpDecoder, + "The Wine Project", + "JPEG-XR Decoder", + "1.0.0.0", + &GUID_VendorMicrosoft, + &GUID_ContainerFormatWmp, + "image/jxr", + ".jxr;.hdp;.wdp", + wmp_formats, + wmp_patterns + }, { &CLSID_WICPngDecoder, "The Wine Project", "PNG Decoder",
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/wmphoto/Makefile.in | 1 + dlls/wmphoto/main.c | 97 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/dlls/wmphoto/Makefile.in b/dlls/wmphoto/Makefile.in index 24e1f49496a..83462bd4c2f 100644 --- a/dlls/wmphoto/Makefile.in +++ b/dlls/wmphoto/Makefile.in @@ -1,4 +1,5 @@ MODULE = wmphoto.dll +IMPORTS = windowscodecs uuid kernelbase
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/wmphoto/main.c b/dlls/wmphoto/main.c index d3a926e7704..3957a6dc283 100644 --- a/dlls/wmphoto/main.c +++ b/dlls/wmphoto/main.c @@ -1,5 +1,6 @@ /* * Copyright 2017 Vincent Povirk for CodeWeavers + * Copyright 2020 Rémi Bernon for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,16 +18,96 @@ */
#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <setjmp.h> + +#define COBJMACROS
#include "windef.h" #include "winbase.h" #include "objbase.h" #include "rpcproxy.h" +#include "wincodecsdk.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+static HRESULT wmp_decoder_create(IUnknown *outer, IUnknown **out) +{ + FIXME("outer %p, out %p, stub!\n"); + return E_NOTIMPL; +} + +struct class_factory +{ + IClassFactory IClassFactory_iface; + HRESULT (*create_instance)(IUnknown *outer, IUnknown **out); +}; + +static inline struct class_factory *impl_from_IClassFactory(IClassFactory *iface) +{ + return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface); +} + +static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory)) + { + *out = iface; + IClassFactory_AddRef(iface); + return S_OK; + } + + *out = NULL; + FIXME("%s not implemented.\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI class_factory_AddRef(IClassFactory *iface) { return 2; } + +static ULONG WINAPI class_factory_Release(IClassFactory *iface) { return 1; } + +static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out) +{ + struct class_factory *factory = impl_from_IClassFactory(iface); + IUnknown *unk; + HRESULT hr; + + TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out); + + if (outer && !IsEqualGUID(iid, &IID_IUnknown)) return E_NOINTERFACE; + + *out = NULL; + if (SUCCEEDED(hr = factory->create_instance(outer, &unk))) + { + hr = IUnknown_QueryInterface(unk, iid, out); + IUnknown_Release(unk); + } + + return hr; +} + +static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL lock) +{ + FIXME("iface %p, lock %d, stub!\n", iface, lock); + return S_OK; +} + +static const IClassFactoryVtbl class_factory_vtbl = +{ + class_factory_QueryInterface, + class_factory_AddRef, + class_factory_Release, + class_factory_CreateInstance, + class_factory_LockServer, +}; + +static struct class_factory wmp_decoder_cf = {{&class_factory_vtbl}, wmp_decoder_create}; + static HINSTANCE WMPHOTO_hInstance;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) @@ -49,10 +130,20 @@ HRESULT WINAPI DllCanUnloadNow(void) return S_FALSE; }
-HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv) +HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID *out) { - FIXME("wmphoto: stub\n"); - return E_NOTIMPL; + struct class_factory *factory; + + TRACE("clsid %s, iid %s, out %p.\n", debugstr_guid(clsid), debugstr_guid(iid), out); + + if (IsEqualGUID(clsid, &CLSID_WICWmpDecoder)) factory = &wmp_decoder_cf; + else + { + FIXME("%s not implemented.\n", debugstr_guid(clsid)); + return CLASS_E_CLASSNOTAVAILABLE; + } + + return IClassFactory_QueryInterface(&factory->IClassFactory_iface, iid, out); }
HRESULT WINAPI DllRegisterServer(void)
This library is the JPEG-XR / Windows Media Photo / HD Photo reference implementation from Microsoft, released under BSD 2-Clause license:
https://archive.codeplex.com/?p=jxrlib
It is available for most Linux distributions already, and is also an optional dependency for imagemagick, freeimage or calibre:
* https://packages.debian.org/source/sid/jxrlib
* https://rpmfind.net/linux/rpm2html/search.php?query=jxrlib
* https://packages.ubuntu.com/source/xenial/jxrlib
* https://www.archlinux.org/packages/community/x86_64/jxrlib/
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- configure.ac | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/configure.ac b/configure.ac index 123dea0f5f1..c04202612de 100644 --- a/configure.ac +++ b/configure.ac @@ -60,6 +60,7 @@ AC_ARG_WITH(gstreamer, AS_HELP_STRING([--without-gstreamer],[do not use GStreame AC_ARG_WITH(hal, AS_HELP_STRING([--without-hal],[do not use HAL (dynamic device support)])) AC_ARG_WITH(inotify, AS_HELP_STRING([--without-inotify],[do not use inotify (filesystem change notifications)])) AC_ARG_WITH(jpeg, AS_HELP_STRING([--without-jpeg],[do not use JPEG])) +AC_ARG_WITH(jxrlib, AS_HELP_STRING([--without-jxrlib],[do not use JPEG-XR])) AC_ARG_WITH(krb5, AS_HELP_STRING([--without-krb5],[do not use krb5 (Kerberos)])) AC_ARG_WITH(ldap, AS_HELP_STRING([--without-ldap],[do not use LDAP]), [if test "x$withval" = "xno"; then ac_cv_header_ldap_h=no; ac_cv_header_lber_h=no; fi]) @@ -1875,6 +1876,21 @@ fi WINE_WARNING_WITH(jpeg,[test "x$ac_cv_lib_soname_jpeg" = "x"], [libjpeg ${notice_platform}development files not found, JPEG won't be supported.])
+dnl **** Check for libjxrglue **** +if test "x$with_jxrlib" != "xno" +then + WINE_PACKAGE_FLAGS(JXRLIB,[jxrlib],,[${JXRLIB_CFLAGS:--I/usr/include/jxrlib}],, + [AC_CHECK_HEADERS([JXRGlue.h],,,[#define FAR]) + if test "$ac_cv_header_JXRGlue_h" = "yes" + then + WINE_CHECK_SONAME(jxrglue,PKImageDecode_Create_WMP,,[JXRLIB_CFLAGS=""],[$JXRLIB_LIBS]) + else + JXRLIB_CFLAGS="" + fi]) +fi +WINE_WARNING_WITH(jxrlib,[test "x$ac_cv_lib_soname_jxrglue" = "x"], + [jxrlib ${notice_platform}development files not found, JPEG-XR won't be supported.]) + dnl **** Check for libpng **** if test "x$with_png" != "xno" then
At least, partially. Only supporting a single frame for now, but that should cover most use cases and in particular, Flight Simulator needs.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windowscodecs/tests/wmpformat.c | 2 +- dlls/wmphoto/Makefile.in | 2 +- dlls/wmphoto/main.c | 640 ++++++++++++++++++++++++++- 3 files changed, 641 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/tests/wmpformat.c b/dlls/windowscodecs/tests/wmpformat.c index f43b4f216b3..3014cff0972 100644 --- a/dlls/windowscodecs/tests/wmpformat.c +++ b/dlls/windowscodecs/tests/wmpformat.c @@ -82,7 +82,7 @@ static void test_decode(void)
hr = CoCreateInstance(&CLSID_WICWmpDecoder, NULL, CLSCTX_INPROC_SERVER, &IID_IWICBitmapDecoder, (void **)&decoder); - todo_wine ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); if (FAILED(hr)) return;
hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, diff --git a/dlls/wmphoto/Makefile.in b/dlls/wmphoto/Makefile.in index 83462bd4c2f..b1a840ca28f 100644 --- a/dlls/wmphoto/Makefile.in +++ b/dlls/wmphoto/Makefile.in @@ -1,7 +1,7 @@ MODULE = wmphoto.dll IMPORTS = windowscodecs uuid kernelbase
-EXTRADLLFLAGS = -mno-cygwin +EXTRAINCL = $(JXRLIB_CFLAGS)
C_SRCS = main.c
diff --git a/dlls/wmphoto/main.c b/dlls/wmphoto/main.c index 3957a6dc283..606ac8bd228 100644 --- a/dlls/wmphoto/main.c +++ b/dlls/wmphoto/main.c @@ -17,6 +17,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "config.h" +#include "wine/port.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif #include <stdarg.h> #include <stdio.h> #include <string.h> @@ -31,15 +37,629 @@ #include "wincodecsdk.h"
#include "wine/debug.h" +#include "wine/unicode.h" + +#ifdef SONAME_LIBJXRGLUE +#undef ERR +#define ERR JXR_ERR +#include <JXRGlue.h> +#undef ERR +#define ERR WINE_ERR +#endif
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+#ifdef SONAME_LIBJXRGLUE + +static void *libjxrglue; +static typeof(PKImageDecode_Create_WMP) *pPKImageDecode_Create_WMP; + +static inline const char *debug_wic_rect(const WICRect *rect) +{ + if (!rect) return "(null)"; + return wine_dbg_sprintf("(%u,%u)-(%u,%u)", rect->X, rect->Y, rect->Width, rect->Height); +} + +static const struct +{ + const WICPixelFormatGUID *format; + int bpp; +} pixel_format_bpp[] = +{ + {&GUID_WICPixelFormat128bppRGBAFixedPoint, 128}, + {&GUID_WICPixelFormat128bppRGBAFloat, 128}, + {&GUID_WICPixelFormat128bppRGBFloat, 128}, + {&GUID_WICPixelFormat16bppBGR555, 16}, + {&GUID_WICPixelFormat16bppBGR565, 16}, + {&GUID_WICPixelFormat16bppGray, 16}, + {&GUID_WICPixelFormat16bppGrayFixedPoint, 16}, + {&GUID_WICPixelFormat16bppGrayHalf, 16}, + {&GUID_WICPixelFormat24bppBGR, 24}, + {&GUID_WICPixelFormat24bppRGB, 24}, + {&GUID_WICPixelFormat32bppBGR, 32}, + {&GUID_WICPixelFormat32bppBGR101010, 32}, + {&GUID_WICPixelFormat32bppBGRA, 32}, + {&GUID_WICPixelFormat32bppCMYK, 32}, + {&GUID_WICPixelFormat32bppGrayFixedPoint, 32}, + {&GUID_WICPixelFormat32bppGrayFloat, 32}, + {&GUID_WICPixelFormat32bppRGBE, 32}, + {&GUID_WICPixelFormat40bppCMYKAlpha, 40}, + {&GUID_WICPixelFormat48bppRGB, 48}, + {&GUID_WICPixelFormat48bppRGBFixedPoint, 48}, + {&GUID_WICPixelFormat48bppRGBHalf, 48}, + {&GUID_WICPixelFormat64bppCMYK, 64}, + {&GUID_WICPixelFormat64bppRGBA, 64}, + {&GUID_WICPixelFormat64bppRGBAFixedPoint, 64}, + {&GUID_WICPixelFormat64bppRGBAHalf, 64}, + {&GUID_WICPixelFormat80bppCMYKAlpha, 80}, + {&GUID_WICPixelFormat8bppGray, 8}, + {&GUID_WICPixelFormat96bppRGBFixedPoint, 96}, + {&GUID_WICPixelFormatBlackWhite, 1}, +}; + +static inline int pixel_format_get_bpp(const WICPixelFormatGUID *format) +{ + int i; + for (i = 0; i < ARRAY_SIZE(pixel_format_bpp); ++i) + if (IsEqualGUID(format, pixel_format_bpp[i].format)) return pixel_format_bpp[i].bpp; + return 0; +} + +struct wmp_decoder +{ + IWICBitmapDecoder IWICBitmapDecoder_iface; + IWICBitmapFrameDecode IWICBitmapFrameDecode_iface; + IWICMetadataBlockReader IWICMetadataBlockReader_iface; + struct WMPStream wmp_stream; + LONG ref; + IStream *stream; + PKImageDecode *decoder; + void *image_data; + CRITICAL_SECTION lock; +}; + +static inline struct wmp_decoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) +{ + return CONTAINING_RECORD(iface, struct wmp_decoder, IWICBitmapDecoder_iface); +} + +static inline struct wmp_decoder *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface) +{ + return CONTAINING_RECORD(iface, struct wmp_decoder, IWICBitmapFrameDecode_iface); +} + +static inline struct wmp_decoder *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface) +{ + return CONTAINING_RECORD(iface, struct wmp_decoder, IWICMetadataBlockReader_iface); +} + +static inline struct wmp_decoder *impl_from_WMPStream(struct WMPStream *iface) +{ + return CONTAINING_RECORD(iface, struct wmp_decoder, wmp_stream); +} + +static JXR_ERR wmp_stream_Close(struct WMPStream **piface) +{ + TRACE("iface %p.\n", piface); + return WMP_errSuccess; +} + +static Bool wmp_stream_EOS(struct WMPStream *iface) +{ + FIXME("iface %p, stub!\n", iface); + return FALSE; +} + +static JXR_ERR wmp_stream_Read(struct WMPStream *iface, void *buf, size_t len) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + HRESULT hr; + ULONG count; + + TRACE("iface %p, buf %p, len %zx.\n", iface, buf, len); + + EnterCriticalSection(&This->lock); + hr = IStream_Read(This->stream, buf, len, &count); + LeaveCriticalSection(&This->lock); + + return FAILED(hr) ? WMP_errFail : WMP_errSuccess; +} + +static JXR_ERR wmp_stream_Write(struct WMPStream *iface, const void *buf, size_t len) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + HRESULT hr; + ULONG count; + + TRACE("iface %p, buf %p, len %zx.\n", iface, buf, len); + + EnterCriticalSection(&This->lock); + hr = IStream_Write(This->stream, buf, len, &count); + LeaveCriticalSection(&This->lock); + + return FAILED(hr) ? WMP_errFail : WMP_errSuccess; +} + +static JXR_ERR wmp_stream_SetPos(struct WMPStream *iface, size_t pos) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + LARGE_INTEGER move; + HRESULT hr; + + TRACE("iface %p, pos %zx.\n", iface, pos); + + move.QuadPart = pos; + EnterCriticalSection(&This->lock); + hr = IStream_Seek(This->stream, move, STREAM_SEEK_SET, NULL); + LeaveCriticalSection(&This->lock); + + return FAILED(hr) ? WMP_errFail : WMP_errSuccess; +} + +static JXR_ERR wmp_stream_GetPos(struct WMPStream *iface, size_t *pos) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + ULARGE_INTEGER curr; + LARGE_INTEGER move; + HRESULT hr; + + TRACE("iface %p, pos %p.\n", iface, pos); + + move.QuadPart = 0; + EnterCriticalSection(&This->lock); + hr = IStream_Seek(This->stream, move, STREAM_SEEK_CUR, &curr); + LeaveCriticalSection(&This->lock); + *pos = curr.QuadPart; + + return FAILED(hr) ? WMP_errFail : WMP_errSuccess; +} + +static HRESULT WINAPI wmp_decoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, void **out) +{ + struct wmp_decoder *This = impl_from_IWICBitmapDecoder(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (!out) return E_INVALIDARG; + + *out = NULL; + if (!IsEqualIID(&IID_IUnknown, iid) && !IsEqualIID(&IID_IWICBitmapDecoder, iid)) + return E_NOINTERFACE; + + *out = &This->IWICBitmapDecoder_iface; + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI wmp_decoder_AddRef(IWICBitmapDecoder *iface) +{ + struct wmp_decoder *This = impl_from_IWICBitmapDecoder(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("iface %p -> ref %u.\n", iface, ref); + return ref; +} + +static ULONG WINAPI wmp_decoder_Release(IWICBitmapDecoder *iface) +{ + struct wmp_decoder *This = impl_from_IWICBitmapDecoder(iface); + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("iface %p -> ref %u.\n", iface, ref); + + if (ref == 0) + { + This->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->lock); + if (This->image_data) HeapFree(GetProcessHeap(), 0, This->image_data); + if (This->decoder) This->decoder->Release(&This->decoder); + if (This->stream) IStream_Release(This->stream); + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI wmp_decoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream, DWORD *capability) +{ + FIXME("iface %p, stream %p, capability %p, stub!\n", iface, stream, capability); + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_Initialize(IWICBitmapDecoder *iface, IStream *stream, WICDecodeOptions options) +{ + struct wmp_decoder *This = impl_from_IWICBitmapDecoder(iface); + LARGE_INTEGER seek; + HRESULT hr = E_FAIL; + + TRACE("iface %p, stream %p, options %u.\n", iface, stream, options); + + EnterCriticalSection(&This->lock); + + seek.QuadPart = 0; + IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL); + IStream_AddRef(stream); + This->stream = stream; + + if (!pPKImageDecode_Create_WMP(&This->decoder) && !This->decoder->Initialize(This->decoder, &This->wmp_stream)) + hr = S_OK; + + LeaveCriticalSection(&This->lock); + return hr; +} + +static HRESULT WINAPI wmp_decoder_GetContainerFormat(IWICBitmapDecoder *iface, GUID *format) +{ + memcpy(format, &GUID_ContainerFormatWmp, sizeof(GUID)); + return S_OK; +} + +static HRESULT WINAPI wmp_decoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **info) +{ + FIXME("iface %p, info %p, stub!\n", iface, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_CopyPalette(IWICBitmapDecoder *iface, IWICPalette *palette) +{ + TRACE("iface %p, palette %p.\n", iface, palette); + return WINCODEC_ERR_PALETTEUNAVAILABLE; +} + +static HRESULT WINAPI wmp_decoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, IWICMetadataQueryReader **reader) +{ + FIXME("iface %p, reader %p, stub!\n", iface, reader); + if (!reader) return E_INVALIDARG; + *reader = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_GetPreview(IWICBitmapDecoder *iface, IWICBitmapSource **source) +{ + FIXME("iface %p, source %p, stub!\n", iface, source); + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_GetColorContexts(IWICBitmapDecoder *iface, UINT maxcount, + IWICColorContext **contexts, UINT *count) +{ + FIXME("iface %p, maxcount %u, contexts %p, count %p, stub!\n", iface, maxcount, contexts, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_GetThumbnail(IWICBitmapDecoder *iface, IWICBitmapSource **thumbnail) +{ + FIXME("iface %p, thumbnail %p, stub!\n", iface, thumbnail); + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_GetFrameCount(IWICBitmapDecoder *iface, UINT *count) +{ + struct wmp_decoder *This = impl_from_IWICBitmapDecoder(iface); + HRESULT hr = E_FAIL; + + TRACE("iface %p, count %p.\n", iface, count); + if (!count) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + if (!This->decoder->GetFrameCount(This->decoder, count)) hr = S_OK; + LeaveCriticalSection(&This->lock); + + if (SUCCEEDED(hr) && *count > 1) FIXME("unsupported frame count %u.\n", *count); + *count = 1; + return hr; +} + +static HRESULT WINAPI wmp_decoder_GetFrame(IWICBitmapDecoder *iface, UINT index, IWICBitmapFrameDecode **frame) +{ + struct wmp_decoder *This = impl_from_IWICBitmapDecoder(iface); + TRACE("iface %p, index %u, frame %p.\n", iface, index, frame); + + if (index != 0) return E_INVALIDARG; + + IWICBitmapDecoder_AddRef(iface); + *frame = &This->IWICBitmapFrameDecode_iface; + return S_OK; +} + +static const IWICBitmapDecoderVtbl wmp_decoder_vtbl = +{ + wmp_decoder_QueryInterface, + wmp_decoder_AddRef, + wmp_decoder_Release, + wmp_decoder_QueryCapability, + wmp_decoder_Initialize, + wmp_decoder_GetContainerFormat, + wmp_decoder_GetDecoderInfo, + wmp_decoder_CopyPalette, + wmp_decoder_GetMetadataQueryReader, + wmp_decoder_GetPreview, + wmp_decoder_GetColorContexts, + wmp_decoder_GetThumbnail, + wmp_decoder_GetFrameCount, + wmp_decoder_GetFrame +}; + +static HRESULT WINAPI wmp_decoder_frame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid, void **out) +{ + struct wmp_decoder *This = impl_from_IWICBitmapFrameDecode(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (!out) return E_INVALIDARG; + + *out = NULL; + if (!IsEqualIID(&IID_IUnknown, iid) && !IsEqualIID(&IID_IWICBitmapSource, iid) && + !IsEqualIID(&IID_IWICBitmapFrameDecode, iid)) + return E_NOINTERFACE; + + *out = &This->IWICBitmapFrameDecode_iface; + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI wmp_decoder_frame_AddRef(IWICBitmapFrameDecode *iface) +{ + struct wmp_decoder *This = impl_from_IWICBitmapFrameDecode(iface); + return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface); +} + +static ULONG WINAPI wmp_decoder_frame_Release(IWICBitmapFrameDecode *iface) +{ + struct wmp_decoder *This = impl_from_IWICBitmapFrameDecode(iface); + return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); +} + +static HRESULT WINAPI wmp_decoder_frame_GetSize(IWICBitmapFrameDecode *iface, UINT *width, UINT *height) +{ + struct wmp_decoder *This = impl_from_IWICBitmapFrameDecode(iface); + HRESULT hr = E_FAIL; + INT32 w, h; + + TRACE("iface %p, width %p, height %p.\n", iface, width, height); + + EnterCriticalSection(&This->lock); + if (!This->decoder->GetSize(This->decoder, &w, &h)) hr = S_OK; + LeaveCriticalSection(&This->lock); + + if (SUCCEEDED(hr)) + { + *width = w; + *height = h; + } + + return hr; +} + +static HRESULT WINAPI wmp_decoder_frame_GetPixelFormat(IWICBitmapFrameDecode *iface, WICPixelFormatGUID *format) +{ + struct wmp_decoder *This = impl_from_IWICBitmapFrameDecode(iface); + HRESULT hr = E_FAIL; + + TRACE("iface %p, format %p.\n", iface, format); + + EnterCriticalSection(&This->lock); + if (!This->decoder->GetPixelFormat(This->decoder, format)) hr = S_OK; + LeaveCriticalSection(&This->lock); + + return hr; +} + +static HRESULT WINAPI wmp_decoder_frame_GetResolution(IWICBitmapFrameDecode *iface, double *dpix, double *dpiy) +{ + struct wmp_decoder *This = impl_from_IWICBitmapFrameDecode(iface); + HRESULT hr = E_FAIL; + float resx, resy; + + TRACE("iface %p, dpix %p, dpiy %p.\n", iface, dpix, dpiy); + + EnterCriticalSection(&This->lock); + if (!This->decoder->GetResolution(This->decoder, &resx, &resy)) hr = S_OK; + LeaveCriticalSection(&This->lock); + + if (SUCCEEDED(hr)) + { + *dpix = resx; + *dpiy = resy; + } + + return hr; +} + +static HRESULT WINAPI wmp_decoder_frame_CopyPalette(IWICBitmapFrameDecode *iface, IWICPalette *palette) +{ + TRACE("iface %p, palette %p.\n", iface, palette); + return WINCODEC_ERR_PALETTEUNAVAILABLE; +} + +static HRESULT WINAPI wmp_decoder_frame_CopyPixels(IWICBitmapFrameDecode *iface, const WICRect *rect, + UINT stride, UINT bufsize, BYTE *buffer) +{ + struct wmp_decoder *This = impl_from_IWICBitmapFrameDecode(iface); + WICPixelFormatGUID format; + PKRect src_rect = {0, 0, 0, 0}; + SIZE_T y, bpp, size, width, src_stride; + BYTE *dst, *src; + JXR_ERR err; + + TRACE("iface %p, rect %p, stride %u, bufsize %u, buffer %p.\n", iface, debug_wic_rect(rect), + stride, bufsize, buffer); + + EnterCriticalSection(&This->lock); + if (This->decoder->GetPixelFormat(This->decoder, &format)) goto failed; + if (This->decoder->GetSize(This->decoder, &src_rect.Width, &src_rect.Height)) goto failed; + if (!(bpp = pixel_format_get_bpp(&format))) goto failed; + src_stride = (src_rect.Width * bpp + 7) / 8; + + if (!This->image_data) + { + size = src_rect.Height * src_stride; + if (!(This->image_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) goto failed; + if ((err = This->decoder->Copy(This->decoder, &src_rect, This->image_data, src_stride))) + goto failed; + } + + if (rect) + { + /* FIXME: not sure what to do here, should we shift bits? it's unlikely to happen anyway */ + if ((bpp % 8) && (rect->X % 8)) + FIXME("unsupported copy with non-aligned format.\n"); + src_rect.X = rect->X; + src_rect.Y = rect->Y; + src_rect.Width = rect->Width; + src_rect.Height = rect->Height; + } + + dst = buffer; + src = This->image_data; + src += (src_rect.X * bpp) / 8; + width = (src_rect.Width * bpp + 7) / 8; + for (y = src_rect.Y; y < src_rect.Y + src_rect.Height; ++y) + { + if (dst + width > buffer + bufsize) goto failed; + memcpy(dst, src + y * src_stride, width); + dst += stride; + } + + LeaveCriticalSection(&This->lock); + return S_OK; + +failed: + LeaveCriticalSection(&This->lock); + return E_FAIL; +} + +static HRESULT WINAPI wmp_decoder_frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, + IWICMetadataQueryReader **reader) +{ + FIXME("iface %p, reader %p, stub!\n", iface, reader); + if (!reader) return E_INVALIDARG; + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_frame_GetColorContexts(IWICBitmapFrameDecode *iface, UINT maxcount, + IWICColorContext **contexts, UINT *count) +{ + FIXME("iface %p, maxcount %u, contexts %p, count %p, stub\n", iface, maxcount, contexts, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_frame_GetThumbnail(IWICBitmapFrameDecode *iface, IWICBitmapSource **thumbnail) +{ + FIXME("iface %p, thumbnail %p, stub!\n", iface, thumbnail); + return WINCODEC_ERR_CODECNOTHUMBNAIL; +} + +static const IWICBitmapFrameDecodeVtbl wmp_decoder_frame_vtbl = +{ + wmp_decoder_frame_QueryInterface, + wmp_decoder_frame_AddRef, + wmp_decoder_frame_Release, + wmp_decoder_frame_GetSize, + wmp_decoder_frame_GetPixelFormat, + wmp_decoder_frame_GetResolution, + wmp_decoder_frame_CopyPalette, + wmp_decoder_frame_CopyPixels, + wmp_decoder_frame_GetMetadataQueryReader, + wmp_decoder_frame_GetColorContexts, + wmp_decoder_frame_GetThumbnail +}; + +static HRESULT WINAPI wmp_decoder_block_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid, void **ppv) +{ + struct wmp_decoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv); +} + +static ULONG WINAPI wmp_decoder_block_AddRef(IWICMetadataBlockReader *iface) +{ + struct wmp_decoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface); +} + +static ULONG WINAPI wmp_decoder_block_Release(IWICMetadataBlockReader *iface) +{ + struct wmp_decoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); +} + +static HRESULT WINAPI wmp_decoder_block_GetContainerFormat(IWICMetadataBlockReader *iface, GUID *format) +{ + if (!format) return E_INVALIDARG; + memcpy(format, &GUID_ContainerFormatWmp, sizeof(GUID)); + return S_OK; +} + +static HRESULT WINAPI wmp_decoder_block_GetCount(IWICMetadataBlockReader *iface, UINT *count) +{ + FIXME("iface %p, count %p, stub!\n", iface, count); + if (!count) return E_INVALIDARG; + *count = 0; + return S_OK; +} + +static HRESULT WINAPI wmp_decoder_block_GetReaderByIndex(IWICMetadataBlockReader *iface, UINT index, + IWICMetadataReader **reader) +{ + FIXME("iface %p, index %u, reader %p, stub!\n", iface, index, reader); + return E_NOTIMPL; +} + +static HRESULT WINAPI wmp_decoder_block_GetEnumerator(IWICMetadataBlockReader *iface, IEnumUnknown **enumerator) +{ + FIXME("iface %p, metadata %p, stub!\n", iface, enumerator); + return E_NOTIMPL; +} + +static const IWICMetadataBlockReaderVtbl wmp_decoder_block_vtbl = +{ + wmp_decoder_block_QueryInterface, + wmp_decoder_block_AddRef, + wmp_decoder_block_Release, + wmp_decoder_block_GetContainerFormat, + wmp_decoder_block_GetCount, + wmp_decoder_block_GetReaderByIndex, + wmp_decoder_block_GetEnumerator, +}; + +static HRESULT wmp_decoder_create(IUnknown *outer, IUnknown **out) +{ + struct wmp_decoder *This; + + TRACE("outer %p, out %p.\n", outer, out); + + *out = NULL; + This = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wmp_decoder)); + if (!This) return E_OUTOFMEMORY; + + This->IWICBitmapDecoder_iface.lpVtbl = &wmp_decoder_vtbl; + This->IWICBitmapFrameDecode_iface.lpVtbl = &wmp_decoder_frame_vtbl; + This->IWICMetadataBlockReader_iface.lpVtbl = &wmp_decoder_block_vtbl; + This->wmp_stream.Close = wmp_stream_Close; + This->wmp_stream.EOS = wmp_stream_EOS; + This->wmp_stream.Read = wmp_stream_Read; + This->wmp_stream.Write = wmp_stream_Write; + This->wmp_stream.SetPos = wmp_stream_SetPos; + This->wmp_stream.GetPos = wmp_stream_GetPos; + This->ref = 1; + This->stream = NULL; + This->decoder = NULL; + This->image_data = NULL; + InitializeCriticalSection(&This->lock); + This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wmp_decoder.lock"); + + *out = (IUnknown *)&This->IWICBitmapDecoder_iface; + return S_OK; +} + +#else /* !defined(SONAME_LIBJXRGLUE) */ + static HRESULT wmp_decoder_create(IUnknown *outer, IUnknown **out) { - FIXME("outer %p, out %p, stub!\n"); + ERR("JPEG-XR support not compiled in!\n"); return E_NOTIMPL; }
+#endif + struct class_factory { IClassFactory IClassFactory_iface; @@ -117,9 +737,27 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_PROCESS_ATTACH: WMPHOTO_hInstance = hinstDLL; DisableThreadLibraryCalls(hinstDLL); +#ifdef SONAME_LIBJXRGLUE + if (!(libjxrglue = dlopen(SONAME_LIBJXRGLUE, RTLD_NOW))) + { + ERR("unable to load %s!\n", SONAME_LIBJXRGLUE); + return FALSE; + } + + if (!(pPKImageDecode_Create_WMP = dlsym(libjxrglue, "PKImageDecode_Create_WMP"))) + { + ERR("unable to find PKImageDecode_Create_WMP in %s!\n", SONAME_LIBJXRGLUE); + return FALSE; + } +#endif break; case DLL_WINE_PREATTACH: return FALSE; /* prefer native version */ + case DLL_PROCESS_DETACH: +#ifdef SONAME_LIBJXRGLUE + dlclose(libjxrglue); +#endif + return TRUE; }
return TRUE;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=78571
Your paranoid android.
=== w2008s64 (32 bit report) ===
windowscodecs: wmpformat.c:132: Test failed: unexpected image data wmpformat.c:132: Test failed: unexpected image data
=== w2008s64 (64 bit report) ===
windowscodecs: wmpformat.c:132: Test failed: unexpected image data wmpformat.c:132: Test failed: unexpected image data
=== debiant (32 bit report) ===
windowscodecs: wmpformat.c:85: Test failed: CoCreateInstance failed, hr=80004001
=== debiant (32 bit French report) ===
windowscodecs: wmpformat.c:85: Test failed: CoCreateInstance failed, hr=80004001
=== debiant (32 bit Japanese:Japan report) ===
windowscodecs: wmpformat.c:85: Test failed: CoCreateInstance failed, hr=80004001
=== debiant (32 bit Chinese:China report) ===
windowscodecs: wmpformat.c:85: Test failed: CoCreateInstance failed, hr=80004001
=== debiant (32 bit WoW report) ===
windowscodecs: wmpformat.c:85: Test failed: CoCreateInstance failed, hr=80004001
=== debiant (64 bit WoW report) ===
windowscodecs: wmpformat.c:85: Test failed: CoCreateInstance failed, hr=80004001
The testbot failures will need to be addressed, of course.
d3dx10:d3dx10 has a todo for this: d3dx10.c:1380: Test succeeded inside todo block: Test 27: Got unexpected hr 0.
While we don't have to support multiple frames for an initial implementation, putting the frame object in the same struct as the decoder means someone will have to split them out later. Since this will become more difficult as the implemenation develops, I'd much rather have it done from the start.
This is effectively reimplementing copy_pixels from windowscodecs. Maybe we can split it into another file that can be shared with wmphoto?
On 2020-09-12 18:24, Esme Povirk (they/them) wrote:
The testbot failures will need to be addressed, of course.
d3dx10:d3dx10 has a todo for this: d3dx10.c:1380: Test succeeded inside todo block: Test 27: Got unexpected hr 0.
Yes, also I saw that the tests aren't passing on windows 2008, probably there isn't wmphoto.dll there.
While we don't have to support multiple frames for an initial implementation, putting the frame object in the same struct as the decoder means someone will have to split them out later. Since this will become more difficult as the implemenation develops, I'd much rather have it done from the start.
Sure.
This is effectively reimplementing copy_pixels from windowscodecs. Maybe we can split it into another file that can be shared with wmphoto?
I didn't see that function, could be handy indeed.
Thanks!
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=78567
Your paranoid android.
=== w2008s64 (32 bit report) ===
windowscodecs: wmpformat.c:132: Test failed: unexpected image data wmpformat.c:132: Test failed: unexpected image data
=== w2008s64 (64 bit report) ===
windowscodecs: wmpformat.c:132: Test failed: unexpected image data wmpformat.c:132: Test failed: unexpected image data