[PATCH 1/2] windowscodecs: Start interface for unix encoders.

Esme Povirk esme at codeweavers.com
Sun Nov 15 14:12:24 CST 2020


Signed-off-by: Esme Povirk <esme at codeweavers.com>
---
 dlls/windowscodecs/libpng.c            | 55 ++++++++++++++++++++++++++
 dlls/windowscodecs/pngformat.c         | 42 ++++++++++++++------
 dlls/windowscodecs/unix_iface.c        | 50 +++++++++++++++++++++++
 dlls/windowscodecs/unix_lib.c          | 12 +++++-
 dlls/windowscodecs/wincodecs_common.h  |  5 +++
 dlls/windowscodecs/wincodecs_private.h | 34 ++++++++++++++++
 6 files changed, 186 insertions(+), 12 deletions(-)

diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index 93ff6e056ec..fd1ee679ec3 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -611,6 +611,55 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
     return S_OK;
 }
 
+struct png_encoder
+{
+    struct encoder encoder;
+};
+
+static inline struct png_encoder *impl_from_encoder(struct encoder* iface)
+{
+    return CONTAINING_RECORD(iface, struct png_encoder, encoder);
+}
+
+static void CDECL png_encoder_destroy(struct encoder *encoder)
+{
+    struct png_encoder *This = impl_from_encoder(encoder);
+    RtlFreeHeap(GetProcessHeap(), 0, This);
+}
+
+static const struct encoder_funcs png_encoder_vtable = {
+    png_encoder_destroy
+};
+
+HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result)
+{
+    struct png_encoder *This;
+
+    if (!load_libpng())
+    {
+        ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG);
+        return E_FAIL;
+    }
+
+    This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This));
+
+    if (!This)
+    {
+        return E_OUTOFMEMORY;
+    }
+
+    This->encoder.vtable = &png_encoder_vtable;
+    *result = &This->encoder;
+
+    info->container_format = GUID_ContainerFormatPng;
+    info->clsid = CLSID_WICPngEncoder;
+    info->encoder_options[0] = ENCODER_OPTION_INTERLACE;
+    info->encoder_options[1] = ENCODER_OPTION_FILTER;
+    info->encoder_options[2] = ENCODER_OPTION_END;
+
+    return S_OK;
+}
+
 #else
 
 HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result)
@@ -619,4 +668,10 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
     return E_FAIL;
 }
 
+HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result)
+{
+    ERR("Trying to save PNG picture, but PNG support is not compiled in.\n");
+    return E_FAIL;
+}
+
 #endif
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 9d24096b2cd..f0ac83dae1c 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -309,9 +309,6 @@ static CRITICAL_SECTION_DEBUG init_png_cs_debug =
 };
 static CRITICAL_SECTION init_png_cs = { &init_png_cs_debug, -1, 0, 0, 0, 0 };
 
-static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
-static const WCHAR wszPngFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
-
 static void *load_libpng(void)
 {
     void *result;
@@ -392,6 +389,14 @@ static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message
     WARN("PNG warning: %s\n", debugstr_a(warning_message));
 }
 
