Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
So, as suggested I instead implemented the few required internal functions in wmphoto.dll instead, using CoCreateInstance there.
The CreateMetadataReader implementation could still be interesting but it can be sent separately now.
dlls/windowscodecs/Makefile.in | 3 +- dlls/windowscodecs/main.c | 171 ---------------------- dlls/windowscodecs/wincodecs_common.c | 203 ++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 172 deletions(-) create mode 100644 dlls/windowscodecs/wincodecs_common.c
diff --git a/dlls/windowscodecs/Makefile.in b/dlls/windowscodecs/Makefile.in index 80e4d16c9d4..440a638e96f 100644 --- a/dlls/windowscodecs/Makefile.in +++ b/dlls/windowscodecs/Makefile.in @@ -41,7 +41,8 @@ C_SRCS = \ ungif.c \ unix_iface.c \ unix_lib.c \ - uuid.c + uuid.c \ + wincodecs_common.c
RC_SRCS = version.rc
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c index e78acc3f34f..4908a5f77e1 100644 --- a/dlls/windowscodecs/main.c +++ b/dlls/windowscodecs/main.c @@ -30,10 +30,6 @@
#include "wine/debug.h"
-WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); - -#include "wincodecs_common.h" - extern BOOL WINAPI WIC_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN;
HMODULE windowscodecs_module = 0; @@ -60,173 +56,6 @@ HRESULT WINAPI DllCanUnloadNow(void) return S_FALSE; }
-HRESULT configure_write_source(IWICBitmapFrameEncode *iface, - IWICBitmapSource *source, const WICRect *prc, - const WICPixelFormatGUID *format, - INT width, INT height, double xres, double yres) -{ - UINT src_width, src_height; - HRESULT hr = S_OK; - - if (width == 0 && height == 0) - { - if (prc) - { - if (prc->Width <= 0 || prc->Height <= 0) return E_INVALIDARG; - width = prc->Width; - height = prc->Height; - } - else - { - hr = IWICBitmapSource_GetSize(source, &src_width, &src_height); - if (FAILED(hr)) return hr; - if (src_width == 0 || src_height == 0) return E_INVALIDARG; - width = src_width; - height = src_height; - } - hr = IWICBitmapFrameEncode_SetSize(iface, (UINT)width, (UINT)height); - if (FAILED(hr)) return hr; - } - if (width == 0 || height == 0) return E_INVALIDARG; - - if (!format) - { - WICPixelFormatGUID src_format; - - hr = IWICBitmapSource_GetPixelFormat(source, &src_format); - if (FAILED(hr)) return hr; - - hr = IWICBitmapFrameEncode_SetPixelFormat(iface, &src_format); - if (FAILED(hr)) return hr; - } - - if (xres == 0.0 || yres == 0.0) - { - hr = IWICBitmapSource_GetResolution(source, &xres, &yres); - if (FAILED(hr)) return hr; - hr = IWICBitmapFrameEncode_SetResolution(iface, xres, yres); - if (FAILED(hr)) return hr; - } - - return hr; -} - -HRESULT write_source(IWICBitmapFrameEncode *iface, - IWICBitmapSource *source, const WICRect *prc, - const WICPixelFormatGUID *format, UINT bpp, BOOL need_palette, - INT width, INT height) -{ - IWICBitmapSource *converted_source; - HRESULT hr=S_OK; - WICRect rc; - UINT stride; - BYTE* pixeldata; - - if (!prc) - { - UINT src_width, src_height; - hr = IWICBitmapSource_GetSize(source, &src_width, &src_height); - if (FAILED(hr)) return hr; - rc.X = 0; - rc.Y = 0; - rc.Width = src_width; - rc.Height = src_height; - prc = &rc; - } - - if (prc->Width != width || prc->Height <= 0) - return E_INVALIDARG; - - hr = WICConvertBitmapSource(format, source, &converted_source); - if (FAILED(hr)) - { - ERR("Failed to convert source, target format %s, %#x\n", debugstr_guid(format), hr); - return E_NOTIMPL; - } - - if (need_palette) - { - IWICPalette *palette; - - hr = PaletteImpl_Create(&palette); - if (SUCCEEDED(hr)) - { - hr = IWICBitmapSource_CopyPalette(converted_source, palette); - - if (SUCCEEDED(hr)) - hr = IWICBitmapFrameEncode_SetPalette(iface, palette); - - IWICPalette_Release(palette); - } - - if (FAILED(hr)) - { - IWICBitmapSource_Release(converted_source); - return hr; - } - } - - stride = (bpp * width + 7)/8; - - pixeldata = HeapAlloc(GetProcessHeap(), 0, stride * prc->Height); - if (!pixeldata) - { - IWICBitmapSource_Release(converted_source); - return E_OUTOFMEMORY; - } - - hr = IWICBitmapSource_CopyPixels(converted_source, prc, stride, - stride*prc->Height, pixeldata); - - if (SUCCEEDED(hr)) - { - hr = IWICBitmapFrameEncode_WritePixels(iface, prc->Height, stride, - stride*prc->Height, pixeldata); - } - - HeapFree(GetProcessHeap(), 0, pixeldata); - IWICBitmapSource_Release(converted_source); - - return hr; -} - -HRESULT CDECL stream_getsize(IStream *stream, ULONGLONG *size) -{ - STATSTG statstg; - HRESULT hr; - - hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME); - - if (SUCCEEDED(hr)) - *size = statstg.cbSize.QuadPart; - - return hr; -} - -HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read) -{ - return IStream_Read(stream, buffer, read, bytes_read); -} - -HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position) -{ - HRESULT hr; - LARGE_INTEGER ofs_large; - ULARGE_INTEGER pos_large; - - ofs_large.QuadPart = ofs; - hr = IStream_Seek(stream, ofs_large, origin, &pos_large); - if (new_position) - *new_position = pos_large.QuadPart; - - return hr; -} - -HRESULT CDECL stream_write(IStream *stream, const void *buffer, ULONG write, ULONG *bytes_written) -{ - return IStream_Write(stream, buffer, write, bytes_written); -} - HRESULT get_pixelformat_bpp(const GUID *pixelformat, UINT *bpp) { HRESULT hr; diff --git a/dlls/windowscodecs/wincodecs_common.c b/dlls/windowscodecs/wincodecs_common.c new file mode 100644 index 00000000000..37ad7128f10 --- /dev/null +++ b/dlls/windowscodecs/wincodecs_common.c @@ -0,0 +1,203 @@ +/* + * wincodecs_common.c - Functions shared with other WIC libraries. + * + * Copyright 2020 Esme Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "objbase.h" + +#include "wincodecs_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); + +#include "wincodecs_common.h" + +HRESULT configure_write_source(IWICBitmapFrameEncode *iface, + IWICBitmapSource *source, const WICRect *prc, + const WICPixelFormatGUID *format, + INT width, INT height, double xres, double yres) +{ + UINT src_width, src_height; + HRESULT hr = S_OK; + + if (width == 0 && height == 0) + { + if (prc) + { + if (prc->Width <= 0 || prc->Height <= 0) return E_INVALIDARG; + width = prc->Width; + height = prc->Height; + } + else + { + hr = IWICBitmapSource_GetSize(source, &src_width, &src_height); + if (FAILED(hr)) return hr; + if (src_width == 0 || src_height == 0) return E_INVALIDARG; + width = src_width; + height = src_height; + } + hr = IWICBitmapFrameEncode_SetSize(iface, (UINT)width, (UINT)height); + if (FAILED(hr)) return hr; + } + if (width == 0 || height == 0) return E_INVALIDARG; + + if (!format) + { + WICPixelFormatGUID src_format; + + hr = IWICBitmapSource_GetPixelFormat(source, &src_format); + if (FAILED(hr)) return hr; + + hr = IWICBitmapFrameEncode_SetPixelFormat(iface, &src_format); + if (FAILED(hr)) return hr; + } + + if (xres == 0.0 || yres == 0.0) + { + hr = IWICBitmapSource_GetResolution(source, &xres, &yres); + if (FAILED(hr)) return hr; + hr = IWICBitmapFrameEncode_SetResolution(iface, xres, yres); + if (FAILED(hr)) return hr; + } + + return hr; +} + +HRESULT write_source(IWICBitmapFrameEncode *iface, + IWICBitmapSource *source, const WICRect *prc, + const WICPixelFormatGUID *format, UINT bpp, BOOL need_palette, + INT width, INT height) +{ + IWICBitmapSource *converted_source; + HRESULT hr=S_OK; + WICRect rc; + UINT stride; + BYTE* pixeldata; + + if (!prc) + { + UINT src_width, src_height; + hr = IWICBitmapSource_GetSize(source, &src_width, &src_height); + if (FAILED(hr)) return hr; + rc.X = 0; + rc.Y = 0; + rc.Width = src_width; + rc.Height = src_height; + prc = &rc; + } + + if (prc->Width != width || prc->Height <= 0) + return E_INVALIDARG; + + hr = WICConvertBitmapSource(format, source, &converted_source); + if (FAILED(hr)) + { + ERR("Failed to convert source, target format %s, %#x\n", debugstr_guid(format), hr); + return E_NOTIMPL; + } + + if (need_palette) + { + IWICPalette *palette; + + hr = PaletteImpl_Create(&palette); + if (SUCCEEDED(hr)) + { + hr = IWICBitmapSource_CopyPalette(converted_source, palette); + + if (SUCCEEDED(hr)) + hr = IWICBitmapFrameEncode_SetPalette(iface, palette); + + IWICPalette_Release(palette); + } + + if (FAILED(hr)) + { + IWICBitmapSource_Release(converted_source); + return hr; + } + } + + stride = (bpp * width + 7)/8; + + pixeldata = HeapAlloc(GetProcessHeap(), 0, stride * prc->Height); + if (!pixeldata) + { + IWICBitmapSource_Release(converted_source); + return E_OUTOFMEMORY; + } + + hr = IWICBitmapSource_CopyPixels(converted_source, prc, stride, + stride*prc->Height, pixeldata); + + if (SUCCEEDED(hr)) + { + hr = IWICBitmapFrameEncode_WritePixels(iface, prc->Height, stride, + stride*prc->Height, pixeldata); + } + + HeapFree(GetProcessHeap(), 0, pixeldata); + IWICBitmapSource_Release(converted_source); + + return hr; +} + +HRESULT CDECL stream_getsize(IStream *stream, ULONGLONG *size) +{ + STATSTG statstg; + HRESULT hr; + + hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME); + + if (SUCCEEDED(hr)) + *size = statstg.cbSize.QuadPart; + + return hr; +} + +HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read) +{ + return IStream_Read(stream, buffer, read, bytes_read); +} + +HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position) +{ + HRESULT hr; + LARGE_INTEGER ofs_large; + ULARGE_INTEGER pos_large; + + ofs_large.QuadPart = ofs; + hr = IStream_Seek(stream, ofs_large, origin, &pos_large); + if (new_position) + *new_position = pos_large.QuadPart; + + return hr; +} + +HRESULT CDECL stream_write(IStream *stream, const void *buffer, ULONG write, ULONG *bytes_written) +{ + return IStream_Write(stream, buffer, write, bytes_written); +}
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 2c4bd667e8f..b4ae2f26f54 100644 --- a/configure.ac +++ b/configure.ac @@ -58,6 +58,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]) @@ -1821,6 +1822,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
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
Rename WMPHOTO_hInstance to windowscodecs_module, so that windowscodecs internal helper can use it to load the corresponding unix library.
dlls/wmphoto/Makefile.in | 10 +++- dlls/wmphoto/main.c | 104 +++++++++++++++++++++++++++++++++---- dlls/wmphoto/unix_lib.c | 107 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+), 11 deletions(-) create mode 100644 dlls/wmphoto/unix_lib.c
diff --git a/dlls/wmphoto/Makefile.in b/dlls/wmphoto/Makefile.in index 24e1f49496a..0780271ed7c 100644 --- a/dlls/wmphoto/Makefile.in +++ b/dlls/wmphoto/Makefile.in @@ -1,7 +1,15 @@ MODULE = wmphoto.dll +IMPORTS = windowscodecs uuid kernelbase combase shcore +PARENTSRC = ../windowscodecs
EXTRADLLFLAGS = -mno-cygwin +EXTRAINCL = $(JXRLIB_CFLAGS)
-C_SRCS = main.c +C_SRCS = \ + decoder.c \ + stream.c \ + unix_iface.c \ + unix_lib.c \ + main.c
IDL_SRCS = wmphoto.idl diff --git a/dlls/wmphoto/main.c b/dlls/wmphoto/main.c index d3a926e7704..8d507560dc2 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,25 +18,98 @@ */
#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <setjmp.h> + +#define COBJMACROS
#include "windef.h" #include "winbase.h" +#include "winternl.h" #include "objbase.h" #include "rpcproxy.h" +#include "wincodecsdk.h"
+#include "wincodecs_private.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
-static HINSTANCE WMPHOTO_hInstance; +#include "wincodecs_common.h" + +struct class_factory +{ + IClassFactory IClassFactory_iface; +};
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +static HRESULT WINAPI wmp_class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out) { - switch (fdwReason) + 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 wmp_class_factory_AddRef(IClassFactory *iface) { return 2; } + +static ULONG WINAPI wmp_class_factory_Release(IClassFactory *iface) { return 1; } + +static HRESULT WINAPI wmp_class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out) +{ + struct decoder_info decoder_info; + struct decoder *decoder; + HRESULT hr; + + TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out); + + *out = NULL; + if (outer) return CLASS_E_NOAGGREGATION; + + hr = get_unix_decoder(&CLSID_WICWmpDecoder, &decoder_info, &decoder); + + if (SUCCEEDED(hr)) + hr = CommonDecoder_CreateInstance(decoder, &decoder_info, iid, out); + + return hr; +} + +static HRESULT WINAPI wmp_class_factory_LockServer(IClassFactory *iface, BOOL lock) +{ + FIXME("iface %p, lock %d, stub!\n", iface, lock); + return S_OK; +} + +static const IClassFactoryVtbl wmp_class_factory_vtbl = +{ + wmp_class_factory_QueryInterface, + wmp_class_factory_AddRef, + wmp_class_factory_Release, + wmp_class_factory_CreateInstance, + wmp_class_factory_LockServer, +}; + +static struct class_factory wmp_class_factory = {{&wmp_class_factory_vtbl}}; + +HMODULE windowscodecs_module = 0; + +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) +{ + TRACE("instance %p, reason %d, reserved %p\n", instance, reason, reserved); + + switch (reason) { case DLL_PROCESS_ATTACH: - WMPHOTO_hInstance = hinstDLL; - DisableThreadLibraryCalls(hinstDLL); + windowscodecs_module = instance; + DisableThreadLibraryCalls(instance); break; case DLL_WINE_PREATTACH: return FALSE; /* prefer native version */ @@ -49,18 +123,28 @@ 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_class_factory; + 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) { - return __wine_register_resources( WMPHOTO_hInstance ); + return __wine_register_resources( windowscodecs_module ); }
HRESULT WINAPI DllUnregisterServer(void) { - return __wine_unregister_resources( WMPHOTO_hInstance ); + return __wine_unregister_resources( windowscodecs_module ); } diff --git a/dlls/wmphoto/unix_lib.c b/dlls/wmphoto/unix_lib.c new file mode 100644 index 00000000000..d8108bfc584 --- /dev/null +++ b/dlls/wmphoto/unix_lib.c @@ -0,0 +1,107 @@ +/* + * unix_lib.c - This is the Unix side of the Unix interface. + * + * Copyright 2020 Esme Povirk + * 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 + * 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 + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" +#include "wine/port.h" + +#include <stdarg.h> + +#define NONAMELESSUNION + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "winbase.h" +#include "objbase.h" + +#include "wincodecs_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); + +#include "wincodecs_common.h" + +static const struct win32_funcs *win32_funcs; + +HRESULT CDECL stream_getsize(IStream *stream, ULONGLONG *size) +{ + return win32_funcs->stream_getsize(stream, size); +} + +HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read) +{ + return win32_funcs->stream_read(stream, buffer, read, bytes_read); +} + +HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position) +{ + return win32_funcs->stream_seek(stream, ofs, origin, new_position); +} + +HRESULT CDECL stream_write(IStream *stream, const void *buffer, ULONG write, ULONG *bytes_written) +{ + return win32_funcs->stream_write(stream, buffer, write, bytes_written); +} + +HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result) +{ + FIXME("decoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(decoder_clsid), info, result); + return E_NOTIMPL; +} + +HRESULT CDECL encoder_create(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result) +{ + FIXME("encoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(encoder_clsid), info, result); + return E_NOTIMPL; +} + +static const struct unix_funcs unix_funcs = { + decoder_create, + decoder_initialize, + decoder_get_frame_info, + decoder_copy_pixels, + decoder_get_metadata_blocks, + decoder_get_color_context, + decoder_destroy, + encoder_create, + encoder_initialize, + encoder_get_supported_format, + encoder_create_frame, + encoder_write_lines, + encoder_commit_frame, + encoder_commit_file, + encoder_destroy +}; + +NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) +{ + if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS; + + win32_funcs = ptr_in; + + *(const struct unix_funcs **)ptr_out = &unix_funcs; + return STATUS_SUCCESS; +}
Sorry I pressed the button too quickly, this one doesn't build.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 7 +- dlls/windowscodecs/tests/wmpformat.c | 4 +- dlls/wmphoto/Makefile.in | 7 +- dlls/wmphoto/main.c | 37 ++- dlls/wmphoto/unix_lib.c | 341 ++++++++++++++++++++++++++- 5 files changed, 384 insertions(+), 12 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index c8a1f9d7f71..b0800d26407 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -1531,8 +1531,7 @@ static void test_get_image_info(void) for (i = 0; i < ARRAY_SIZE(test_image); ++i) { hr = D3DX10GetImageInfoFromMemory(test_image[i].data, test_image[i].size, NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) - ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); + ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr != S_OK) continue; check_image_info(&image_info, i, __LINE__); @@ -1552,13 +1551,11 @@ static void test_get_image_info(void) create_file(test_filename, test_image[i].data, test_image[i].size, path);
hr = D3DX10GetImageInfoFromFileW(path, NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr == S_OK) check_image_info(&image_info, i, __LINE__);
hr = D3DX10GetImageInfoFromFileA(get_str_a(path), NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr == S_OK) check_image_info(&image_info, i, __LINE__); @@ -1583,13 +1580,11 @@ static void test_get_image_info(void) resource_module = create_resource_module(test_resource_name, test_image[i].data, test_image[i].size);
hr = D3DX10GetImageInfoFromResourceW(resource_module, test_resource_name, NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr == S_OK) check_image_info(&image_info, i, __LINE__);
hr = D3DX10GetImageInfoFromResourceA(resource_module, get_str_a(test_resource_name), NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr == S_OK) check_image_info(&image_info, i, __LINE__); diff --git a/dlls/windowscodecs/tests/wmpformat.c b/dlls/windowscodecs/tests/wmpformat.c index 2e2809701f6..c4f947d8acf 100644 --- a/dlls/windowscodecs/tests/wmpformat.c +++ b/dlls/windowscodecs/tests/wmpformat.c @@ -89,7 +89,7 @@ static void test_decode(void) &IID_IWICBitmapDecoder, (void **)&decoder); if (FAILED(hr)) { - todo_wine win_skip("WmpDecoder isn't available, skipping test\n"); + win_skip("WmpDecoder isn't available, skipping test\n"); return; }
@@ -123,7 +123,7 @@ static void test_decode(void) ok(count == 1, "unexpected count %u\n", count);
hr = IWICBitmapDecoder_GetFrame(decoder, 0, NULL); - ok(hr == E_INVALIDARG, "GetFrame(NULL) returned hr=%x\n", hr); + todo_wine ok(hr == E_INVALIDARG, "GetFrame(NULL) returned hr=%x\n", hr);
for (j = 2; j > 0; --j) { diff --git a/dlls/wmphoto/Makefile.in b/dlls/wmphoto/Makefile.in index 0780271ed7c..7f87d92c939 100644 --- a/dlls/wmphoto/Makefile.in +++ b/dlls/wmphoto/Makefile.in @@ -1,5 +1,5 @@ MODULE = wmphoto.dll -IMPORTS = windowscodecs uuid kernelbase combase shcore +IMPORTS = windowscodecs uuid ole32 oleaut32 propsys rpcrt4 shlwapi PARENTSRC = ../windowscodecs
EXTRADLLFLAGS = -mno-cygwin @@ -7,9 +7,12 @@ EXTRAINCL = $(JXRLIB_CFLAGS)
C_SRCS = \ decoder.c \ + main.c \ + metadataquery.c \ + palette.c \ stream.c \ unix_iface.c \ unix_lib.c \ - main.c + wincodecs_common.c
IDL_SRCS = wmphoto.idl diff --git a/dlls/wmphoto/main.c b/dlls/wmphoto/main.c index 8d507560dc2..73d0778581a 100644 --- a/dlls/wmphoto/main.c +++ b/dlls/wmphoto/main.c @@ -36,7 +36,42 @@
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
-#include "wincodecs_common.h" +HRESULT create_instance(CLSID *clsid, const IID *iid, void **ppv) +{ + return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, ppv); +} + +HRESULT ImagingFactory_CreateInstance(REFIID iid, void** ppv) +{ + return CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + iid, ppv); +} + +HRESULT get_decoder_info(REFCLSID clsid, IWICBitmapDecoderInfo **info) +{ + IWICImagingFactory* factory; + IWICComponentInfo *compinfo; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICImagingFactory, (void **)&factory); + if (FAILED(hr)) + return hr; + + hr = IWICImagingFactory_CreateComponentInfo(factory, clsid, &compinfo); + if (FAILED(hr)) + { + IWICImagingFactory_Release(factory); + return hr; + } + + hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo, + (void **)info); + + IWICComponentInfo_Release(compinfo); + IWICImagingFactory_Release(factory); + return hr; +}
struct class_factory { diff --git a/dlls/wmphoto/unix_lib.c b/dlls/wmphoto/unix_lib.c index d8108bfc584..6647b582eab 100644 --- a/dlls/wmphoto/unix_lib.c +++ b/dlls/wmphoto/unix_lib.c @@ -37,6 +37,14 @@ #include "winbase.h" #include "objbase.h"
+#include "initguid.h" + +#ifdef SONAME_LIBJXRGLUE +#define ERR JXR_ERR +#include <JXRGlue.h> +#undef ERR +#endif + #include "wincodecs_private.h" #include "wine/debug.h"
@@ -44,6 +52,320 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
#include "wincodecs_common.h"
+#ifdef SONAME_LIBJXRGLUE +static void *libjxrglue; +static typeof(PKImageDecode_Create_WMP) *pPKImageDecode_Create_WMP; + +static const struct +{ + const WICPixelFormatGUID *format; + UINT bpp; +} pixel_format_bpp[] = +{ + {&GUID_PKPixelFormat128bppRGBAFixedPoint, 128}, + {&GUID_PKPixelFormat128bppRGBAFloat, 128}, + {&GUID_PKPixelFormat128bppRGBFloat, 128}, + {&GUID_PKPixelFormat16bppRGB555, 16}, + {&GUID_PKPixelFormat16bppRGB565, 16}, + {&GUID_PKPixelFormat16bppGray, 16}, + {&GUID_PKPixelFormat16bppGrayFixedPoint, 16}, + {&GUID_PKPixelFormat16bppGrayHalf, 16}, + {&GUID_PKPixelFormat24bppBGR, 24}, + {&GUID_PKPixelFormat24bppRGB, 24}, + {&GUID_PKPixelFormat32bppBGR, 32}, + {&GUID_PKPixelFormat32bppRGB101010, 32}, + {&GUID_PKPixelFormat32bppBGRA, 32}, + {&GUID_PKPixelFormat32bppCMYK, 32}, + {&GUID_PKPixelFormat32bppGrayFixedPoint, 32}, + {&GUID_PKPixelFormat32bppGrayFloat, 32}, + {&GUID_PKPixelFormat32bppRGBE, 32}, + {&GUID_PKPixelFormat40bppCMYKAlpha, 40}, + {&GUID_PKPixelFormat48bppRGB, 48}, + {&GUID_PKPixelFormat48bppRGBFixedPoint, 48}, + {&GUID_PKPixelFormat48bppRGBHalf, 48}, + {&GUID_PKPixelFormat64bppCMYK, 64}, + {&GUID_PKPixelFormat64bppRGBA, 64}, + {&GUID_PKPixelFormat64bppRGBAFixedPoint, 64}, + {&GUID_PKPixelFormat64bppRGBAHalf, 64}, + {&GUID_PKPixelFormat80bppCMYKAlpha, 80}, + {&GUID_PKPixelFormat8bppGray, 8}, + {&GUID_PKPixelFormat96bppRGBFixedPoint, 96}, + {&GUID_PKPixelFormatBlackWhite, 1}, +}; + +static inline UINT 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 +{ + struct decoder decoder_iface; + struct WMPStream WMPStream_iface; + PKImageDecode *decoder; + IStream *stream; + struct decoder_frame frame; + UINT frame_stride; + BYTE *frame_data; +}; + +static inline struct wmp_decoder *impl_from_decoder(struct decoder *iface) +{ + return CONTAINING_RECORD(iface, struct wmp_decoder, decoder_iface); +} + +static inline struct wmp_decoder *impl_from_WMPStream(struct WMPStream *iface) +{ + return CONTAINING_RECORD(iface, struct wmp_decoder, WMPStream_iface); +} + +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); + ULONG count; + if (FAILED(stream_read(This->stream, buf, len, &count))) + return WMP_errFileIO; + return 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); + ULONG count; + if (FAILED(stream_write(This->stream, buf, len, &count))) + return WMP_errFileIO; + return WMP_errSuccess; +} + +static JXR_ERR wmp_stream_SetPos(struct WMPStream *iface, size_t pos) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + if (FAILED(stream_seek(This->stream, pos, STREAM_SEEK_SET, NULL))) + return WMP_errFileIO; + return WMP_errSuccess; +} + +static JXR_ERR wmp_stream_GetPos(struct WMPStream *iface, size_t *pos) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + ULONGLONG ofs; + if (FAILED(stream_seek(This->stream, 0, STREAM_SEEK_CUR, &ofs))) + return WMP_errFileIO; + *pos = ofs; + return WMP_errSuccess; +} + +HRESULT CDECL wmp_decoder_initialize(struct decoder *iface, IStream *stream, struct decoder_stat *st) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + HRESULT hr; + Float dpix, dpiy; + I32 width, height; + U32 count; + + TRACE("iface %p, stream %p, st %p\n", iface, stream, st); + + if (This->stream) + return WINCODEC_ERR_WRONGSTATE; + + This->stream = stream; + if (FAILED(hr = stream_seek(This->stream, 0, STREAM_SEEK_SET, NULL))) + return hr; + if (This->decoder->Initialize(This->decoder, &This->WMPStream_iface)) + return E_FAIL; + + if (This->decoder->GetFrameCount(This->decoder, &st->frame_count)) + return E_FAIL; + + if (st->frame_count > 1) FIXME("multi frame JPEG-XR not implemented\n"); + st->frame_count = 1; + st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages | + WICBitmapDecoderCapabilityCanDecodeSomeImages | + WICBitmapDecoderCapabilityCanEnumerateMetadata; + + if (This->decoder->SelectFrame(This->decoder, 0)) + return E_FAIL; + if (This->decoder->GetPixelFormat(This->decoder, &This->frame.pixel_format)) + return E_FAIL; + if (This->decoder->GetSize(This->decoder, &width, &height)) + return E_FAIL; + if (This->decoder->GetResolution(This->decoder, &dpix, &dpiy)) + return E_FAIL; + if (This->decoder->GetColorContext(This->decoder, NULL, &count)) + return E_FAIL; + + if (!(This->frame.bpp = pixel_format_get_bpp(&This->frame.pixel_format))) return E_FAIL; + This->frame.width = width; + This->frame.height = height; + This->frame.dpix = dpix; + This->frame.dpiy = dpiy; + This->frame.num_colors = 0; + if (count) This->frame.num_color_contexts = 1; + else This->frame.num_color_contexts = 0; + + return S_OK; +} + +HRESULT CDECL wmp_decoder_get_frame_info(struct decoder *iface, UINT frame, struct decoder_frame *info) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + + TRACE("iface %p, frame %d, info %p\n", iface, frame, info); + + if (frame > 0) + { + FIXME("multi frame JPEG-XR not implemented\n"); + return E_NOTIMPL; + } + + *info = This->frame; + return S_OK; +} + +HRESULT CDECL wmp_decoder_copy_pixels(struct decoder *iface, UINT frame, const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + PKRect pkrect; + U8 *frame_data; + + TRACE("iface %p, frame %d, rect %p, stride %d, buffersize %d, buffer %p\n", iface, frame, prc, stride, buffersize, buffer); + + if (frame > 0) + { + FIXME("multi frame JPEG-XR not implemented\n"); + return E_NOTIMPL; + } + + if (!This->frame_data) + { + pkrect.X = 0; + pkrect.Y = 0; + pkrect.Width = This->frame.width; + pkrect.Height = This->frame.height; + This->frame_stride = (This->frame.width * This->frame.bpp + 7) / 8; + if (!(frame_data = RtlAllocateHeap(GetProcessHeap(), 0, This->frame.height * This->frame_stride))) + return E_FAIL; + if (This->decoder->Copy(This->decoder, &pkrect, frame_data, stride)) + { + RtlFreeHeap(GetProcessHeap(), 0, frame_data); + return E_FAIL; + } + + This->frame_data = frame_data; + } + + return copy_pixels(This->frame.bpp, This->frame_data, + This->frame.width, This->frame.height, This->frame_stride, + prc, stride, buffersize, buffer); +} + +HRESULT CDECL wmp_decoder_get_metadata_blocks(struct decoder* iface, UINT frame, UINT *count, struct decoder_block **blocks) +{ + TRACE("iface %p, frame %d, count %p, blocks %p\n", iface, frame, count, blocks); + + *count = 0; + *blocks = NULL; + return S_OK; +} + +HRESULT CDECL wmp_decoder_get_color_context(struct decoder* iface, UINT frame, UINT num, BYTE **data, DWORD *datasize) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + U32 count; + U8 *bytes; + + TRACE("iface %p, frame %d, num %u, data %p, datasize %p\n", iface, frame, num, data, datasize); + + *datasize = 0; + *data = NULL; + + if (This->decoder->GetColorContext(This->decoder, NULL, &count)) + return E_FAIL; + *datasize = count; + + bytes = RtlAllocateHeap(GetProcessHeap(), 0, count); + if (!bytes) + return E_OUTOFMEMORY; + + if (This->decoder->GetColorContext(This->decoder, bytes, &count)) + { + RtlFreeHeap(GetProcessHeap(), 0, bytes); + return E_FAIL; + } + + *data = bytes; + return S_OK; +} + +void CDECL wmp_decoder_destroy(struct decoder* iface) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + + TRACE("iface %p\n", iface); + + This->decoder->Release(&This->decoder); + RtlFreeHeap(GetProcessHeap(), 0, This->frame_data); + RtlFreeHeap(GetProcessHeap(), 0, This); +} + +static const struct decoder_funcs wmp_decoder_vtable = { + wmp_decoder_initialize, + wmp_decoder_get_frame_info, + wmp_decoder_copy_pixels, + wmp_decoder_get_metadata_blocks, + wmp_decoder_get_color_context, + wmp_decoder_destroy +}; + +HRESULT CDECL wmp_decoder_create(struct decoder_info *info, struct decoder **result) +{ + struct wmp_decoder *This; + PKImageDecode *decoder; + + if (!pPKImageDecode_Create_WMP || pPKImageDecode_Create_WMP(&decoder)) return E_FAIL; + This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This)); + if (!This) + return E_OUTOFMEMORY; + + This->decoder_iface.vtable = &wmp_decoder_vtable; + This->WMPStream_iface.Close = &wmp_stream_Close; + This->WMPStream_iface.EOS = &wmp_stream_EOS; + This->WMPStream_iface.Read = &wmp_stream_Read; + This->WMPStream_iface.Write = &wmp_stream_Write; + This->WMPStream_iface.SetPos = &wmp_stream_SetPos; + This->WMPStream_iface.GetPos = &wmp_stream_GetPos; + + This->decoder = decoder; + This->stream = NULL; + memset(&This->frame, 0, sizeof(This->frame)); + This->frame_stride = 0; + This->frame_data = NULL; + + *result = &This->decoder_iface; + + info->container_format = GUID_ContainerFormatWmp; + info->block_format = GUID_ContainerFormatWmp; + info->clsid = CLSID_WICWmpDecoder; + + return S_OK; +} +#endif + static const struct win32_funcs *win32_funcs;
HRESULT CDECL stream_getsize(IStream *stream, ULONGLONG *size) @@ -68,7 +390,17 @@ HRESULT CDECL stream_write(IStream *stream, const void *buffer, ULONG write, ULO
HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result) { - FIXME("decoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(decoder_clsid), info, result); + if (IsEqualGUID(decoder_clsid, &CLSID_WICWmpDecoder)) +#ifdef SONAME_LIBJXRGLUE + return wmp_decoder_create(info, result); +#else + { + WARN("jxrlib support not compiled in!\n"); + return E_NOINTERFACE; + } +#endif + + FIXME("encoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(decoder_clsid), info, result); return E_NOTIMPL; }
@@ -102,6 +434,13 @@ NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *p
win32_funcs = ptr_in;
+#ifdef SONAME_LIBJXRGLUE + if (!(libjxrglue = dlopen(SONAME_LIBJXRGLUE, RTLD_NOW))) + ERR("failed to load %s\n", SONAME_LIBJXRGLUE); + else if (!(pPKImageDecode_Create_WMP = dlsym(libjxrglue, "PKImageDecode_Create_WMP"))) + ERR("unable to find PKImageDecode_Create_WMP in %s!\n", SONAME_LIBJXRGLUE); +#endif + *(const struct unix_funcs **)ptr_out = &unix_funcs; return STATUS_SUCCESS; }