[PATCH v2 5/5] gdiplus: Implement GdipSaveAddImage() and GdipSaveAdd().

Florian Will florian.will at gmail.com
Wed Feb 19 01:47:07 CST 2020


Signed-off-by: Florian Will <florian.will at gmail.com>
---
v2: Use the new terminate_encoder_wic() function signature from patch
1/5 (which simplifies things). Changes related to the GpImage "encoder"
field dropped from this patch because they have been moved to patch 1.
---
 dlls/gdiplus/image.c       | 54 ++++++++++++++++++++++++++++++++------
 dlls/gdiplus/tests/image.c | 24 ++++++++---------
 2 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index 94c03ede19..28ccc78400 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -4426,6 +4426,9 @@ GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR* filenam
     if (!image || !filename|| !clsidEncoder)
         return InvalidParameter;
 
+    /* this might release an old file stream held by the encoder so we can re-create it below */
+    terminate_encoder_wic(image);
+
     stat = GdipCreateStreamOnFile(filename, GENERIC_WRITE, &stream);
     if (stat != Ok)
         return GenericError;
@@ -4598,6 +4601,27 @@ static GpStatus encode_frame_wic(IWICBitmapEncoder *encoder, GpImage *image)
     return hresult_to_status(hr);
 }
 
+static BOOL has_encoder_param_long(GDIPCONST EncoderParameters *params, GUID param_guid, ULONG val)
+{
+    if (!params)
+        return FALSE;
+
+    for (int param_idx = 0; param_idx < params->Count; param_idx++)
+    {
+        EncoderParameter param = params->Parameter[param_idx];
+        if (param.Type == EncoderParameterValueTypeLong && IsEqualCLSID(&param.Guid, &param_guid))
+        {
+            ULONG *value_array = (ULONG*) param.Value;
+            for (int value_idx = 0; value_idx < param.NumberOfValues; value_idx++)
+            {
+                if (value_array[value_idx] == val)
+                    return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+
 static GpStatus encode_image_wic(GpImage *image, IStream *stream,
     REFGUID container, GDIPCONST EncoderParameters *params)
 {
@@ -4611,10 +4635,13 @@ static GpStatus encode_image_wic(GpImage *image, IStream *stream,
     if (status == Ok)
         status = encode_frame_wic(image->encoder, image);
 
-    /* always try to terminate, but if something already failed earlier, keep the old status. */
-    terminate_status = terminate_encoder_wic(image);
-    if (status == Ok)
-        status = terminate_status;
+    if (!has_encoder_param_long(params, EncoderSaveFlag, EncoderValueMultiFrame))
+    {
+        /* always try to terminate, but if something already failed earlier, keep the old status. */
+        terminate_status = terminate_encoder_wic(image);
+        if (status == Ok)
+            status = terminate_status;
+    }
 
     return status;
 }
@@ -4687,8 +4714,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
  */
 GpStatus WINGDIPAPI GdipSaveAdd(GpImage *image, GDIPCONST EncoderParameters *params)
 {
-    FIXME("(%p,%p): stub\n", image, params);
-    return NotImplemented;
+    return GdipSaveAddImage(image, image, params);
 }
 
 /*****************************************************************************
@@ -4704,8 +4730,20 @@ GpStatus WINGDIPAPI GdipSaveAdd(GpImage *image, GDIPCONST EncoderParameters *par
 GpStatus WINGDIPAPI GdipSaveAddImage(GpImage *image, GpImage *additional_image,
     GDIPCONST EncoderParameters *params)
 {
-    FIXME("(%p,%p,%p): stub\n", image, additional_image, params);
-    return NotImplemented;
+    TRACE("%p, %p, %p\n", image, additional_image, params);
+
+    if (!image || !additional_image || !params)
+        return InvalidParameter;
+
+    if (!image->encoder)
+        return Win32Error;
+
+    if (has_encoder_param_long(params, EncoderSaveFlag, EncoderValueFlush))
+        return terminate_encoder_wic(image);
+    else if (has_encoder_param_long(params, EncoderSaveFlag, EncoderValueFrameDimensionPage))
+        return encode_frame_wic(image->encoder, additional_image);
+    else
+        return InvalidParameter;
 }
 
 /*****************************************************************************
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
index 01d79f08c4..bbb9365edb 100644
--- a/dlls/gdiplus/tests/image.c
+++ b/dlls/gdiplus/tests/image.c
@@ -552,41 +552,41 @@ static void test_SavingMultiPageTiff(void)
 
     /* invalid params: NULL */
     stat = GdipSaveAdd(0, &params);
-    todo_wine expect(InvalidParameter, stat);
+    expect(InvalidParameter, stat);
     stat = GdipSaveAdd((GpImage*)bm1, 0);
-    todo_wine expect(InvalidParameter, stat);
+    expect(InvalidParameter, stat);
 
     stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, 0);
-    todo_wine expect(InvalidParameter, stat);
+    expect(InvalidParameter, stat);
     stat = GdipSaveAddImage((GpImage*)bm1, 0, &params);
-    todo_wine expect(InvalidParameter, stat);
+    expect(InvalidParameter, stat);
     stat = GdipSaveAddImage(0, (GpImage*)bm2, &params);
-    todo_wine expect(InvalidParameter, stat);
+    expect(InvalidParameter, stat);
 
     /* win32 error: SaveAdd() can only be called after Save() with the MultiFrame param */
     stat = GdipSaveAdd((GpImage*)bm1, &params);
-    todo_wine expect(Win32Error, stat);
+    expect(Win32Error, stat);
     stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, &params);
-    todo_wine expect(Win32Error, stat);
+    expect(Win32Error, stat);
 
     stat = GdipSaveImageToFile((GpImage*)bm1, filename1, &tiff_clsid, 0); /* param not set! */
     expect(Ok, stat);
     if (stat != Ok) goto cleanup;
 
     stat = GdipSaveAdd((GpImage*)bm1, &params);
-    todo_wine expect(Win32Error, stat);
+    expect(Win32Error, stat);
     stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, &params);
-    todo_wine expect(Win32Error, stat);
+    expect(Win32Error, stat);
 
     /* win32 error: can't flush before starting the encoding process */
     paramValue = EncoderValueFlush;
     stat = GdipSaveAdd((GpImage*)bm1, &params);
-    todo_wine expect(Win32Error, stat);
+    expect(Win32Error, stat);
 
     /* win32 error: can't start encoding process through SaveAdd(), only Save() */
     paramValue = EncoderValueMultiFrame;
     stat = GdipSaveAdd((GpImage*)bm1, &params);
-    todo_wine expect(Win32Error, stat);
+    expect(Win32Error, stat);
 
     /* start encoding process: add first frame (bm1) */
     paramValue = EncoderValueMultiFrame;
@@ -600,7 +600,7 @@ static void test_SavingMultiPageTiff(void)
     /* add second frame (bm2) */
     paramValue = EncoderValueFrameDimensionPage;
     stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, &params);
-    todo_wine expect(Ok, stat);
+    expect(Ok, stat);
     if (stat != Ok) goto cleanup;
 
     /* finish encoding process */
-- 
2.20.1




More information about the wine-devel mailing list