+static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
+static const WCHAR wszPngFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
+
+static const PROPBAG2 encoder_option_properties[ENCODER_OPTION_END] = {
+    { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszPngInterlaceOption },
+    { PROPBAG2_TYPE_DATA, VT_UI1,  0, 0, (LPOLESTR)wszPngFilterOption }
+};
+
 struct png_pixelformat {
     const WICPixelFormatGUID *guid;
     UINT bpp;
@@ -426,6 +431,8 @@ typedef struct PngEncoder {
     IStream *stream;
     png_structp png_ptr;
     png_infop info_ptr;
+    struct encoder *encoder;
+    struct encoder_info encoder_info;
     UINT frame_count;
     BOOL frame_initialized;
     const struct png_pixelformat *format;
@@ -964,6 +971,7 @@ static ULONG WINAPI PngEncoder_Release(IWICBitmapEncoder *iface)
         if (This->stream)
             IStream_Release(This->stream);
         HeapFree(GetProcessHeap(), 0, This->data);
+        encoder_destroy(This->encoder);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -1045,17 +1053,19 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
 
 static HRESULT WINAPI PngEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID *format)
 {
+    PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
     TRACE("(%p,%p)\n", iface, format);
 
     if (!format)
         return E_INVALIDARG;
 
-    memcpy(format, &GUID_ContainerFormatPng, sizeof(*format));
+    memcpy(format, &This->encoder_info.container_format, sizeof(*format));
     return S_OK;
 }
 
 static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
 {
+    PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
     IWICComponentInfo *comp_info;
     HRESULT hr;
 
@@ -1063,7 +1073,7 @@ static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBi
 
     if (!info) return E_INVALIDARG;
 
-    hr = CreateComponentInfo(&CLSID_WICPngEncoder, &comp_info);
+    hr = CreateComponentInfo(&This->encoder_info.clsid, &comp_info);
     if (hr == S_OK)
     {
         hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
@@ -1112,11 +1122,8 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
 {
     PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
     HRESULT hr;
-    static const PROPBAG2 opts[2] =
-    {
-        { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszPngInterlaceOption },
-        { PROPBAG2_TYPE_DATA, VT_UI1,  0, 0, (LPOLESTR)wszPngFilterOption },
-    };
+    DWORD opts_length;
+    PROPBAG2 opts[6];
 
     TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
 
@@ -1136,7 +1143,12 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
 
     if (ppIEncoderOptions)
     {
-        hr = CreatePropertyBag2(opts, ARRAY_SIZE(opts), ppIEncoderOptions);
+        for (opts_length = 0; This->encoder_info.encoder_options[opts_length] < ENCODER_OPTION_END; opts_length++)
+        {
+            opts[opts_length] = encoder_option_properties[This->encoder_info.encoder_options[opts_length]];
+        }
+
+        hr = CreatePropertyBag2(opts, opts_length, ppIEncoderOptions);
         if (FAILED(hr))
         {
             LeaveCriticalSection(&This->lock);
@@ -1215,6 +1227,14 @@ HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv)
     This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngEncoder));
     if (!This) return E_OUTOFMEMORY;
 
+    ret = get_unix_encoder(&CLSID_WICPngEncoder, &This->encoder_info, &This->encoder);
+
+    if (FAILED(ret))
+    {
+        HeapFree(GetProcessHeap(), 0, This);
+        return ret;
+    }
+
     This->IWICBitmapEncoder_iface.lpVtbl = &PngEncoder_Vtbl;
     This->IWICBitmapFrameEncode_iface.lpVtbl = &PngEncoder_FrameVtbl;
     This->ref = 1;
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index 5ed995e7642..80769b5d560 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -143,3 +143,53 @@ HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info,
 
     return hr;
 }
+
+struct encoder_wrapper
+{
+    struct encoder win32_encoder;
+    struct encoder *unix_encoder;
+};
+
+static inline struct encoder_wrapper *impl_from_encoder(struct encoder* iface)
+{
+    return CONTAINING_RECORD(iface, struct encoder_wrapper, win32_encoder);
+}
+
+void CDECL encoder_wrapper_destroy(struct encoder* iface)
+{
+    struct encoder_wrapper* This = impl_from_encoder(iface);
+    unix_funcs->encoder_destroy(This->unix_encoder);
+    HeapFree(GetProcessHeap(), 0, This);
+}
+
+static const struct encoder_funcs encoder_wrapper_vtable = {
+    encoder_wrapper_destroy
+};
+
+HRESULT get_unix_encoder(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result)
+{
+    HRESULT hr;
+    struct encoder_wrapper *wrapper;
+    struct encoder *unix_encoder;
+
+    init_unixlib();
+
+    hr = unix_funcs->encoder_create(encoder_clsid, info, &unix_encoder);
+
+    if (SUCCEEDED(hr))
+    {
+        wrapper = HeapAlloc(GetProcessHeap(), 0, sizeof(*wrapper));
+
+        if (!wrapper)
+        {
+            unix_funcs->encoder_destroy(unix_encoder);
+            return E_OUTOFMEMORY;
+        }
+
+        wrapper->win32_encoder.vtable = &encoder_wrapper_vtable;
+        wrapper->unix_encoder = unix_encoder;
+        *result = &wrapper->win32_encoder;
+    }
+
+    return hr;
+}
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index dc8549e1eb8..b0c6b37bfce 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -76,6 +76,14 @@ HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *in
     return E_NOTIMPL;
 }
 
+HRESULT CDECL encoder_create(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result)
+{
+    if (IsEqualGUID(encoder_clsid, &CLSID_WICPngEncoder))
+        return png_encoder_create(info, result);
+
+    return E_NOTIMPL;
+}
+
 static const struct unix_funcs unix_funcs = {
     decoder_create,
     decoder_initialize,
@@ -83,7 +91,9 @@ static const struct unix_funcs unix_funcs = {
     decoder_copy_pixels,
     decoder_get_metadata_blocks,
     decoder_get_color_context,
-    decoder_destroy
+    decoder_destroy,
+    encoder_create,
+    encoder_destroy
 };
 
 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index b7572d69df4..303c2d9f38b 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -48,6 +48,11 @@ void CDECL decoder_destroy(struct decoder *decoder)
     decoder->vtable->destroy(decoder);
 }
 
+void CDECL encoder_destroy(struct encoder *encoder)
+{
+    encoder->vtable->destroy(encoder);
+}
+
 HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
     UINT srcwidth, UINT srcheight, INT srcstride,
     const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index d60b281faef..8495ea73521 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -332,10 +332,41 @@ HRESULT CDECL decoder_get_color_context(struct decoder* This, UINT frame, UINT n
     BYTE **data, DWORD *datasize);
 void CDECL decoder_destroy(struct decoder *This);
 
+struct encoder_funcs;
+
+/* sync with encoder_option_properties */
+enum encoder_option
+{
+    ENCODER_OPTION_INTERLACE,
+    ENCODER_OPTION_FILTER,
+    ENCODER_OPTION_END
+};
+
+struct encoder_info
+{
+    GUID container_format;
+    CLSID clsid;
+    DWORD encoder_options[7];
+};
+
+struct encoder
+{
+    const struct encoder_funcs *vtable;
+};
+
+struct encoder_funcs
+{
+    void (CDECL *destroy)(struct encoder* This);
+};
+
+void CDECL encoder_destroy(struct encoder* This);
+
 HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
 HRESULT CDECL tiff_decoder_create(struct decoder_info *info, struct decoder **result);
 HRESULT CDECL jpeg_decoder_create(struct decoder_info *info, struct decoder **result);
 
+HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result);
+
 struct unix_funcs
 {
     HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
@@ -348,9 +379,12 @@ struct unix_funcs
     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 *encoder_create)(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result);
+    void (CDECL *encoder_destroy)(struct encoder* This);
 };
 
 HRESULT get_unix_decoder(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
+HRESULT get_unix_encoder(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result);
 
 extern HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
     const struct decoder_info *decoder_info, REFIID iid, void** ppv) DECLSPEC_HIDDEN;
-- 
2.17.1




More information about the wine-devel mailing list