Wine-Devel
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 4 participants
- 84544 discussions
Oct. 11, 2020
Fixes test failures on recent Windows 10 builds, where 0x00800000 option is acceptable.
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dbgeng/tests/dbgeng.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/dbgeng/tests/dbgeng.c b/dlls/dbgeng/tests/dbgeng.c
index 572d96e405b..62797175193 100644
--- a/dlls/dbgeng/tests/dbgeng.c
+++ b/dlls/dbgeng/tests/dbgeng.c
@@ -50,7 +50,7 @@ static void test_engine_options(void)
ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
ok(options == DEBUG_ENGOPT_INITIAL_BREAK, "Unexpected options %#x.\n", options);
- hr = control->lpVtbl->AddEngineOptions(control, 0x00800000);
+ hr = control->lpVtbl->AddEngineOptions(control, 0x01000000);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
options = 0;
@@ -58,7 +58,7 @@ static void test_engine_options(void)
ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
ok(options == DEBUG_ENGOPT_INITIAL_BREAK, "Unexpected options %#x.\n", options);
- hr = control->lpVtbl->RemoveEngineOptions(control, 0x00800000);
+ hr = control->lpVtbl->RemoveEngineOptions(control, 0x01000000);
ok(hr == S_OK, "Failed to remove options, hr %#x.\n", hr);
hr = control->lpVtbl->AddEngineOptions(control, DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION);
@@ -86,10 +86,10 @@ static void test_engine_options(void)
ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
ok(options == DEBUG_ENGOPT_INITIAL_BREAK, "Unexpected options %#x.\n", options);
- hr = control->lpVtbl->SetEngineOptions(control, 0x00800000);
+ hr = control->lpVtbl->SetEngineOptions(control, 0x01000000);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
- hr = control->lpVtbl->SetEngineOptions(control, 0x00800000 | DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION);
+ hr = control->lpVtbl->SetEngineOptions(control, 0x01000000 | DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
options = 0;
--
2.28.0
1
0
Oct. 10, 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49449
Signed-off-by: Vijay Kiran Kamuju <infyquest(a)gmail.com>
1
0
2
1
Binary packages for various distributions will be available from:
https://www.winehq.org/download
Summary since last release
* Rebased to current wine 5.19 (662 patches are applied to wine vanilla)
NOTE: Currently the esync patchset has been disabled until it can be
rebased.
Upstreamed (Either directly from staging or fixed with a similar patch).
* d3dx9_36: No need to fail if we don't support vertices reordering in
D3DXMESHOPT_ATTRSORT
* winegstreamer: Add a GstPad wrapping the media source's bytestream.
* winegstreamer: Implement IMFMediaStream::GetStreamDescriptor.
* gdi32: Perform lazy initialization of fonts to improve startup
performance.
* ws2_32: Fix handling of empty string in WS_getaddrinfo.
Added:
* [46534] windows.networking.connectivity: New DLL
Updated:
* ntdll-Junction_Points
* mfplat-streaming-support
* xactengine-initial
* bcrypt-ECDHSecretAgreement
* server-Object_Types
* xactengine2-dll
* ntdll-ForceBottomUpAlloc
* color-sRGB-profile
Where can you help
* Run Steam/Battle.net/GOG/UPlay/Epic
* Test your favorite game.
* Test your favorite applications.
* Improve staging patches and get them accepted upstream.
As always, if you find a bug, please report it via
https://bugs.winehq.org
Best Regards
Alistair.
1
0
[PATCH 8/8] windowscodecs: Add a general wrapper around the decoder interface.
by Esme Povirk Oct. 9, 2020
by Esme Povirk Oct. 9, 2020
Oct. 9, 2020
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/Makefile.in | 1 +
dlls/windowscodecs/decoder.c | 746 +++++++++++++++++++++++
dlls/windowscodecs/pngformat.c | 810 +------------------------
dlls/windowscodecs/wincodecs_private.h | 3 +
4 files changed, 765 insertions(+), 795 deletions(-)
create mode 100644 dlls/windowscodecs/decoder.c
diff --git a/dlls/windowscodecs/Makefile.in b/dlls/windowscodecs/Makefile.in
index fde28aea778..2472ef57d63 100644
--- a/dlls/windowscodecs/Makefile.in
+++ b/dlls/windowscodecs/Makefile.in
@@ -14,6 +14,7 @@ C_SRCS = \
colortransform.c \
converter.c \
ddsformat.c \
+ decoder.c \
fliprotate.c \
gifformat.c \
icnsformat.c \
diff --git a/dlls/windowscodecs/decoder.c b/dlls/windowscodecs/decoder.c
new file mode 100644
index 00000000000..599b5780e8f
--- /dev/null
+++ b/dlls/windowscodecs/decoder.c
@@ -0,0 +1,746 @@
+/*
+ * Copyright 2020 Esme Povirk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+typedef struct {
+ IWICBitmapDecoder IWICBitmapDecoder_iface;
+ LONG ref;
+ CRITICAL_SECTION lock; /* must be held when stream or decoder is accessed */
+ IStream *stream;
+ struct decoder *decoder;
+ struct decoder_info decoder_info;
+ struct decoder_stat file_info;
+ WICDecodeOptions cache_options;
+} CommonDecoder;
+
+static inline CommonDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
+{
+ return CONTAINING_RECORD(iface, CommonDecoder, IWICBitmapDecoder_iface);
+}
+
+static HRESULT WINAPI CommonDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
+ void **ppv)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
+ {
+ *ppv = &This->IWICBitmapDecoder_iface;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI CommonDecoder_AddRef(IWICBitmapDecoder *iface)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI CommonDecoder_Release(IWICBitmapDecoder *iface)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ if (This->stream)
+ IStream_Release(This->stream);
+ This->lock.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&This->lock);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI CommonDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
+ DWORD *capability)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p,%p)\n", iface, stream, capability);
+
+ if (!stream || !capability) return E_INVALIDARG;
+
+ hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
+ if (hr != S_OK) return hr;
+
+ *capability = (This->file_info.flags & DECODER_FLAGS_CAPABILITY_MASK);
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
+ WICDecodeOptions cacheOptions)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ HRESULT hr=S_OK;
+
+ TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
+
+ EnterCriticalSection(&This->lock);
+
+ if (This->stream)
+ hr = WINCODEC_ERR_WRONGSTATE;
+
+ if (SUCCEEDED(hr))
+ hr = decoder_initialize(This->decoder, pIStream, &This->file_info);
+
+ if (SUCCEEDED(hr))
+ {
+ This->cache_options = cacheOptions;
+ This->stream = pIStream;
+ IStream_AddRef(This->stream);
+ }
+
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
+ GUID *pguidContainerFormat)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ memcpy(pguidContainerFormat, &This->decoder_info.container_format, sizeof(GUID));
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
+ IWICBitmapDecoderInfo **ppIDecoderInfo)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
+
+ return get_decoder_info(&This->decoder_info.clsid, ppIDecoderInfo);
+}
+
+static HRESULT WINAPI CommonDecoder_CopyPalette(IWICBitmapDecoder *iface,
+ IWICPalette *palette)
+{
+ TRACE("(%p,%p)\n", iface, palette);
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
+}
+
+static HRESULT WINAPI CommonDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
+ IWICMetadataQueryReader **reader)
+{
+ TRACE("(%p,%p)\n", iface, reader);
+
+ if (!reader) return E_INVALIDARG;
+
+ *reader = NULL;
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI CommonDecoder_GetPreview(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIBitmapSource)
+{
+ TRACE("(%p,%p)\n", iface, ppIBitmapSource);
+
+ if (!ppIBitmapSource) return E_INVALIDARG;
+
+ *ppIBitmapSource = NULL;
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI CommonDecoder_GetColorContexts(IWICBitmapDecoder *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI CommonDecoder_GetThumbnail(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+
+ if (!ppIThumbnail) return E_INVALIDARG;
+
+ *ppIThumbnail = NULL;
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static HRESULT WINAPI CommonDecoder_GetFrameCount(IWICBitmapDecoder *iface,
+ UINT *pCount)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ if (!pCount) return E_INVALIDARG;
+
+ if (!This->stream) return WINCODEC_ERR_WRONGSTATE;
+
+ *pCount = This->file_info.frame_count;
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface,
+ UINT index, IWICBitmapFrameDecode **ppIBitmapFrame);
+
+static const IWICBitmapDecoderVtbl CommonDecoder_Vtbl = {
+ CommonDecoder_QueryInterface,
+ CommonDecoder_AddRef,
+ CommonDecoder_Release,
+ CommonDecoder_QueryCapability,
+ CommonDecoder_Initialize,
+ CommonDecoder_GetContainerFormat,
+ CommonDecoder_GetDecoderInfo,
+ CommonDecoder_CopyPalette,
+ CommonDecoder_GetMetadataQueryReader,
+ CommonDecoder_GetPreview,
+ CommonDecoder_GetColorContexts,
+ CommonDecoder_GetThumbnail,
+ CommonDecoder_GetFrameCount,
+ CommonDecoder_GetFrame
+};
+
+typedef struct {
+ IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
+ IWICMetadataBlockReader IWICMetadataBlockReader_iface;
+ LONG ref;
+ CommonDecoder *parent;
+ DWORD frame;
+ struct decoder_frame decoder_frame;
+ BOOL metadata_initialized;
+ ULONG metadata_count;
+ struct decoder_block* metadata_blocks;
+} CommonDecoderFrame;
+
+static inline CommonDecoderFrame *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
+{
+ return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICBitmapFrameDecode_iface);
+}
+
+static inline CommonDecoderFrame *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
+{
+ return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICMetadataBlockReader_iface);
+}
+
+static HRESULT WINAPI CommonDecoderFrame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
+ void **ppv)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapSource, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
+ {
+ *ppv = &This->IWICBitmapFrameDecode_iface;
+ }
+ else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid) &&
+ (This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata))
+ {
+ *ppv = &This->IWICMetadataBlockReader_iface;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI CommonDecoderFrame_AddRef(IWICBitmapFrameDecode *iface)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI CommonDecoderFrame_Release(IWICBitmapFrameDecode *iface)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ IWICBitmapDecoder_Release(&This->parent->IWICBitmapDecoder_iface);
+ HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetSize(IWICBitmapFrameDecode *iface,
+ UINT *puiWidth, UINT *puiHeight)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ TRACE("(%p,%p,%p)\n", This, puiWidth, puiHeight);
+
+ if (!puiWidth || !puiHeight)
+ return E_POINTER;
+
+ *puiWidth = This->decoder_frame.width;
+ *puiHeight = This->decoder_frame.height;
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetPixelFormat(IWICBitmapFrameDecode *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ TRACE("(%p,%p)\n", This, pPixelFormat);
+
+ if (!pPixelFormat)
+ return E_POINTER;
+
+ *pPixelFormat = This->decoder_frame.pixel_format;
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetResolution(IWICBitmapFrameDecode *iface,
+ double *pDpiX, double *pDpiY)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ TRACE("(%p,%p,%p)\n", This, pDpiX, pDpiY);
+
+ if (!pDpiX || !pDpiY)
+ return E_POINTER;
+
+ *pDpiX = This->decoder_frame.dpix;
+ *pDpiY = This->decoder_frame.dpiy;
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_CopyPalette(IWICBitmapFrameDecode *iface,
+ IWICPalette *pIPalette)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ HRESULT hr=S_OK;
+
+ TRACE("(%p,%p)\n", iface, pIPalette);
+
+ if (This->decoder_frame.num_colors)
+ {
+ hr = IWICPalette_InitializeCustom(pIPalette, This->decoder_frame.palette, This->decoder_frame.num_colors);
+ }
+ else
+ {
+ hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_CopyPixels(IWICBitmapFrameDecode *iface,
+ const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ HRESULT hr;
+ UINT bytesperrow;
+ WICRect rect;
+
+ TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
+
+ if (!pbBuffer)
+ return E_POINTER;
+
+ if (!prc)
+ {
+ rect.X = 0;
+ rect.Y = 0;
+ rect.Width = This->decoder_frame.width;
+ rect.Height = This->decoder_frame.height;
+ prc = ▭
+ }
+ else
+ {
+ if (prc->X < 0 || prc->Y < 0 ||
+ prc->X+prc->Width > This->decoder_frame.width ||
+ prc->Y+prc->Height > This->decoder_frame.height)
+ return E_INVALIDARG;
+ }
+
+ bytesperrow = ((This->decoder_frame.bpp * prc->Width)+7)/8;
+
+ if (cbStride < bytesperrow)
+ return E_INVALIDARG;
+
+ if ((cbStride * (prc->Height-1)) + bytesperrow > cbBufferSize)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&This->parent->lock);
+
+ hr = decoder_copy_pixels(This->parent->decoder, This->frame,
+ prc, cbStride, cbBufferSize, pbBuffer);
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+
+ TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
+
+ if (!ppIMetadataQueryReader)
+ return E_INVALIDARG;
+
+ if (!(This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata))
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+
+ return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, NULL, ppIMetadataQueryReader);
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetColorContexts(IWICBitmapFrameDecode *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
+ HRESULT hr=S_OK;
+ UINT i;
+ BYTE *profile;
+ DWORD profile_len;
+
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+
+ if (!pcActualCount) return E_INVALIDARG;
+
+ *pcActualCount = This->decoder_frame.num_color_contexts;
+
+ if (This->decoder_frame.num_color_contexts && cCount && ppIColorContexts)
+ {
+ if (cCount >= This->decoder_frame.num_color_contexts)
+ {
+ EnterCriticalSection(&This->parent->lock);
+
+ for (i=0; i<This->decoder_frame.num_color_contexts; i++)
+ {
+ hr = decoder_get_color_context(This->parent->decoder, This->frame, i,
+ &profile, &profile_len);
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICColorContext_InitializeFromMemory(ppIColorContexts[i], profile, profile_len);
+
+ HeapFree(GetProcessHeap(), 0, profile);
+ }
+
+ if (FAILED(hr))
+ break;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_GetThumbnail(IWICBitmapFrameDecode *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+
+ if (!ppIThumbnail) return E_INVALIDARG;
+
+ *ppIThumbnail = NULL;
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static const IWICBitmapFrameDecodeVtbl CommonDecoderFrameVtbl = {
+ CommonDecoderFrame_QueryInterface,
+ CommonDecoderFrame_AddRef,
+ CommonDecoderFrame_Release,
+ CommonDecoderFrame_GetSize,
+ CommonDecoderFrame_GetPixelFormat,
+ CommonDecoderFrame_GetResolution,
+ CommonDecoderFrame_CopyPalette,
+ CommonDecoderFrame_CopyPixels,
+ CommonDecoderFrame_GetMetadataQueryReader,
+ CommonDecoderFrame_GetColorContexts,
+ CommonDecoderFrame_GetThumbnail
+};
+
+static HRESULT WINAPI CommonDecoderFrame_Block_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid,
+ void **ppv)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
+}
+
+static ULONG WINAPI CommonDecoderFrame_Block_AddRef(IWICMetadataBlockReader *iface)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
+}
+
+static ULONG WINAPI CommonDecoderFrame_Block_Release(IWICMetadataBlockReader *iface)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
+}
+
+static HRESULT WINAPI CommonDecoderFrame_Block_GetContainerFormat(IWICMetadataBlockReader *iface,
+ GUID *pguidContainerFormat)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ if (!pguidContainerFormat) return E_INVALIDARG;
+ *pguidContainerFormat = This->parent->decoder_info.block_format;
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_InitializeMetadata(CommonDecoderFrame *This)
+{
+ HRESULT hr=S_OK;
+
+ if (This->metadata_initialized)
+ return S_OK;
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (!This->metadata_initialized)
+ {
+ hr = decoder_get_metadata_blocks(This->parent->decoder, This->frame, &This->metadata_count, &This->metadata_blocks);
+ if (SUCCEEDED(hr))
+ This->metadata_initialized = TRUE;
+ }
+
+ LeaveCriticalSection(&This->parent->lock);
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_Block_GetCount(IWICMetadataBlockReader *iface,
+ UINT *pcCount)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ HRESULT hr;
+
+ TRACE("%p,%p\n", iface, pcCount);
+
+ if (!pcCount) return E_INVALIDARG;
+
+ hr = CommonDecoderFrame_InitializeMetadata(This);
+ if (SUCCEEDED(hr))
+ *pcCount = This->metadata_count;
+
+ return hr;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
+ UINT nIndex, IWICMetadataReader **ppIMetadataReader)
+{
+ CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
+ HRESULT hr;
+ IWICComponentFactory* factory;
+ IWICStream* stream;
+
+ TRACE("%p,%d,%p\n", iface, nIndex, ppIMetadataReader);
+
+ if (!ppIMetadataReader)
+ return E_INVALIDARG;
+
+ hr = CommonDecoderFrame_InitializeMetadata(This);
+
+ if (SUCCEEDED(hr) && nIndex >= This->metadata_count)
+ hr = E_INVALIDARG;
+
+ if (SUCCEEDED(hr))
+ hr = StreamImpl_Create(&stream);
+
+ if (SUCCEEDED(hr))
+ {
+ ULARGE_INTEGER offset, length;
+
+ offset.QuadPart = This->metadata_blocks[nIndex].offset;
+ length.QuadPart = This->metadata_blocks[nIndex].length;
+ hr = IWICStream_InitializeFromIStreamRegion(stream, This->parent->stream,
+ offset, length);
+
+ if (SUCCEEDED(hr))
+ hr = ImagingFactory_CreateInstance(&IID_IWICComponentFactory, (void**)&factory);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
+ &This->parent->decoder_info.block_format, NULL, This->metadata_blocks[nIndex].options,
+ (IStream*)stream, ppIMetadataReader);
+
+ IWICComponentFactory_Release(factory);
+ }
+
+ IWICStream_Release(stream);
+ }
+
+ if (FAILED(hr))
+ *ppIMetadataReader = NULL;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI CommonDecoderFrame_Block_GetEnumerator(IWICMetadataBlockReader *iface,
+ IEnumUnknown **ppIEnumMetadata)
+{
+ FIXME("%p,%p\n", iface, ppIEnumMetadata);
+ return E_NOTIMPL;
+}
+
+static const IWICMetadataBlockReaderVtbl CommonDecoderFrame_BlockVtbl = {
+ CommonDecoderFrame_Block_QueryInterface,
+ CommonDecoderFrame_Block_AddRef,
+ CommonDecoderFrame_Block_Release,
+ CommonDecoderFrame_Block_GetContainerFormat,
+ CommonDecoderFrame_Block_GetCount,
+ CommonDecoderFrame_Block_GetReaderByIndex,
+ CommonDecoderFrame_Block_GetEnumerator,
+};
+
+static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface,
+ UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
+{
+ CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
+ HRESULT hr=S_OK;
+ CommonDecoderFrame *result;
+
+ TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
+
+ if (!ppIBitmapFrame)
+ return E_POINTER;
+
+ EnterCriticalSection(&This->lock);
+
+ if (!This->stream || index >= This->file_info.frame_count)
+ hr = WINCODEC_ERR_FRAMEMISSING;
+
+ if (SUCCEEDED(hr))
+ {
+ result = HeapAlloc(GetProcessHeap(), 0, sizeof(*result));
+ if (!result)
+ hr = E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ result->IWICBitmapFrameDecode_iface.lpVtbl = &CommonDecoderFrameVtbl;
+ result->IWICMetadataBlockReader_iface.lpVtbl = &CommonDecoderFrame_BlockVtbl;
+ result->ref = 1;
+ result->parent = This;
+ result->frame = index;
+ result->metadata_initialized = FALSE;
+ result->metadata_count = 0;
+ result->metadata_blocks = NULL;
+
+ hr = decoder_get_frame_info(This->decoder, index, &result->decoder_frame);
+
+ if (SUCCEEDED(hr) && This->cache_options == WICDecodeMetadataCacheOnLoad)
+ hr = CommonDecoderFrame_InitializeMetadata(result);
+
+ if (FAILED(hr))
+ HeapFree(GetProcessHeap(), 0, result);
+ }
+
+ LeaveCriticalSection(&This->lock);
+
+ if (SUCCEEDED(hr))
+ {
+ TRACE("-> %ux%u, %u-bit pixelformat=%s res=%f,%f colors=%u contexts=%u\n",
+ result->decoder_frame.width, result->decoder_frame.height,
+ result->decoder_frame.bpp, wine_dbgstr_guid(&result->decoder_frame.pixel_format),
+ result->decoder_frame.dpix, result->decoder_frame.dpiy,
+ result->decoder_frame.num_colors, result->decoder_frame.num_color_contexts);
+ IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
+ *ppIBitmapFrame = &result->IWICBitmapFrameDecode_iface;
+ }
+ else
+ {
+ *ppIBitmapFrame = NULL;
+ }
+
+ return hr;
+}
+
+HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
+ const struct decoder_info *decoder_info, REFIID iid, void** ppv)
+{
+ CommonDecoder *This;
+ HRESULT hr;
+
+ TRACE("(%s,%s,%p)\n", debugstr_guid(&decoder_info->clsid), debugstr_guid(iid), ppv);
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+ if (!This)
+ {
+ decoder_destroy(decoder);
+ return E_OUTOFMEMORY;
+ }
+
+ This->IWICBitmapDecoder_iface.lpVtbl = &CommonDecoder_Vtbl;
+ This->ref = 1;
+ This->stream = NULL;
+ This->decoder = decoder;
+ This->decoder_info = *decoder_info;
+ InitializeCriticalSection(&This->lock);
+ This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CommonDecoder.lock");
+
+ hr = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
+ IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
+
+ return hr;
+}
+
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index efd5f6ab2c1..b36512447b2 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -392,795 +392,6 @@ static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message
WARN("PNG warning: %s\n", debugstr_a(warning_message));
}
-typedef struct {
- ULARGE_INTEGER ofs, len;
- IWICMetadataReader* reader;
-} metadata_block_info;
-
-typedef struct {
- IWICBitmapDecoder IWICBitmapDecoder_iface;
- IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
- IWICMetadataBlockReader IWICMetadataBlockReader_iface;
- LONG ref;
- IStream *stream;
- struct decoder *png_decoder;
- struct decoder_info decoder_info;
- struct decoder_stat file_info;
- struct decoder_frame decoder_frame;
- png_structp png_ptr;
- png_infop info_ptr;
- png_infop end_info;
- BOOL initialized;
- int bpp;
- int width, height;
- UINT stride;
- const WICPixelFormatGUID *format;
- BYTE *image_bits;
- CRITICAL_SECTION lock; /* must be held when png structures are accessed or initialized is set */
- ULONG metadata_count;
- struct decoder_block* metadata_blocks;
-} PngDecoder;
-
-static inline PngDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
-{
- return CONTAINING_RECORD(iface, PngDecoder, IWICBitmapDecoder_iface);
-}
-
-static inline PngDecoder *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
-{
- return CONTAINING_RECORD(iface, PngDecoder, IWICBitmapFrameDecode_iface);
-}
-
-static inline PngDecoder *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
-{
- return CONTAINING_RECORD(iface, PngDecoder, IWICMetadataBlockReader_iface);
-}
-
-static const IWICBitmapFrameDecodeVtbl PngDecoder_FrameVtbl;
-
-static HRESULT WINAPI PngDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
- void **ppv)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
-
- if (!ppv) return E_INVALIDARG;
-
- if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
- {
- *ppv = &This->IWICBitmapDecoder_iface;
- }
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
-}
-
-static ULONG WINAPI PngDecoder_AddRef(IWICBitmapDecoder *iface)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) refcount=%u\n", iface, ref);
-
- return ref;
-}
-
-static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
-
- TRACE("(%p) refcount=%u\n", iface, ref);
-
- if (ref == 0)
- {
- if (This->stream)
- IStream_Release(This->stream);
- if (This->png_ptr)
- ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info);
- if (This->png_decoder)
- decoder_destroy(This->png_decoder);
- This->lock.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&This->lock);
- HeapFree(GetProcessHeap(), 0, This->image_bits);
- HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
- HeapFree(GetProcessHeap(), 0, This);
- }
-
- return ref;
-}
-
-static HRESULT WINAPI PngDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
- DWORD *capability)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- HRESULT hr;
-
- TRACE("(%p,%p,%p)\n", iface, stream, capability);
-
- if (!stream || !capability) return E_INVALIDARG;
-
- hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
- if (hr != S_OK) return hr;
-
- *capability = (This->file_info.flags & DECODER_FLAGS_CAPABILITY_MASK);
- return S_OK;
-}
-
-static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
-{
- IStream *stream = ppng_get_io_ptr(png_ptr);
- HRESULT hr;
- ULONG bytesread;
-
- hr = IStream_Read(stream, data, length, &bytesread);
- if (FAILED(hr) || bytesread != length)
- {
- ppng_error(png_ptr, "failed reading data");
- }
-}
-
-static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
- WICDecodeOptions cacheOptions)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- LARGE_INTEGER seek;
- HRESULT hr=S_OK;
- png_bytep *row_pointers=NULL;
- UINT image_size;
- UINT i;
- int color_type, bit_depth;
- png_bytep trans;
- int num_trans;
- png_uint_32 transparency;
- png_color_16p trans_values;
- jmp_buf jmpbuf;
-
- TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
-
- EnterCriticalSection(&This->lock);
-
- if (This->initialized)
- {
- hr = WINCODEC_ERR_WRONGSTATE;
- goto end;
- }
-
- hr = decoder_initialize(This->png_decoder, pIStream, &This->file_info);
- if (FAILED(hr))
- goto end;
-
- /* this function cannot fail in PNG decoder */
- decoder_get_frame_info(This->png_decoder, 0, &This->decoder_frame);
-
- /* initialize libpng */
- This->png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!This->png_ptr)
- {
- hr = E_FAIL;
- goto end;
- }
-
- This->info_ptr = ppng_create_info_struct(This->png_ptr);
- if (!This->info_ptr)
- {
- ppng_destroy_read_struct(&This->png_ptr, NULL, NULL);
- This->png_ptr = NULL;
- hr = E_FAIL;
- goto end;
- }
-
- This->end_info = ppng_create_info_struct(This->png_ptr);
- if (!This->end_info)
- {
- ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, NULL);
- This->png_ptr = NULL;
- hr = E_FAIL;
- goto end;
- }
-
- /* set up setjmp/longjmp error handling */
- if (setjmp(jmpbuf))
- {
- ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info);
- This->png_ptr = NULL;
- hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT;
- goto end;
- }
- ppng_set_error_fn(This->png_ptr, jmpbuf, user_error_fn, user_warning_fn);
- ppng_set_crc_action(This->png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
-
- /* seek to the start of the stream */
- seek.QuadPart = 0;
- hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
- if (FAILED(hr)) goto end;
-
- /* set up custom i/o handling */
- ppng_set_read_fn(This->png_ptr, pIStream, user_read_data);
-
- /* read the header */
- ppng_read_info(This->png_ptr, This->info_ptr);
-
- /* choose a pixel format */
- color_type = ppng_get_color_type(This->png_ptr, This->info_ptr);
- bit_depth = ppng_get_bit_depth(This->png_ptr, This->info_ptr);
-
- /* PNGs with bit-depth greater than 8 are network byte order. Windows does not expect this. */
- if (bit_depth > 8)
- ppng_set_swap(This->png_ptr);
-
- /* check for color-keyed alpha */
- transparency = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans, &num_trans, &trans_values);
-
- if (transparency && (color_type == PNG_COLOR_TYPE_RGB ||
- (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16)))
- {
- /* expand to RGBA */
- if (color_type == PNG_COLOR_TYPE_GRAY)
- ppng_set_gray_to_rgb(This->png_ptr);
- ppng_set_tRNS_to_alpha(This->png_ptr);
- color_type = PNG_COLOR_TYPE_RGB_ALPHA;
- }
-
- switch (color_type)
- {
- case PNG_COLOR_TYPE_GRAY_ALPHA:
- /* WIC does not support grayscale alpha formats so use RGBA */
- ppng_set_gray_to_rgb(This->png_ptr);
- /* fall through */
- case PNG_COLOR_TYPE_RGB_ALPHA:
- This->bpp = bit_depth * 4;
- switch (bit_depth)
- {
- case 8:
- ppng_set_bgr(This->png_ptr);
- This->format = &GUID_WICPixelFormat32bppBGRA;
- break;
- case 16: This->format = &GUID_WICPixelFormat64bppRGBA; break;
- default:
- ERR("invalid RGBA bit depth: %i\n", bit_depth);
- hr = E_FAIL;
- goto end;
- }
- break;
- case PNG_COLOR_TYPE_GRAY:
- This->bpp = bit_depth;
- if (!transparency)
- {
- switch (bit_depth)
- {
- case 1: This->format = &GUID_WICPixelFormatBlackWhite; break;
- case 2: This->format = &GUID_WICPixelFormat2bppGray; break;
- case 4: This->format = &GUID_WICPixelFormat4bppGray; break;
- case 8: This->format = &GUID_WICPixelFormat8bppGray; break;
- case 16: This->format = &GUID_WICPixelFormat16bppGray; break;
- default:
- ERR("invalid grayscale bit depth: %i\n", bit_depth);
- hr = E_FAIL;
- goto end;
- }
- break;
- }
- /* else fall through */
- case PNG_COLOR_TYPE_PALETTE:
- This->bpp = bit_depth;
- switch (bit_depth)
- {
- case 1: This->format = &GUID_WICPixelFormat1bppIndexed; break;
- case 2: This->format = &GUID_WICPixelFormat2bppIndexed; break;
- case 4: This->format = &GUID_WICPixelFormat4bppIndexed; break;
- case 8: This->format = &GUID_WICPixelFormat8bppIndexed; break;
- default:
- ERR("invalid indexed color bit depth: %i\n", bit_depth);
- hr = E_FAIL;
- goto end;
- }
- break;
- case PNG_COLOR_TYPE_RGB:
- This->bpp = bit_depth * 3;
- switch (bit_depth)
- {
- case 8:
- ppng_set_bgr(This->png_ptr);
- This->format = &GUID_WICPixelFormat24bppBGR;
- break;
- case 16: This->format = &GUID_WICPixelFormat48bppRGB; break;
- default:
- ERR("invalid RGB color bit depth: %i\n", bit_depth);
- hr = E_FAIL;
- goto end;
- }
- break;
- default:
- ERR("invalid color type %i\n", color_type);
- hr = E_FAIL;
- goto end;
- }
-
- /* read the image data */
- This->width = ppng_get_image_width(This->png_ptr, This->info_ptr);
- This->height = ppng_get_image_height(This->png_ptr, This->info_ptr);
- This->stride = (This->width * This->bpp + 7) / 8;
- image_size = This->stride * This->height;
-
- This->image_bits = HeapAlloc(GetProcessHeap(), 0, image_size);
- if (!This->image_bits)
- {
- hr = E_OUTOFMEMORY;
- goto end;
- }
-
- row_pointers = HeapAlloc(GetProcessHeap(), 0, sizeof(png_bytep)*This->height);
- if (!row_pointers)
- {
- hr = E_OUTOFMEMORY;
- goto end;
- }
-
- for (i=0; i<This->height; i++)
- row_pointers[i] = This->image_bits + i * This->stride;
-
- ppng_read_image(This->png_ptr, row_pointers);
-
- HeapFree(GetProcessHeap(), 0, row_pointers);
- row_pointers = NULL;
-
- ppng_read_end(This->png_ptr, This->end_info);
-
- decoder_get_metadata_blocks(This->png_decoder, 0, &This->metadata_count, &This->metadata_blocks);
-
- This->stream = pIStream;
- IStream_AddRef(This->stream);
-
- This->initialized = TRUE;
-
-end:
- LeaveCriticalSection(&This->lock);
-
- HeapFree(GetProcessHeap(), 0, row_pointers);
-
- return hr;
-}
-
-static HRESULT WINAPI PngDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
- GUID *pguidContainerFormat)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- memcpy(pguidContainerFormat, &This->decoder_info.container_format, sizeof(GUID));
- return S_OK;
-}
-
-static HRESULT WINAPI PngDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
- IWICBitmapDecoderInfo **ppIDecoderInfo)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
-
- return get_decoder_info(&This->decoder_info.clsid, ppIDecoderInfo);
-}
-
-static HRESULT WINAPI PngDecoder_CopyPalette(IWICBitmapDecoder *iface,
- IWICPalette *palette)
-{
- TRACE("(%p,%p)\n", iface, palette);
- return WINCODEC_ERR_PALETTEUNAVAILABLE;
-}
-
-static HRESULT WINAPI PngDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
- IWICMetadataQueryReader **reader)
-{
- TRACE("(%p,%p)\n", iface, reader);
-
- if (!reader) return E_INVALIDARG;
-
- *reader = NULL;
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI PngDecoder_GetPreview(IWICBitmapDecoder *iface,
- IWICBitmapSource **ppIBitmapSource)
-{
- TRACE("(%p,%p)\n", iface, ppIBitmapSource);
-
- if (!ppIBitmapSource) return E_INVALIDARG;
-
- *ppIBitmapSource = NULL;
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI PngDecoder_GetColorContexts(IWICBitmapDecoder *iface,
- UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
-{
- TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI PngDecoder_GetThumbnail(IWICBitmapDecoder *iface,
- IWICBitmapSource **ppIThumbnail)
-{
- TRACE("(%p,%p)\n", iface, ppIThumbnail);
-
- if (!ppIThumbnail) return E_INVALIDARG;
-
- *ppIThumbnail = NULL;
- return WINCODEC_ERR_CODECNOTHUMBNAIL;
-}
-
-static HRESULT WINAPI PngDecoder_GetFrameCount(IWICBitmapDecoder *iface,
- UINT *pCount)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- if (!pCount) return E_INVALIDARG;
-
- if (!This->initialized) return WINCODEC_ERR_WRONGSTATE;
-
- *pCount = This->file_info.frame_count;
- return S_OK;
-}
-
-static HRESULT WINAPI PngDecoder_GetFrame(IWICBitmapDecoder *iface,
- UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
-{
- PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
- TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
-
- if (!This->initialized) return WINCODEC_ERR_FRAMEMISSING;
-
- if (index != 0) return E_INVALIDARG;
-
- IWICBitmapDecoder_AddRef(iface);
-
- *ppIBitmapFrame = &This->IWICBitmapFrameDecode_iface;
-
- return S_OK;
-}
-
-static const IWICBitmapDecoderVtbl PngDecoder_Vtbl = {
- PngDecoder_QueryInterface,
- PngDecoder_AddRef,
- PngDecoder_Release,
- PngDecoder_QueryCapability,
- PngDecoder_Initialize,
- PngDecoder_GetContainerFormat,
- PngDecoder_GetDecoderInfo,
- PngDecoder_CopyPalette,
- PngDecoder_GetMetadataQueryReader,
- PngDecoder_GetPreview,
- PngDecoder_GetColorContexts,
- PngDecoder_GetThumbnail,
- PngDecoder_GetFrameCount,
- PngDecoder_GetFrame
-};
-
-static HRESULT WINAPI PngDecoder_Frame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
- void **ppv)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- if (!ppv) return E_INVALIDARG;
-
- if (IsEqualIID(&IID_IUnknown, iid) ||
- IsEqualIID(&IID_IWICBitmapSource, iid) ||
- IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
- {
- *ppv = &This->IWICBitmapFrameDecode_iface;
- }
- else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid))
- {
- *ppv = &This->IWICMetadataBlockReader_iface;
- }
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
-}
-
-static ULONG WINAPI PngDecoder_Frame_AddRef(IWICBitmapFrameDecode *iface)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
-}
-
-static ULONG WINAPI PngDecoder_Frame_Release(IWICBitmapFrameDecode *iface)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
-}
-
-static HRESULT WINAPI PngDecoder_Frame_GetSize(IWICBitmapFrameDecode *iface,
- UINT *puiWidth, UINT *puiHeight)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- *puiWidth = This->decoder_frame.width;
- *puiHeight = This->decoder_frame.height;
- TRACE("(%p)->(%u,%u)\n", iface, *puiWidth, *puiHeight);
- return S_OK;
-}
-
-static HRESULT WINAPI PngDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *iface,
- WICPixelFormatGUID *pPixelFormat)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- TRACE("(%p,%p)\n", iface, pPixelFormat);
-
- memcpy(pPixelFormat, &This->decoder_frame.pixel_format, sizeof(GUID));
-
- return S_OK;
-}
-
-static HRESULT WINAPI PngDecoder_Frame_GetResolution(IWICBitmapFrameDecode *iface,
- double *pDpiX, double *pDpiY)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
-
- *pDpiX = This->decoder_frame.dpix;
- *pDpiY = This->decoder_frame.dpiy;
-
- TRACE("(%p)->(%0.2f,%0.2f)\n", iface, *pDpiX, *pDpiY);
-
- return S_OK;
-}
-
-static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
- IWICPalette *pIPalette)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- HRESULT hr=S_OK;
-
- TRACE("(%p,%p)\n", iface, pIPalette);
-
- if (This->decoder_frame.num_colors)
- {
- hr = IWICPalette_InitializeCustom(pIPalette, This->decoder_frame.palette, This->decoder_frame.num_colors);
- }
- else
- {
- hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
- }
-
- return hr;
-}
-
-static HRESULT WINAPI PngDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
- const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
-
- return decoder_copy_pixels(This->png_decoder, 0,
- prc, cbStride, cbBufferSize, pbBuffer);
-}
-
-static HRESULT WINAPI PngDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
- IWICMetadataQueryReader **ppIMetadataQueryReader)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
-
- TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
-
- if (!ppIMetadataQueryReader)
- return E_INVALIDARG;
-
- return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, NULL, ppIMetadataQueryReader);
-}
-
-static HRESULT WINAPI PngDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *iface,
- UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
-{
- PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- HRESULT hr=S_OK;
- BYTE *profile;
- DWORD profile_len;
-
- TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
-
- if (!pcActualCount) return E_INVALIDARG;
-
- *pcActualCount = This->decoder_frame.num_color_contexts;
-
- if (This->decoder_frame.num_color_contexts && cCount && ppIColorContexts)
- {
- EnterCriticalSection(&This->lock);
-
- hr = decoder_get_color_context(This->png_decoder, 0, 0,
- &profile, &profile_len);
-
- LeaveCriticalSection(&This->lock);
-
- if (SUCCEEDED(hr))
- {
- hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, profile_len);
-
- HeapFree(GetProcessHeap(), 0, profile);
- }
- }
-
- return hr;
-}
-
-static HRESULT WINAPI PngDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface,
- IWICBitmapSource **ppIThumbnail)
-{
- TRACE("(%p,%p)\n", iface, ppIThumbnail);
-
- if (!ppIThumbnail) return E_INVALIDARG;
-
- *ppIThumbnail = NULL;
- return WINCODEC_ERR_CODECNOTHUMBNAIL;
-}
-
-static const IWICBitmapFrameDecodeVtbl PngDecoder_FrameVtbl = {
- PngDecoder_Frame_QueryInterface,
- PngDecoder_Frame_AddRef,
- PngDecoder_Frame_Release,
- PngDecoder_Frame_GetSize,
- PngDecoder_Frame_GetPixelFormat,
- PngDecoder_Frame_GetResolution,
- PngDecoder_Frame_CopyPalette,
- PngDecoder_Frame_CopyPixels,
- PngDecoder_Frame_GetMetadataQueryReader,
- PngDecoder_Frame_GetColorContexts,
- PngDecoder_Frame_GetThumbnail
-};
-
-static HRESULT WINAPI PngDecoder_Block_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid,
- void **ppv)
-{
- PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
- return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
-}
-
-static ULONG WINAPI PngDecoder_Block_AddRef(IWICMetadataBlockReader *iface)
-{
- PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
- return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
-}
-
-static ULONG WINAPI PngDecoder_Block_Release(IWICMetadataBlockReader *iface)
-{
- PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
- return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
-}
-
-static HRESULT WINAPI PngDecoder_Block_GetContainerFormat(IWICMetadataBlockReader *iface,
- GUID *pguidContainerFormat)
-{
- PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
- if (!pguidContainerFormat) return E_INVALIDARG;
- memcpy(pguidContainerFormat, &This->decoder_info.block_format, sizeof(GUID));
- return S_OK;
-}
-
-static HRESULT WINAPI PngDecoder_Block_GetCount(IWICMetadataBlockReader *iface,
- UINT *pcCount)
-{
- PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
-
- TRACE("%p,%p\n", iface, pcCount);
-
- if (!pcCount) return E_INVALIDARG;
-
- *pcCount = This->metadata_count;
-
- return S_OK;
-}
-
-static HRESULT WINAPI PngDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
- UINT nIndex, IWICMetadataReader **ppIMetadataReader)
-{
- PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
- HRESULT hr;
- IWICComponentFactory* factory;
- IWICStream* stream;
-
- TRACE("%p,%d,%p\n", iface, nIndex, ppIMetadataReader);
-
- if (nIndex >= This->metadata_count || !ppIMetadataReader)
- return E_INVALIDARG;
-
- hr = StreamImpl_Create(&stream);
-
- if (SUCCEEDED(hr))
- {
- ULARGE_INTEGER offset, length;
-
- offset.QuadPart = This->metadata_blocks[nIndex].offset;
- length.QuadPart = This->metadata_blocks[nIndex].length;
- hr = IWICStream_InitializeFromIStreamRegion(stream, This->stream,
- offset, length);
-
- if (SUCCEEDED(hr))
- hr = ImagingFactory_CreateInstance(&IID_IWICComponentFactory, (void**)&factory);
-
- if (SUCCEEDED(hr))
- {
- hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
- &GUID_ContainerFormatPng, NULL, This->metadata_blocks[nIndex].options,
- (IStream*)stream, ppIMetadataReader);
-
- IWICComponentFactory_Release(factory);
- }
-
- IWICStream_Release(stream);
- }
-
- if (FAILED(hr))
- *ppIMetadataReader = NULL;
-
- return S_OK;
-}
-
-static HRESULT WINAPI PngDecoder_Block_GetEnumerator(IWICMetadataBlockReader *iface,
- IEnumUnknown **ppIEnumMetadata)
-{
- FIXME("%p,%p\n", iface, ppIEnumMetadata);
- return E_NOTIMPL;
-}
-
-static const IWICMetadataBlockReaderVtbl PngDecoder_BlockVtbl = {
- PngDecoder_Block_QueryInterface,
- PngDecoder_Block_AddRef,
- PngDecoder_Block_Release,
- PngDecoder_Block_GetContainerFormat,
- PngDecoder_Block_GetCount,
- PngDecoder_Block_GetReaderByIndex,
- PngDecoder_Block_GetEnumerator,
-};
-
-HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv)
-{
- PngDecoder *This;
- HRESULT ret;
-
- TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
-
- *ppv = NULL;
-
- if (!load_libpng())
- {
- ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG);
- return E_FAIL;
- }
-
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngDecoder));
- if (!This) return E_OUTOFMEMORY;
-
- ret = get_unix_decoder(&CLSID_WICPngDecoder, &This->decoder_info, &This->png_decoder);
- if (FAILED(ret))
- {
- HeapFree(GetProcessHeap(), 0, This);
- return ret;
- }
-
- This->IWICBitmapDecoder_iface.lpVtbl = &PngDecoder_Vtbl;
- This->IWICBitmapFrameDecode_iface.lpVtbl = &PngDecoder_FrameVtbl;
- This->IWICMetadataBlockReader_iface.lpVtbl = &PngDecoder_BlockVtbl;
- This->ref = 1;
- This->png_ptr = NULL;
- This->info_ptr = NULL;
- This->end_info = NULL;
- This->stream = NULL;
- This->initialized = FALSE;
- This->image_bits = NULL;
- InitializeCriticalSection(&This->lock);
- This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngDecoder.lock");
- This->metadata_count = 0;
- This->metadata_blocks = NULL;
-
- ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
- IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
-
- return ret;
-}
-
struct png_pixelformat {
const WICPixelFormatGUID *guid;
UINT bpp;
@@ -2034,12 +1245,6 @@ HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv)
#else /* !SONAME_LIBPNG */
-HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv)
-{
- ERR("Trying to load PNG picture, but PNG support is not compiled in.\n");
- return E_FAIL;
-}
-
HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv)
{
ERR("Trying to save PNG picture, but PNG support is not compiled in.\n");
@@ -2047,3 +1252,18 @@ HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv)
}
#endif
+
+HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv)
+{
+ HRESULT hr;
+ struct decoder *decoder;
+ struct decoder_info decoder_info;
+
+ hr = get_unix_decoder(&CLSID_WICPngDecoder, &decoder_info, &decoder);
+
+ if (SUCCEEDED(hr))
+ hr = CommonDecoder_CreateInstance(decoder, &decoder_info, iid, ppv);
+
+ return hr;
+}
+
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index e5294b8cf1a..2cdd1066eb7 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -343,4 +343,7 @@ struct unix_funcs
HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
+extern HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
+ const struct decoder_info *decoder_info, REFIID iid, void** ppv) DECLSPEC_HIDDEN;
+
#endif /* WINCODECS_PRIVATE_H */
--
2.17.1
1
0
This isn't necessary because we do not use libpng to read metadata
or verify checksums. If this happens to be the last thing we do,
it will fail the pngformat tests which do not expect us to return
with the stream seeked to the end of the file.
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index 36151e94f1b..f101935211c 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -61,7 +61,6 @@ MAKE_FUNCPTR(png_get_io_ptr);
MAKE_FUNCPTR(png_get_pHYs);
MAKE_FUNCPTR(png_get_PLTE);
MAKE_FUNCPTR(png_get_tRNS);
-MAKE_FUNCPTR(png_read_end);
MAKE_FUNCPTR(png_read_image);
MAKE_FUNCPTR(png_read_info);
MAKE_FUNCPTR(png_set_bgr);
@@ -111,7 +110,6 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_get_pHYs);
LOAD_FUNCPTR(png_get_PLTE);
LOAD_FUNCPTR(png_get_tRNS);
- LOAD_FUNCPTR(png_read_end);
LOAD_FUNCPTR(png_read_image);
LOAD_FUNCPTR(png_read_info);
LOAD_FUNCPTR(png_set_bgr);
@@ -183,7 +181,6 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
struct png_decoder *This = impl_from_decoder(iface);
png_structp png_ptr;
png_infop info_ptr;
- png_infop end_info;
jmp_buf jmpbuf;
HRESULT hr = E_FAIL;
int color_type, bit_depth;
@@ -216,13 +213,6 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
return E_FAIL;
}
- end_info = ppng_create_info_struct(png_ptr);
- if (!end_info)
- {
- ppng_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- return E_FAIL;
- }
-
/* set up setjmp/longjmp error handling */
if (setjmp(jmpbuf))
{
@@ -443,7 +433,7 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
free(row_pointers);
row_pointers = NULL;
- ppng_read_end(png_ptr, end_info);
+ /* png_read_end intentionally not called to not seek to the end of the file */
st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
WICBitmapDecoderCapabilityCanDecodeSomeImages |
@@ -455,7 +445,7 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
hr = S_OK;
end:
- ppng_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ ppng_destroy_read_struct(&png_ptr, &info_ptr, NULL);
free(row_pointers);
if (FAILED(hr))
{
--
2.17.1
1
0
Oct. 9, 2020
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 45 ++++++++++++++++++++++++++
dlls/windowscodecs/pngformat.c | 35 +++++++++-----------
dlls/windowscodecs/unix_iface.c | 8 +++++
dlls/windowscodecs/unix_lib.c | 1 +
dlls/windowscodecs/wincodecs_common.h | 6 ++++
dlls/windowscodecs/wincodecs_private.h | 7 ++++
6 files changed, 83 insertions(+), 19 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index 8a4db91f2a9..36151e94f1b 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -54,6 +54,7 @@ MAKE_FUNCPTR(png_error);
MAKE_FUNCPTR(png_get_bit_depth);
MAKE_FUNCPTR(png_get_color_type);
MAKE_FUNCPTR(png_get_error_ptr);
+MAKE_FUNCPTR(png_get_iCCP);
MAKE_FUNCPTR(png_get_image_height);
MAKE_FUNCPTR(png_get_image_width);
MAKE_FUNCPTR(png_get_io_ptr);
@@ -105,6 +106,7 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_get_error_ptr);
LOAD_FUNCPTR(png_get_image_height);
LOAD_FUNCPTR(png_get_image_width);
+ LOAD_FUNCPTR(png_get_iCCP);
LOAD_FUNCPTR(png_get_io_ptr);
LOAD_FUNCPTR(png_get_pHYs);
LOAD_FUNCPTR(png_get_PLTE);
@@ -137,6 +139,8 @@ struct png_decoder
struct decoder_frame decoder_frame;
UINT stride;
BYTE *image_bits;
+ BYTE *color_profile;
+ DWORD color_profile_len;
};
static inline struct png_decoder *impl_from_decoder(struct decoder* iface)
@@ -194,6 +198,10 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
int i;
UINT image_size;
png_bytep *row_pointers=NULL;
+ png_charp cp_name;
+ png_bytep cp_profile;
+ png_uint_32 cp_len;
+ int cp_compression;
png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
@@ -351,6 +359,22 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
This->decoder_frame.dpix = This->decoder_frame.dpiy = 96.0;
}
+ ret = ppng_get_iCCP(png_ptr, info_ptr, &cp_name, &cp_compression, &cp_profile, &cp_len);
+ if (ret)
+ {
+ This->decoder_frame.num_color_contexts = 1;
+ This->color_profile_len = cp_len;
+ This->color_profile = malloc(cp_len);
+ if (!This->color_profile)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+ memcpy(This->color_profile, cp_profile, cp_len);
+ }
+ else
+ This->decoder_frame.num_color_contexts = 0;
+
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
ret = ppng_get_PLTE(png_ptr, info_ptr, &png_palette, &num_palette);
@@ -437,6 +461,8 @@ end:
{
free(This->image_bits);
This->image_bits = NULL;
+ free(This->color_profile);
+ This->color_profile = NULL;
}
return hr;
}
@@ -531,11 +557,28 @@ end:
return hr;
}
+HRESULT CDECL png_decoder_get_color_context(struct decoder* iface, UINT frame, UINT num,
+ BYTE **data, DWORD *datasize)
+{
+ struct png_decoder *This = impl_from_decoder(iface);
+
+ *data = RtlAllocateHeap(GetProcessHeap(), 0, This->color_profile_len);
+ *datasize = This->color_profile_len;
+
+ if (!*data)
+ return E_OUTOFMEMORY;
+
+ memcpy(*data, This->color_profile, This->color_profile_len);
+
+ return S_OK;
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
free(This->image_bits);
+ free(This->color_profile);
RtlFreeHeap(GetProcessHeap(), 0, This);
}
@@ -544,6 +587,7 @@ static const struct decoder_funcs png_decoder_vtable = {
png_decoder_get_frame_info,
png_decoder_copy_pixels,
png_decoder_get_metadata_blocks,
+ png_decoder_get_color_context,
png_decoder_destroy
};
@@ -566,6 +610,7 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
This->decoder.vtable = &png_decoder_vtable;
This->image_bits = NULL;
+ This->color_profile = NULL;
*result = &This->decoder;
info->container_format = GUID_ContainerFormatPng;
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 1d696a4fe01..efd5f6ab2c1 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -976,37 +976,34 @@ static HRESULT WINAPI PngDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *i
UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- png_charp name;
+ HRESULT hr=S_OK;
BYTE *profile;
- png_uint_32 len;
- int compression_type;
- HRESULT hr;
+ DWORD profile_len;
TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
if (!pcActualCount) return E_INVALIDARG;
- EnterCriticalSection(&This->lock);
+ *pcActualCount = This->decoder_frame.num_color_contexts;
- if (ppng_get_iCCP(This->png_ptr, This->info_ptr, &name, &compression_type, (void *)&profile, &len))
+ if (This->decoder_frame.num_color_contexts && cCount && ppIColorContexts)
{
- if (cCount && ppIColorContexts)
+ EnterCriticalSection(&This->lock);
+
+ hr = decoder_get_color_context(This->png_decoder, 0, 0,
+ &profile, &profile_len);
+
+ LeaveCriticalSection(&This->lock);
+
+ if (SUCCEEDED(hr))
{
- hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, len);
- if (FAILED(hr))
- {
- LeaveCriticalSection(&This->lock);
- return hr;
- }
+ hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, profile_len);
+
+ HeapFree(GetProcessHeap(), 0, profile);
}
- *pcActualCount = 1;
}
- else
- *pcActualCount = 0;
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
+ return hr;
}
static HRESULT WINAPI PngDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface,
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index 8d22b49ba22..cdc92a7d160 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -92,6 +92,13 @@ HRESULT CDECL decoder_wrapper_get_metadata_blocks(struct decoder* iface,
return unix_funcs->decoder_get_metadata_blocks(This->unix_decoder, frame, count, blocks);
}
+HRESULT CDECL decoder_wrapper_get_color_context(struct decoder* iface,
+ UINT frame, UINT num, BYTE **data, DWORD *datasize)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_get_color_context(This->unix_decoder, frame, num, data, datasize);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -104,6 +111,7 @@ static const struct decoder_funcs decoder_wrapper_vtable = {
decoder_wrapper_get_frame_info,
decoder_wrapper_copy_pixels,
decoder_wrapper_get_metadata_blocks,
+ decoder_wrapper_get_color_context,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 58c68018430..217a5a2e63a 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -71,6 +71,7 @@ static const struct unix_funcs unix_funcs = {
decoder_get_frame_info,
decoder_copy_pixels,
decoder_get_metadata_blocks,
+ decoder_get_color_context,
decoder_destroy
};
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index 5489a055a27..b5d7b645638 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -37,6 +37,12 @@ HRESULT CDECL decoder_get_metadata_blocks(struct decoder *decoder, UINT frame, U
return decoder->vtable->get_metadata_blocks(decoder, frame, count, blocks);
}
+HRESULT CDECL decoder_get_color_context(struct decoder *decoder, UINT frame,
+ UINT num, BYTE **data, DWORD *datasize)
+{
+ return decoder->vtable->get_color_context(decoder, frame, num, data, datasize);
+}
+
void CDECL decoder_destroy(struct decoder *decoder)
{
decoder->vtable->destroy(decoder);
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 3c0b73e893f..e5294b8cf1a 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -275,6 +275,7 @@ struct decoder_frame
UINT width, height;
UINT bpp;
double dpix, dpiy;
+ DWORD num_color_contexts;
DWORD num_colors;
WICColor palette[256];
};
@@ -299,6 +300,8 @@ struct decoder_funcs
UINT stride, UINT buffersize, BYTE *buffer);
HRESULT (CDECL *get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count,
struct decoder_block **blocks);
+ HRESULT (CDECL *get_color_context)(struct decoder* This, UINT frame, UINT num,
+ BYTE **data, DWORD *datasize);
void (CDECL *destroy)(struct decoder* This);
};
@@ -318,6 +321,8 @@ HRESULT CDECL decoder_copy_pixels(struct decoder* This, UINT frame, const WICRec
UINT stride, UINT buffersize, BYTE *buffer);
HRESULT CDECL decoder_get_metadata_blocks(struct decoder* This, UINT frame, UINT *count,
struct decoder_block **blocks);
+HRESULT CDECL decoder_get_color_context(struct decoder* This, UINT frame, UINT num,
+ BYTE **data, DWORD *datasize);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -331,6 +336,8 @@ struct unix_funcs
UINT stride, UINT buffersize, BYTE *buffer);
HRESULT (CDECL *decoder_get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count,
struct decoder_block **blocks);
+ HRESULT (CDECL *decoder_get_color_context)(struct decoder* This, UINT frame, UINT num,
+ BYTE **data, DWORD *datasize);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0
Oct. 9, 2020
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 77 +++++++++++++
dlls/windowscodecs/main.c | 1 +
dlls/windowscodecs/pngformat.c | 143 ++++---------------------
dlls/windowscodecs/unix_iface.c | 8 ++
dlls/windowscodecs/unix_lib.c | 1 +
dlls/windowscodecs/wincodecs_common.h | 51 +++++++++
dlls/windowscodecs/wincodecs_private.h | 15 +++
7 files changed, 174 insertions(+), 122 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index 397d2d371ef..8a4db91f2a9 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -133,6 +133,7 @@ static void *load_libpng(void)
struct png_decoder
{
struct decoder decoder;
+ IStream *stream;
struct decoder_frame decoder_frame;
UINT stride;
BYTE *image_bits;
@@ -425,6 +426,8 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
WICBitmapDecoderCapabilityCanEnumerateMetadata;
st->frame_count = 1;
+ This->stream = stream;
+
hr = S_OK;
end:
@@ -455,6 +458,79 @@ HRESULT CDECL png_decoder_copy_pixels(struct decoder *iface, UINT frame,
prc, stride, buffersize, buffer);
}
+HRESULT CDECL png_decoder_get_metadata_blocks(struct decoder* iface,
+ UINT frame, UINT *count, struct decoder_block **blocks)
+{
+ struct png_decoder *This = impl_from_decoder(iface);
+ HRESULT hr;
+ struct decoder_block *result = NULL;
+ ULONGLONG seek;
+ BYTE chunk_type[4];
+ ULONG chunk_size;
+ ULONGLONG chunk_start;
+ ULONG metadata_blocks_size = 0;
+
+ seek = 8;
+ *count = 0;
+
+ do
+ {
+ hr = stream_seek(This->stream, seek, STREAM_SEEK_SET, &chunk_start);
+ if (FAILED(hr)) goto end;
+
+ hr = read_png_chunk(This->stream, chunk_type, NULL, &chunk_size);
+ if (FAILED(hr)) goto end;
+
+ if (chunk_type[0] >= 'a' && chunk_type[0] <= 'z' &&
+ memcmp(chunk_type, "tRNS", 4) && memcmp(chunk_type, "pHYs", 4))
+ {
+ /* This chunk is considered metadata. */
+ if (*count == metadata_blocks_size)
+ {
+ struct decoder_block *new_metadata_blocks;
+ ULONG new_metadata_blocks_size;
+
+ new_metadata_blocks_size = 4 + metadata_blocks_size * 2;
+ new_metadata_blocks = RtlAllocateHeap(GetProcessHeap(), 0,
+ new_metadata_blocks_size * sizeof(*new_metadata_blocks));
+
+ if (!new_metadata_blocks)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ memcpy(new_metadata_blocks, result,
+ *count * sizeof(*new_metadata_blocks));
+
+ RtlFreeHeap(GetProcessHeap(), 0, result);
+ result = new_metadata_blocks;
+ metadata_blocks_size = new_metadata_blocks_size;
+ }
+
+ result[*count].offset = chunk_start;
+ result[*count].length = chunk_size + 12;
+ result[*count].options = WICMetadataCreationAllowUnknown;
+ (*count)++;
+ }
+
+ seek = chunk_start + chunk_size + 12; /* skip data and CRC */
+ } while (memcmp(chunk_type, "IEND", 4));
+
+end:
+ if (SUCCEEDED(hr))
+ {
+ *blocks = result;
+ }
+ else
+ {
+ *count = 0;
+ *blocks = NULL;
+ RtlFreeHeap(GetProcessHeap(), 0, result);
+ }
+ return hr;
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
@@ -467,6 +543,7 @@ static const struct decoder_funcs png_decoder_vtable = {
png_decoder_initialize,
png_decoder_get_frame_info,
png_decoder_copy_pixels,
+ png_decoder_get_metadata_blocks,
png_decoder_destroy
};
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 982c8ddfada..4dcc146d6c8 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -24,6 +24,7 @@
#include "windef.h"
#include "winbase.h"
+#include "winternl.h"
#include "objbase.h"
#include "wincodecs_private.h"
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 834cc81d306..1d696a4fe01 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -44,47 +44,6 @@ static inline ULONG read_ulong_be(BYTE* data)
return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
}
-static HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size)
-{
- BYTE header[8];
- HRESULT hr;
- ULONG bytesread;
-
- hr = IStream_Read(stream, header, 8, &bytesread);
- if (FAILED(hr) || bytesread < 8)
- {
- if (SUCCEEDED(hr))
- hr = E_FAIL;
- return hr;
- }
-
- *data_size = read_ulong_be(&header[0]);
-
- memcpy(type, &header[4], 4);
-
- if (data)
- {
- *data = HeapAlloc(GetProcessHeap(), 0, *data_size);
- if (!*data)
- return E_OUTOFMEMORY;
-
- hr = IStream_Read(stream, *data, *data_size, &bytesread);
-
- if (FAILED(hr) || bytesread < *data_size)
- {
- if (SUCCEEDED(hr))
- hr = E_FAIL;
- HeapFree(GetProcessHeap(), 0, *data);
- *data = NULL;
- return hr;
- }
-
- /* Windows ignores CRC of the chunk */
- }
-
- return S_OK;
-}
-
static HRESULT LoadTextMetadata(IStream *stream, const GUID *preferred_vendor,
DWORD persist_options, MetadataItem **items, DWORD *item_count)
{
@@ -459,7 +418,7 @@ typedef struct {
BYTE *image_bits;
CRITICAL_SECTION lock; /* must be held when png structures are accessed or initialized is set */
ULONG metadata_count;
- metadata_block_info* metadata_blocks;
+ struct decoder_block* metadata_blocks;
} PngDecoder;
static inline PngDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
@@ -515,7 +474,6 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
{
PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- ULONG i;
TRACE("(%p) refcount=%u\n", iface, ref);
@@ -530,11 +488,6 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock);
HeapFree(GetProcessHeap(), 0, This->image_bits);
- for (i=0; i<This->metadata_count; i++)
- {
- if (This->metadata_blocks[i].reader)
- IWICMetadataReader_Release(This->metadata_blocks[i].reader);
- }
HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -587,10 +540,6 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
png_uint_32 transparency;
png_color_16p trans_values;
jmp_buf jmpbuf;
- BYTE chunk_type[4];
- ULONG chunk_size;
- ULARGE_INTEGER chunk_start;
- ULONG metadata_blocks_size = 0;
TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
@@ -783,52 +732,7 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
ppng_read_end(This->png_ptr, This->end_info);
- /* Find the metadata chunks in the file. */
- seek.QuadPart = 8;
-
- do
- {
- hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start);
- if (FAILED(hr)) goto end;
-
- hr = read_png_chunk(pIStream, chunk_type, NULL, &chunk_size);
- if (FAILED(hr)) goto end;
-
- if (chunk_type[0] >= 'a' && chunk_type[0] <= 'z' &&
- memcmp(chunk_type, "tRNS", 4) && memcmp(chunk_type, "pHYs", 4))
- {
- /* This chunk is considered metadata. */
- if (This->metadata_count == metadata_blocks_size)
- {
- metadata_block_info* new_metadata_blocks;
- ULONG new_metadata_blocks_size;
-
- new_metadata_blocks_size = 4 + metadata_blocks_size * 2;
- new_metadata_blocks = HeapAlloc(GetProcessHeap(), 0,
- new_metadata_blocks_size * sizeof(*new_metadata_blocks));
-
- if (!new_metadata_blocks)
- {
- hr = E_OUTOFMEMORY;
- goto end;
- }
-
- memcpy(new_metadata_blocks, This->metadata_blocks,
- This->metadata_count * sizeof(*new_metadata_blocks));
-
- HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
- This->metadata_blocks = new_metadata_blocks;
- metadata_blocks_size = new_metadata_blocks_size;
- }
-
- This->metadata_blocks[This->metadata_count].ofs = chunk_start;
- This->metadata_blocks[This->metadata_count].len.QuadPart = chunk_size + 12;
- This->metadata_blocks[This->metadata_count].reader = NULL;
- This->metadata_count++;
- }
-
- seek.QuadPart = chunk_start.QuadPart + chunk_size + 12; /* skip data and CRC */
- } while (memcmp(chunk_type, "IEND", 4));
+ decoder_get_metadata_blocks(This->png_decoder, 0, &This->metadata_count, &This->metadata_blocks);
This->stream = pIStream;
IStream_AddRef(This->stream);
@@ -1185,39 +1089,34 @@ static HRESULT WINAPI PngDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader
if (nIndex >= This->metadata_count || !ppIMetadataReader)
return E_INVALIDARG;
- if (!This->metadata_blocks[nIndex].reader)
- {
- hr = StreamImpl_Create(&stream);
+ hr = StreamImpl_Create(&stream);
- if (SUCCEEDED(hr))
- {
- hr = IWICStream_InitializeFromIStreamRegion(stream, This->stream,
- This->metadata_blocks[nIndex].ofs, This->metadata_blocks[nIndex].len);
+ if (SUCCEEDED(hr))
+ {
+ ULARGE_INTEGER offset, length;
- if (SUCCEEDED(hr))
- hr = ImagingFactory_CreateInstance(&IID_IWICComponentFactory, (void**)&factory);
+ offset.QuadPart = This->metadata_blocks[nIndex].offset;
+ length.QuadPart = This->metadata_blocks[nIndex].length;
+ hr = IWICStream_InitializeFromIStreamRegion(stream, This->stream,
+ offset, length);
- if (SUCCEEDED(hr))
- {
- hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
- &GUID_ContainerFormatPng, NULL, WICMetadataCreationAllowUnknown,
- (IStream*)stream, &This->metadata_blocks[nIndex].reader);
+ if (SUCCEEDED(hr))
+ hr = ImagingFactory_CreateInstance(&IID_IWICComponentFactory, (void**)&factory);
- IWICComponentFactory_Release(factory);
- }
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
+ &GUID_ContainerFormatPng, NULL, This->metadata_blocks[nIndex].options,
+ (IStream*)stream, ppIMetadataReader);
- IWICStream_Release(stream);
+ IWICComponentFactory_Release(factory);
}
- if (FAILED(hr))
- {
- *ppIMetadataReader = NULL;
- return hr;
- }
+ IWICStream_Release(stream);
}
- *ppIMetadataReader = This->metadata_blocks[nIndex].reader;
- IWICMetadataReader_AddRef(*ppIMetadataReader);
+ if (FAILED(hr))
+ *ppIMetadataReader = NULL;
return S_OK;
}
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index 46bcacff941..8d22b49ba22 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -85,6 +85,13 @@ HRESULT CDECL decoder_wrapper_copy_pixels(struct decoder* iface, UINT frame,
return unix_funcs->decoder_copy_pixels(This->unix_decoder, frame, prc, stride, buffersize, buffer);
}
+HRESULT CDECL decoder_wrapper_get_metadata_blocks(struct decoder* iface,
+ UINT frame, UINT *count, struct decoder_block **blocks)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_get_metadata_blocks(This->unix_decoder, frame, count, blocks);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -96,6 +103,7 @@ static const struct decoder_funcs decoder_wrapper_vtable = {
decoder_wrapper_initialize,
decoder_wrapper_get_frame_info,
decoder_wrapper_copy_pixels,
+ decoder_wrapper_get_metadata_blocks,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 5ab1cb342e6..58c68018430 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -70,6 +70,7 @@ static const struct unix_funcs unix_funcs = {
decoder_initialize,
decoder_get_frame_info,
decoder_copy_pixels,
+ decoder_get_metadata_blocks,
decoder_destroy
};
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index f116fb6fd8f..5489a055a27 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -32,6 +32,11 @@ HRESULT CDECL decoder_copy_pixels(struct decoder *decoder, UINT frame,
return decoder->vtable->copy_pixels(decoder, frame, prc, stride, buffersize, buffer);
}
+HRESULT CDECL decoder_get_metadata_blocks(struct decoder *decoder, UINT frame, UINT *count, struct decoder_block **blocks)
+{
+ return decoder->vtable->get_metadata_blocks(decoder, frame, count, blocks);
+}
+
void CDECL decoder_destroy(struct decoder *decoder)
{
decoder->vtable->destroy(decoder);
@@ -102,3 +107,49 @@ HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
}
}
+static inline ULONG read_ulong_be(BYTE* data)
+{
+ return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+}
+
+HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size)
+{
+ BYTE header[8];
+ HRESULT hr;
+ ULONG bytesread;
+
+ hr = stream_read(stream, header, 8, &bytesread);
+ if (FAILED(hr) || bytesread < 8)
+ {
+ if (SUCCEEDED(hr))
+ hr = E_FAIL;
+ return hr;
+ }
+
+ *data_size = read_ulong_be(&header[0]);
+
+ memcpy(type, &header[4], 4);
+
+ if (data)
+ {
+ *data = RtlAllocateHeap(GetProcessHeap(), 0, *data_size);
+ if (!*data)
+ return E_OUTOFMEMORY;
+
+ hr = stream_read(stream, *data, *data_size, &bytesread);
+
+ if (FAILED(hr) || bytesread < *data_size)
+ {
+ if (SUCCEEDED(hr))
+ hr = E_FAIL;
+ RtlFreeHeap(GetProcessHeap(), 0, *data);
+ *data = NULL;
+ return hr;
+ }
+
+ /* Windows ignores CRC of the chunk */
+ }
+
+ return S_OK;
+}
+
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 24cae3652f4..3c0b73e893f 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -249,6 +249,8 @@ static inline const char *debug_wic_rect(const WICRect *rect)
HMODULE windowscodecs_module;
+HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size);
+
/* unixlib iface */
struct decoder_funcs;
@@ -277,6 +279,13 @@ struct decoder_frame
WICColor palette[256];
};
+struct decoder_block
+{
+ ULONGLONG offset;
+ ULONGLONG length;
+ DWORD options;
+};
+
struct decoder
{
const struct decoder_funcs *vtable;
@@ -288,6 +297,8 @@ struct decoder_funcs
HRESULT (CDECL *get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
HRESULT (CDECL *copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
UINT stride, UINT buffersize, BYTE *buffer);
+ HRESULT (CDECL *get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count,
+ struct decoder_block **blocks);
void (CDECL *destroy)(struct decoder* This);
};
@@ -305,6 +316,8 @@ HRESULT CDECL decoder_initialize(struct decoder *This, IStream *stream, struct d
HRESULT CDECL decoder_get_frame_info(struct decoder* This, UINT frame, struct decoder_frame *info);
HRESULT CDECL decoder_copy_pixels(struct decoder* This, UINT frame, const WICRect *prc,
UINT stride, UINT buffersize, BYTE *buffer);
+HRESULT CDECL decoder_get_metadata_blocks(struct decoder* This, UINT frame, UINT *count,
+ struct decoder_block **blocks);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -316,6 +329,8 @@ struct unix_funcs
HRESULT (CDECL *decoder_get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
HRESULT (CDECL *decoder_copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
UINT stride, UINT buffersize, BYTE *buffer);
+ HRESULT (CDECL *decoder_get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count,
+ struct decoder_block **blocks);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0
Oct. 9, 2020
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 54 ++++++++++++++++++++
dlls/windowscodecs/main.c | 65 -----------------------
dlls/windowscodecs/pngformat.c | 3 +-
dlls/windowscodecs/unix_iface.c | 8 +++
dlls/windowscodecs/unix_lib.c | 3 ++
dlls/windowscodecs/wincodecs_common.h | 71 ++++++++++++++++++++++++++
dlls/windowscodecs/wincodecs_private.h | 6 +++
7 files changed, 143 insertions(+), 67 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index bed7ea72d65..397d2d371ef 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -60,6 +60,8 @@ MAKE_FUNCPTR(png_get_io_ptr);
MAKE_FUNCPTR(png_get_pHYs);
MAKE_FUNCPTR(png_get_PLTE);
MAKE_FUNCPTR(png_get_tRNS);
+MAKE_FUNCPTR(png_read_end);
+MAKE_FUNCPTR(png_read_image);
MAKE_FUNCPTR(png_read_info);
MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_set_crc_action);
@@ -107,6 +109,8 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_get_pHYs);
LOAD_FUNCPTR(png_get_PLTE);
LOAD_FUNCPTR(png_get_tRNS);
+ LOAD_FUNCPTR(png_read_end);
+ LOAD_FUNCPTR(png_read_image);
LOAD_FUNCPTR(png_read_info);
LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_set_crc_action);
@@ -130,6 +134,8 @@ struct png_decoder
{
struct decoder decoder;
struct decoder_frame decoder_frame;
+ UINT stride;
+ BYTE *image_bits;
};
static inline struct png_decoder *impl_from_decoder(struct decoder* iface)
@@ -185,6 +191,8 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
png_colorp png_palette;
int num_palette;
int i;
+ UINT image_size;
+ png_bytep *row_pointers=NULL;
png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
@@ -385,6 +393,33 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
This->decoder_frame.num_colors = 0;
}
+ This->stride = (This->decoder_frame.width * This->decoder_frame.bpp + 7) / 8;
+ image_size = This->stride * This->decoder_frame.height;
+
+ This->image_bits = malloc(image_size);
+ if (!This->image_bits)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ row_pointers = malloc(sizeof(png_bytep)*This->decoder_frame.height);
+ if (!row_pointers)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ for (i=0; i<This->decoder_frame.height; i++)
+ row_pointers[i] = This->image_bits + i * This->stride;
+
+ ppng_read_image(png_ptr, row_pointers);
+
+ free(row_pointers);
+ row_pointers = NULL;
+
+ ppng_read_end(png_ptr, end_info);
+
st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
WICBitmapDecoderCapabilityCanDecodeSomeImages |
WICBitmapDecoderCapabilityCanEnumerateMetadata;
@@ -394,6 +429,12 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
end:
ppng_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ free(row_pointers);
+ if (FAILED(hr))
+ {
+ free(This->image_bits);
+ This->image_bits = NULL;
+ }
return hr;
}
@@ -404,16 +445,28 @@ HRESULT CDECL png_decoder_get_frame_info(struct decoder *iface, UINT frame, stru
return S_OK;
}
+HRESULT CDECL png_decoder_copy_pixels(struct decoder *iface, UINT frame,
+ const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+ struct png_decoder *This = impl_from_decoder(iface);
+
+ return copy_pixels(This->decoder_frame.bpp, This->image_bits,
+ This->decoder_frame.width, This->decoder_frame.height, This->stride,
+ prc, stride, buffersize, buffer);
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
+ free(This->image_bits);
RtlFreeHeap(GetProcessHeap(), 0, This);
}
static const struct decoder_funcs png_decoder_vtable = {
png_decoder_initialize,
png_decoder_get_frame_info,
+ png_decoder_copy_pixels,
png_decoder_destroy
};
@@ -435,6 +488,7 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
}
This->decoder.vtable = &png_decoder_vtable;
+ This->image_bits = NULL;
*result = &This->decoder;
info->container_format = GUID_ContainerFormatPng;
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 2d8b0336f3f..982c8ddfada 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -60,71 +60,6 @@ HRESULT WINAPI DllCanUnloadNow(void)
return S_FALSE;
}
-HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
- UINT srcwidth, UINT srcheight, INT srcstride,
- const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
-{
- UINT bytesperrow;
- UINT row_offset; /* number of bits into the source rows where the data starts */
- WICRect rect;
-
- if (!rc)
- {
- rect.X = 0;
- rect.Y = 0;
- rect.Width = srcwidth;
- rect.Height = srcheight;
- rc = ▭
- }
- else
- {
- if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
- return E_INVALIDARG;
- }
-
- bytesperrow = ((bpp * rc->Width)+7)/8;
-
- if (dststride < bytesperrow)
- return E_INVALIDARG;
-
- if ((dststride * (rc->Height-1)) + bytesperrow > dstbuffersize)
- return E_INVALIDARG;
-
- /* if the whole bitmap is copied and the buffer format matches then it's a matter of a single memcpy */
- if (rc->X == 0 && rc->Y == 0 && rc->Width == srcwidth && rc->Height == srcheight &&
- srcstride == dststride && srcstride == bytesperrow)
- {
- memcpy(dstbuffer, srcbuffer, srcstride * srcheight);
- return S_OK;
- }
-
- row_offset = rc->X * bpp;
-
- if (row_offset % 8 == 0)
- {
- /* everything lines up on a byte boundary */
- INT row;
- const BYTE *src;
- BYTE *dst;
-
- src = srcbuffer + (row_offset / 8) + srcstride * rc->Y;
- dst = dstbuffer;
- for (row=0; row < rc->Height; row++)
- {
- memcpy(dst, src, bytesperrow);
- src += srcstride;
- dst += dststride;
- }
- return S_OK;
- }
- else
- {
- /* we have to do a weird bitwise copy. eww. */
- FIXME("cannot reliably copy bitmap data if bpp < 8\n");
- return E_FAIL;
- }
-}
-
HRESULT configure_write_source(IWICBitmapFrameEncode *iface,
IWICBitmapSource *source, const WICRect *prc,
const WICPixelFormatGUID *format,
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index d10afcedbc3..834cc81d306 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -1051,8 +1051,7 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
- return copy_pixels(This->bpp, This->image_bits,
- This->width, This->height, This->stride,
+ return decoder_copy_pixels(This->png_decoder, 0,
prc, cbStride, cbBufferSize, pbBuffer);
}
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index cf66fbd964d..46bcacff941 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -78,6 +78,13 @@ HRESULT CDECL decoder_wrapper_get_frame_info(struct decoder* iface, UINT frame,
return unix_funcs->decoder_get_frame_info(This->unix_decoder, frame, info);
}
+HRESULT CDECL decoder_wrapper_copy_pixels(struct decoder* iface, UINT frame,
+ const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_copy_pixels(This->unix_decoder, frame, prc, stride, buffersize, buffer);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -88,6 +95,7 @@ void CDECL decoder_wrapper_destroy(struct decoder* iface)
static const struct decoder_funcs decoder_wrapper_vtable = {
decoder_wrapper_initialize,
decoder_wrapper_get_frame_info,
+ decoder_wrapper_copy_pixels,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 111a82dc637..5ab1cb342e6 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -41,6 +41,8 @@
#include "wine/debug.h"
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
#include "wincodecs_common.h"
static const struct win32_funcs *win32_funcs;
@@ -67,6 +69,7 @@ static const struct unix_funcs unix_funcs = {
decoder_create,
decoder_initialize,
decoder_get_frame_info,
+ decoder_copy_pixels,
decoder_destroy
};
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index ac8ae015c76..f116fb6fd8f 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -26,8 +26,79 @@ HRESULT CDECL decoder_get_frame_info(struct decoder *decoder, UINT frame, struct
return decoder->vtable->get_frame_info(decoder, frame, info);
}
+HRESULT CDECL decoder_copy_pixels(struct decoder *decoder, UINT frame,
+ const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+ return decoder->vtable->copy_pixels(decoder, frame, prc, stride, buffersize, buffer);
+}
+
void CDECL decoder_destroy(struct decoder *decoder)
{
decoder->vtable->destroy(decoder);
}
+HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
+ UINT srcwidth, UINT srcheight, INT srcstride,
+ const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
+{
+ UINT bytesperrow;
+ UINT row_offset; /* number of bits into the source rows where the data starts */
+ WICRect rect;
+
+ if (!rc)
+ {
+ rect.X = 0;
+ rect.Y = 0;
+ rect.Width = srcwidth;
+ rect.Height = srcheight;
+ rc = ▭
+ }
+ else
+ {
+ if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
+ return E_INVALIDARG;
+ }
+
+ bytesperrow = ((bpp * rc->Width)+7)/8;
+
+ if (dststride < bytesperrow)
+ return E_INVALIDARG;
+
+ if ((dststride * (rc->Height-1)) + bytesperrow > dstbuffersize)
+ return E_INVALIDARG;
+
+ /* if the whole bitmap is copied and the buffer format matches then it's a matter of a single memcpy */
+ if (rc->X == 0 && rc->Y == 0 && rc->Width == srcwidth && rc->Height == srcheight &&
+ srcstride == dststride && srcstride == bytesperrow)
+ {
+ memcpy(dstbuffer, srcbuffer, srcstride * srcheight);
+ return S_OK;
+ }
+
+ row_offset = rc->X * bpp;
+
+ if (row_offset % 8 == 0)
+ {
+ /* everything lines up on a byte boundary */
+ INT row;
+ const BYTE *src;
+ BYTE *dst;
+
+ src = srcbuffer + (row_offset / 8) + srcstride * rc->Y;
+ dst = dstbuffer;
+ for (row=0; row < rc->Height; row++)
+ {
+ memcpy(dst, src, bytesperrow);
+ src += srcstride;
+ dst += dststride;
+ }
+ return S_OK;
+ }
+ else
+ {
+ /* we have to do a weird bitwise copy. eww. */
+ FIXME("cannot reliably copy bitmap data if bpp < 8\n");
+ return E_FAIL;
+ }
+}
+
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 6d12b98bfc4..24cae3652f4 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -286,6 +286,8 @@ struct decoder_funcs
{
HRESULT (CDECL *initialize)(struct decoder* This, IStream *stream, struct decoder_stat *st);
HRESULT (CDECL *get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
+ HRESULT (CDECL *copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
+ UINT stride, UINT buffersize, BYTE *buffer);
void (CDECL *destroy)(struct decoder* This);
};
@@ -301,6 +303,8 @@ struct win32_funcs
HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT CDECL decoder_initialize(struct decoder *This, IStream *stream, struct decoder_stat *st);
HRESULT CDECL decoder_get_frame_info(struct decoder* This, UINT frame, struct decoder_frame *info);
+HRESULT CDECL decoder_copy_pixels(struct decoder* This, UINT frame, const WICRect *prc,
+ UINT stride, UINT buffersize, BYTE *buffer);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -310,6 +314,8 @@ struct unix_funcs
HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT (CDECL *decoder_initialize)(struct decoder *This, IStream *stream, struct decoder_stat *st);
HRESULT (CDECL *decoder_get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
+ HRESULT (CDECL *decoder_copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
+ UINT stride, UINT buffersize, BYTE *buffer);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0
Oct. 9, 2020
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 201 +++++++++++++++++++++++++
dlls/windowscodecs/pngformat.c | 96 ++----------
dlls/windowscodecs/unix_iface.c | 7 +
dlls/windowscodecs/unix_lib.c | 1 +
dlls/windowscodecs/wincodecs_common.h | 5 +
dlls/windowscodecs/wincodecs_private.h | 13 ++
6 files changed, 238 insertions(+), 85 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index f41ef765f9b..bed7ea72d65 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -1,4 +1,5 @@
/*
+ * Copyright 2016 Dmitry Timoshkov
* Copyright 2020 Esme Povirk
*
* This library is free software; you can redistribute it and/or
@@ -50,12 +51,23 @@ MAKE_FUNCPTR(png_create_info_struct);
MAKE_FUNCPTR(png_create_read_struct);
MAKE_FUNCPTR(png_destroy_read_struct);
MAKE_FUNCPTR(png_error);
+MAKE_FUNCPTR(png_get_bit_depth);
+MAKE_FUNCPTR(png_get_color_type);
MAKE_FUNCPTR(png_get_error_ptr);
+MAKE_FUNCPTR(png_get_image_height);
+MAKE_FUNCPTR(png_get_image_width);
MAKE_FUNCPTR(png_get_io_ptr);
+MAKE_FUNCPTR(png_get_pHYs);
+MAKE_FUNCPTR(png_get_PLTE);
+MAKE_FUNCPTR(png_get_tRNS);
MAKE_FUNCPTR(png_read_info);
+MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_set_crc_action);
MAKE_FUNCPTR(png_set_error_fn);
+MAKE_FUNCPTR(png_set_gray_to_rgb);
MAKE_FUNCPTR(png_set_read_fn);
+MAKE_FUNCPTR(png_set_swap);
+MAKE_FUNCPTR(png_set_tRNS_to_alpha);
#undef MAKE_FUNCPTR
static CRITICAL_SECTION init_png_cs;
@@ -86,12 +98,23 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_create_read_struct);
LOAD_FUNCPTR(png_destroy_read_struct);
LOAD_FUNCPTR(png_error);
+ LOAD_FUNCPTR(png_get_bit_depth);
+ LOAD_FUNCPTR(png_get_color_type);
LOAD_FUNCPTR(png_get_error_ptr);
+ LOAD_FUNCPTR(png_get_image_height);
+ LOAD_FUNCPTR(png_get_image_width);
LOAD_FUNCPTR(png_get_io_ptr);
+ LOAD_FUNCPTR(png_get_pHYs);
+ LOAD_FUNCPTR(png_get_PLTE);
+ LOAD_FUNCPTR(png_get_tRNS);
LOAD_FUNCPTR(png_read_info);
+ LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_set_crc_action);
LOAD_FUNCPTR(png_set_error_fn);
+ LOAD_FUNCPTR(png_set_gray_to_rgb);
LOAD_FUNCPTR(png_set_read_fn);
+ LOAD_FUNCPTR(png_set_swap);
+ LOAD_FUNCPTR(png_set_tRNS_to_alpha);
#undef LOAD_FUNCPTR
}
@@ -106,6 +129,7 @@ static void *load_libpng(void)
struct png_decoder
{
struct decoder decoder;
+ struct decoder_frame decoder_frame;
};
static inline struct png_decoder *impl_from_decoder(struct decoder* iface)
@@ -145,11 +169,22 @@ static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t lengt
HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, struct decoder_stat *st)
{
+ struct png_decoder *This = impl_from_decoder(iface);
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
jmp_buf jmpbuf;
HRESULT hr = E_FAIL;
+ int color_type, bit_depth;
+ png_bytep trans;
+ int num_trans;
+ png_uint_32 transparency;
+ png_color_16p trans_values;
+ png_uint_32 ret, xres, yres;
+ int unit_type;
+ png_colorp png_palette;
+ int num_palette;
+ int i;
png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
@@ -193,10 +228,168 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
/* read the header */
ppng_read_info(png_ptr, info_ptr);
+ /* choose a pixel format */
+ color_type = ppng_get_color_type(png_ptr, info_ptr);
+ bit_depth = ppng_get_bit_depth(png_ptr, info_ptr);
+
+ /* PNGs with bit-depth greater than 8 are network byte order. Windows does not expect this. */
+ if (bit_depth > 8)
+ ppng_set_swap(png_ptr);
+
+ /* check for color-keyed alpha */
+ transparency = ppng_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);
+ if (!transparency)
+ num_trans = 0;
+
+ if (transparency && (color_type == PNG_COLOR_TYPE_RGB ||
+ (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16)))
+ {
+ /* expand to RGBA */
+ if (color_type == PNG_COLOR_TYPE_GRAY)
+ ppng_set_gray_to_rgb(png_ptr);
+ ppng_set_tRNS_to_alpha(png_ptr);
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ }
+
+ switch (color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ /* WIC does not support grayscale alpha formats so use RGBA */
+ ppng_set_gray_to_rgb(png_ptr);
+ /* fall through */
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ This->decoder_frame.bpp = bit_depth * 4;
+ switch (bit_depth)
+ {
+ case 8:
+ ppng_set_bgr(png_ptr);
+ This->decoder_frame.pixel_format = GUID_WICPixelFormat32bppBGRA;
+ break;
+ case 16: This->decoder_frame.pixel_format = GUID_WICPixelFormat64bppRGBA; break;
+ default:
+ ERR("invalid RGBA bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ This->decoder_frame.bpp = bit_depth;
+ if (!transparency)
+ {
+ switch (bit_depth)
+ {
+ case 1: This->decoder_frame.pixel_format = GUID_WICPixelFormatBlackWhite; break;
+ case 2: This->decoder_frame.pixel_format = GUID_WICPixelFormat2bppGray; break;
+ case 4: This->decoder_frame.pixel_format = GUID_WICPixelFormat4bppGray; break;
+ case 8: This->decoder_frame.pixel_format = GUID_WICPixelFormat8bppGray; break;
+ case 16: This->decoder_frame.pixel_format = GUID_WICPixelFormat16bppGray; break;
+ default:
+ ERR("invalid grayscale bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ }
+ /* else fall through */
+ case PNG_COLOR_TYPE_PALETTE:
+ This->decoder_frame.bpp = bit_depth;
+ switch (bit_depth)
+ {
+ case 1: This->decoder_frame.pixel_format = GUID_WICPixelFormat1bppIndexed; break;
+ case 2: This->decoder_frame.pixel_format = GUID_WICPixelFormat2bppIndexed; break;
+ case 4: This->decoder_frame.pixel_format = GUID_WICPixelFormat4bppIndexed; break;
+ case 8: This->decoder_frame.pixel_format = GUID_WICPixelFormat8bppIndexed; break;
+ default:
+ ERR("invalid indexed color bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ This->decoder_frame.bpp = bit_depth * 3;
+ switch (bit_depth)
+ {
+ case 8:
+ ppng_set_bgr(png_ptr);
+ This->decoder_frame.pixel_format = GUID_WICPixelFormat24bppBGR;
+ break;
+ case 16: This->decoder_frame.pixel_format = GUID_WICPixelFormat48bppRGB; break;
+ default:
+ ERR("invalid RGB color bit depth: %i\n", bit_depth);
+ hr = E_FAIL;
+ goto end;
+ }
+ break;
+ default:
+ ERR("invalid color type %i\n", color_type);
+ hr = E_FAIL;
+ goto end;
+ }
+
+ This->decoder_frame.width = ppng_get_image_width(png_ptr, info_ptr);
+ This->decoder_frame.height = ppng_get_image_height(png_ptr, info_ptr);
+
+ ret = ppng_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type);
+
+ if (ret && unit_type == PNG_RESOLUTION_METER)
+ {
+ This->decoder_frame.dpix = xres * 0.0254;
+ This->decoder_frame.dpiy = yres * 0.0254;
+ }
+ else
+ {
+ WARN("no pHYs block present\n");
+ This->decoder_frame.dpix = This->decoder_frame.dpiy = 96.0;
+ }
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ ret = ppng_get_PLTE(png_ptr, info_ptr, &png_palette, &num_palette);
+ if (!ret)
+ {
+ ERR("paletted image with no PLTE chunk\n");
+ hr = E_FAIL;
+ goto end;
+ }
+
+ if (num_palette > 256)
+ {
+ ERR("palette has %i colors?!\n", num_palette);
+ hr = E_FAIL;
+ goto end;
+ }
+
+ This->decoder_frame.num_colors = num_palette;
+ for (i=0; i<num_palette; i++)
+ {
+ BYTE alpha = (i < num_trans) ? trans[i] : 0xff;
+ This->decoder_frame.palette[i] = (alpha << 24 |
+ png_palette[i].red << 16|
+ png_palette[i].green << 8|
+ png_palette[i].blue);
+ }
+ }
+ else if (color_type == PNG_COLOR_TYPE_GRAY && transparency && bit_depth <= 8) {
+ num_palette = 1 << bit_depth;
+
+ This->decoder_frame.num_colors = num_palette;
+ for (i=0; i<num_palette; i++)
+ {
+ BYTE alpha = (i == trans_values[0].gray) ? 0 : 0xff;
+ BYTE val = i * 255 / (num_palette - 1);
+ This->decoder_frame.palette[i] = (alpha << 24 | val << 16 | val << 8 | val);
+ }
+ }
+ else
+ {
+ This->decoder_frame.num_colors = 0;
+ }
+
st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
WICBitmapDecoderCapabilityCanDecodeSomeImages |
WICBitmapDecoderCapabilityCanEnumerateMetadata;
st->frame_count = 1;
+
hr = S_OK;
end:
@@ -204,6 +397,13 @@ end:
return hr;
}
+HRESULT CDECL png_decoder_get_frame_info(struct decoder *iface, UINT frame, struct decoder_frame *info)
+{
+ struct png_decoder *This = impl_from_decoder(iface);
+ *info = This->decoder_frame;
+ return S_OK;
+}
+
void CDECL png_decoder_destroy(struct decoder* iface)
{
struct png_decoder *This = impl_from_decoder(iface);
@@ -213,6 +413,7 @@ void CDECL png_decoder_destroy(struct decoder* iface)
static const struct decoder_funcs png_decoder_vtable = {
png_decoder_initialize,
+ png_decoder_get_frame_info,
png_decoder_destroy
};
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 5a4d94ae4f3..d10afcedbc3 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -447,6 +447,7 @@ typedef struct {
struct decoder *png_decoder;
struct decoder_info decoder_info;
struct decoder_stat file_info;
+ struct decoder_frame decoder_frame;
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
@@ -605,6 +606,9 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
if (FAILED(hr))
goto end;
+ /* this function cannot fail in PNG decoder */
+ decoder_get_frame_info(This->png_decoder, 0, &This->decoder_frame);
+
/* initialize libpng */
This->png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!This->png_ptr)
@@ -991,8 +995,8 @@ static HRESULT WINAPI PngDecoder_Frame_GetSize(IWICBitmapFrameDecode *iface,
UINT *puiWidth, UINT *puiHeight)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- *puiWidth = This->width;
- *puiHeight = This->height;
+ *puiWidth = This->decoder_frame.width;
+ *puiHeight = This->decoder_frame.height;
TRACE("(%p)->(%u,%u)\n", iface, *puiWidth, *puiHeight);
return S_OK;
}
@@ -1003,7 +1007,7 @@ static HRESULT WINAPI PngDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *ifa
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
TRACE("(%p,%p)\n", iface, pPixelFormat);
- memcpy(pPixelFormat, This->format, sizeof(GUID));
+ memcpy(pPixelFormat, &This->decoder_frame.pixel_format, sizeof(GUID));
return S_OK;
}
@@ -1012,25 +1016,9 @@ static HRESULT WINAPI PngDecoder_Frame_GetResolution(IWICBitmapFrameDecode *ifac
double *pDpiX, double *pDpiY)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- png_uint_32 ret, xres, yres;
- int unit_type;
-
- EnterCriticalSection(&This->lock);
-
- ret = ppng_get_pHYs(This->png_ptr, This->info_ptr, &xres, &yres, &unit_type);
-
- if (ret && unit_type == PNG_RESOLUTION_METER)
- {
- *pDpiX = xres * 0.0254;
- *pDpiY = yres * 0.0254;
- }
- else
- {
- WARN("no pHYs block present\n");
- *pDpiX = *pDpiY = 96.0;
- }
- LeaveCriticalSection(&This->lock);
+ *pDpiX = This->decoder_frame.dpix;
+ *pDpiY = This->decoder_frame.dpiy;
TRACE("(%p)->(%0.2f,%0.2f)\n", iface, *pDpiX, *pDpiY);
@@ -1041,81 +1029,19 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
IWICPalette *pIPalette)
{
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
- png_uint_32 ret, color_type, bit_depth;
- png_colorp png_palette;
- int num_palette;
- WICColor palette[256];
- png_bytep trans_alpha;
- int num_trans;
- png_color_16p trans_values;
- int i;
HRESULT hr=S_OK;
TRACE("(%p,%p)\n", iface, pIPalette);
- EnterCriticalSection(&This->lock);
-
- color_type = ppng_get_color_type(This->png_ptr, This->info_ptr);
- bit_depth = ppng_get_bit_depth(This->png_ptr, This->info_ptr);
-
- if (color_type == PNG_COLOR_TYPE_PALETTE)
+ if (This->decoder_frame.num_colors)
{
- ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette);
- if (!ret)
- {
- hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
- goto end;
- }
-
- if (num_palette > 256)
- {
- ERR("palette has %i colors?!\n", num_palette);
- hr = E_FAIL;
- goto end;
- }
-
- ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
- if (!ret) num_trans = 0;
-
- for (i=0; i<num_palette; i++)
- {
- BYTE alpha = (i < num_trans) ? trans_alpha[i] : 0xff;
- palette[i] = (alpha << 24 |
- png_palette[i].red << 16|
- png_palette[i].green << 8|
- png_palette[i].blue);
- }
- }
- else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth <= 8) {
- ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
-
- if (!ret)
- {
- hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
- goto end;
- }
-
- num_palette = 1 << bit_depth;
-
- for (i=0; i<num_palette; i++)
- {
- BYTE alpha = (i == trans_values[0].gray) ? 0 : 0xff;
- BYTE val = i * 255 / (num_palette - 1);
- palette[i] = (alpha << 24 | val << 16 | val << 8 | val);
- }
+ hr = IWICPalette_InitializeCustom(pIPalette, This->decoder_frame.palette, This->decoder_frame.num_colors);
}
else
{
hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
}
-end:
-
- LeaveCriticalSection(&This->lock);
-
- if (SUCCEEDED(hr))
- hr = IWICPalette_InitializeCustom(pIPalette, palette, num_palette);
-
return hr;
}
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index 924ed7f5c0d..cf66fbd964d 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -72,6 +72,12 @@ HRESULT CDECL decoder_wrapper_initialize(struct decoder* iface, IStream* stream,
return unix_funcs->decoder_initialize(This->unix_decoder, stream, st);
}
+HRESULT CDECL decoder_wrapper_get_frame_info(struct decoder* iface, UINT frame, struct decoder_frame *info)
+{
+ struct decoder_wrapper* This = impl_from_decoder(iface);
+ return unix_funcs->decoder_get_frame_info(This->unix_decoder, frame, info);
+}
+
void CDECL decoder_wrapper_destroy(struct decoder* iface)
{
struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -81,6 +87,7 @@ void CDECL decoder_wrapper_destroy(struct decoder* iface)
static const struct decoder_funcs decoder_wrapper_vtable = {
decoder_wrapper_initialize,
+ decoder_wrapper_get_frame_info,
decoder_wrapper_destroy
};
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index fb4400bfe97..111a82dc637 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -66,6 +66,7 @@ HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *in
static const struct unix_funcs unix_funcs = {
decoder_create,
decoder_initialize,
+ decoder_get_frame_info,
decoder_destroy
};
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index ddc3d486dcd..ac8ae015c76 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -21,6 +21,11 @@ HRESULT CDECL decoder_initialize(struct decoder *decoder, IStream *stream, struc
return decoder->vtable->initialize(decoder, stream, st);
}
+HRESULT CDECL decoder_get_frame_info(struct decoder *decoder, UINT frame, struct decoder_frame *info)
+{
+ return decoder->vtable->get_frame_info(decoder, frame, info);
+}
+
void CDECL decoder_destroy(struct decoder *decoder)
{
decoder->vtable->destroy(decoder);
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 110a0bd510a..6d12b98bfc4 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -267,6 +267,16 @@ struct decoder_stat
DWORD frame_count;
};
+struct decoder_frame
+{
+ CLSID pixel_format;
+ UINT width, height;
+ UINT bpp;
+ double dpix, dpiy;
+ DWORD num_colors;
+ WICColor palette[256];
+};
+
struct decoder
{
const struct decoder_funcs *vtable;
@@ -275,6 +285,7 @@ struct decoder
struct decoder_funcs
{
HRESULT (CDECL *initialize)(struct decoder* This, IStream *stream, struct decoder_stat *st);
+ HRESULT (CDECL *get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
void (CDECL *destroy)(struct decoder* This);
};
@@ -289,6 +300,7 @@ struct win32_funcs
HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT CDECL decoder_initialize(struct decoder *This, IStream *stream, struct decoder_stat *st);
+HRESULT CDECL decoder_get_frame_info(struct decoder* This, UINT frame, struct decoder_frame *info);
void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -297,6 +309,7 @@ struct unix_funcs
{
HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
HRESULT (CDECL *decoder_initialize)(struct decoder *This, IStream *stream, struct decoder_stat *st);
+ HRESULT (CDECL *decoder_get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
void (CDECL *decoder_destroy)(struct decoder* This);
};
--
2.17.1
1
0