Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/d3dx10_43/tests/d3dx10.c | 7 +-
dlls/windowscodecs/tests/wmpformat.c | 4 +-
dlls/wmphoto/unix_lib.c | 381 ++++++++++++++++++++++++++-
3 files changed, 383 insertions(+), 9 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/unix_lib.c b/dlls/wmphoto/unix_lib.c
index d8108bfc584..4ac3693505d 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,358 @@ 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)) || count != len)
+ {
+ WARN("Failed to read data!\n");
+ 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)) || count != len)
+ {
+ WARN("Failed to write data!\n");
+ 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)))
+ {
+ WARN("Failed to set stream pos!\n");
+ 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)))
+ {
+ WARN("Failed to get stream pos!\n");
+ 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))
+ {
+ ERR("Failed to initialize jxrlib decoder!\n");
+ return E_FAIL;
+ }
+
+ if (This->decoder->GetFrameCount(This->decoder, &st->frame_count))
+ {
+ ERR("Failed to get frame count!\n");
+ 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))
+ {
+ ERR("Failed to select frame 0!\n");
+ return E_FAIL;
+ }
+ if (This->decoder->GetPixelFormat(This->decoder,
&This->frame.pixel_format))
+ {
+ ERR("Failed to get frame pixel format!\n");
+ return E_FAIL;
+ }
+ if (This->decoder->GetSize(This->decoder, &width, &height))
+ {
+ ERR("Failed to get frame size!\n");
+ return E_FAIL;
+ }
+ if (This->decoder->GetResolution(This->decoder, &dpix, &dpiy))
+ {
+ ERR("Failed to get frame resolution!\n");
+ return E_FAIL;
+ }
+ if (This->decoder->GetColorContext(This->decoder, NULL, &count))
+ {
+ ERR("Failed to get frame color context size!\n");
+ 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))
+ {
+ ERR("Failed to copy frame data!\n");
+ 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))
+ {
+ ERR("Failed to get frame color context size!\n");
+ return E_FAIL;
+ }
+ *datasize = count;
+
+ bytes = RtlAllocateHeap(GetProcessHeap(), 0, count);
+ if (!bytes)
+ return E_OUTOFMEMORY;
+
+ if (This->decoder->GetColorContext(This->decoder, bytes, &count))
+ {
+ ERR("Failed to get frame color context!\n");
+ 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 +428,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, returning E_NOINTERFACE.\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 +472,15 @@ 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);
+#else
+ ERR("jxrlib support not compiled in!\n");
+#endif
+
*(const struct unix_funcs **)ptr_out = &unix_funcs;
return STATUS_SUCCESS;
}
--
2.30.0