Also move the get_encoder_clsid() helper to the top of the file so it can be used by the new test.
Signed-off-by: Florian Will florian.will@gmail.com --- dlls/gdiplus/tests/image.c | 244 ++++++++++++++++++++++++++++++++----- 1 file changed, 214 insertions(+), 30 deletions(-)
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index d6f74050c0..01d79f08c4 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -76,6 +76,36 @@ static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo expect_guid(expected, &raw, line, todo); }
+static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid) +{ + GpStatus status; + UINT n_codecs, info_size, i; + ImageCodecInfo *info; + BOOL ret = FALSE; + + status = GdipGetImageEncodersSize(&n_codecs, &info_size); + expect(Ok, status); + + info = GdipAlloc(info_size); + + status = GdipGetImageEncoders(n_codecs, info_size, info); + expect(Ok, status); + + for (i = 0; i < n_codecs; i++) + { + if (!lstrcmpW(info[i].MimeType, mime)) + { + *format = info[i].FormatID; + *clsid = info[i].Clsid; + ret = TRUE; + break; + } + } + + GdipFree(info); + return ret; +} + static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo) { LPSTREAM stream; @@ -487,6 +517,189 @@ static void test_SavingImages(void) ok(DeleteFileA(filenameA), "Delete failed.\n"); }
+static void test_SavingMultiPageTiff(void) +{ + GpStatus stat; + BOOL result; + GpBitmap *bm1 = NULL, *bm2 = NULL, *check_bm = NULL; + const REAL WIDTH = 10.0, HEIGHT = 20.0; + REAL w, h; + GUID format, tiff_clsid; + EncoderParameters params; + ULONG32 paramValue = EncoderValueFrameDimensionPage; + UINT frame_count; + static const CHAR filename1A[] = "1.tif"; + static const CHAR filename2A[] = "2.tif"; + static const WCHAR filename1[] = { '1','.','t','i','f',0 }; + static const WCHAR filename2[] = { '2','.','t','i','f',0 }; + static const WCHAR tiff_mimetype[] = { 'i','m','a','g','e','/','t','i','f','f',0 }; + + params.Count = 1; + params.Parameter[0].Guid = EncoderSaveFlag; + params.Parameter[0].Type = EncoderParameterValueTypeLong; + params.Parameter[0].NumberOfValues = 1; + params.Parameter[0].Value = ¶mValue; + + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm1); + expect(Ok, stat); + stat = GdipCreateBitmapFromScan0(2 * WIDTH, 2 * HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm2); + expect(Ok, stat); + result = get_encoder_clsid(tiff_mimetype, &format, &tiff_clsid); + ok(result, "getting TIFF encoding clsid failed"); + + if (!bm1 || !bm2 || !result) + return; + + /* invalid params: NULL */ + stat = GdipSaveAdd(0, ¶ms); + todo_wine expect(InvalidParameter, stat); + stat = GdipSaveAdd((GpImage*)bm1, 0); + todo_wine expect(InvalidParameter, stat); + + stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, 0); + todo_wine expect(InvalidParameter, stat); + stat = GdipSaveAddImage((GpImage*)bm1, 0, ¶ms); + todo_wine expect(InvalidParameter, stat); + stat = GdipSaveAddImage(0, (GpImage*)bm2, ¶ms); + todo_wine expect(InvalidParameter, stat); + + /* win32 error: SaveAdd() can only be called after Save() with the MultiFrame param */ + stat = GdipSaveAdd((GpImage*)bm1, ¶ms); + todo_wine expect(Win32Error, stat); + stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, ¶ms); + todo_wine 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, ¶ms); + todo_wine expect(Win32Error, stat); + stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, ¶ms); + todo_wine expect(Win32Error, stat); + + /* win32 error: can't flush before starting the encoding process */ + paramValue = EncoderValueFlush; + stat = GdipSaveAdd((GpImage*)bm1, ¶ms); + todo_wine expect(Win32Error, stat); + + /* win32 error: can't start encoding process through SaveAdd(), only Save() */ + paramValue = EncoderValueMultiFrame; + stat = GdipSaveAdd((GpImage*)bm1, ¶ms); + todo_wine expect(Win32Error, stat); + + /* start encoding process: add first frame (bm1) */ + paramValue = EncoderValueMultiFrame; + stat = GdipSaveImageToFile((GpImage*)bm1, filename1, &tiff_clsid, ¶ms); + expect(Ok, stat); + + /* re-start encoding process: add first frame (bm1), should re-create the file */ + stat = GdipSaveImageToFile((GpImage*)bm1, filename1, &tiff_clsid, ¶ms); + expect(Ok, stat); + + /* add second frame (bm2) */ + paramValue = EncoderValueFrameDimensionPage; + stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, ¶ms); + todo_wine expect(Ok, stat); + if (stat != Ok) goto cleanup; + + /* finish encoding process */ + paramValue = EncoderValueFlush; + stat = GdipSaveAdd((GpImage*)bm1, ¶ms); + expect(Ok, stat); + + /* bm1 should be unchanged, only the saved file on disk has multiple frames */ + stat = GdipImageGetFrameCount((GpImage*)bm1, &FrameDimensionPage, &frame_count); + expect(Ok, stat); + expect(1, frame_count); + + /* win32 error: encoding process already finished */ + paramValue = EncoderValueFrameDimensionPage; + stat = GdipSaveAddImage((GpImage*)bm1, (GpImage*)bm2, ¶ms); + expect(Win32Error, stat); + + stat = GdipSaveAdd((GpImage*)bm1, ¶ms); + expect(Win32Error, stat); + + GdipDisposeImage((GpImage*)bm1); + bm1 = 0; + GdipDisposeImage((GpImage*)bm2); + bm2 = 0; + + /* re-load and check image stats */ + stat = GdipLoadImageFromFile(filename1, (GpImage**)&check_bm); + expect(Ok, stat); + + stat = GdipImageGetFrameCount((GpImage*)check_bm, &FrameDimensionPage, &frame_count); + expect(Ok, stat); + expect(2, frame_count); + if (stat != Ok || frame_count != 2) goto cleanup; + + stat = GdipGetImageDimension((GpImage*)check_bm, &w, &h); + expect(Ok, stat); + expectf(WIDTH, w); /* frame index 0: bm1 stats */ + expectf(HEIGHT, h); + + stat = GdipImageSelectActiveFrame((GpImage*)check_bm, &FrameDimensionPage, 1); + expect(Ok, stat); + + stat = GdipGetImageDimension((GpImage*)check_bm, &w, &h); + expectf(2 * WIDTH, w); /* frame index 1: bm2 stats */ + expectf(2 * HEIGHT, h); + + /* now proper API use for SaveAdd() to swap the frames in check_bm */ + paramValue = EncoderValueMultiFrame; + stat = GdipSaveImageToFile((GpImage*)check_bm, filename2, &tiff_clsid, ¶ms); + expect(Ok, stat); /* second frame is active: bm2 */ + + stat = GdipImageSelectActiveFrame((GpImage*)check_bm, &FrameDimensionPage, 0); + expect(Ok, stat); + + paramValue = EncoderValueFrameDimensionPage; + stat = GdipSaveAdd((GpImage*)check_bm, ¶ms); + expect(Ok, stat); /* first frame is active: bm1 */ + + paramValue = EncoderValueFlush; + stat = GdipSaveAdd((GpImage*)check_bm, ¶ms); + expect(Ok, stat); /* flushed encoder (finished encoding process) */ + + GdipDisposeImage((GpImage*)check_bm); + check_bm = 0; + + /* re-load and check image stats */ + stat = GdipLoadImageFromFile(filename2, (GpImage**)&check_bm); + expect(Ok, stat); + + stat = GdipImageGetFrameCount((GpImage*)check_bm, &FrameDimensionPage, &frame_count); + expect(Ok, stat); + expect(2, frame_count); + + stat = GdipGetImageDimension((GpImage*)check_bm, &w, &h); + expect(Ok, stat); + expectf(2 * WIDTH, w); /* frame index 0: bm2 stats */ + expectf(2 * HEIGHT, h); + + stat = GdipImageSelectActiveFrame((GpImage*)check_bm, &FrameDimensionPage, 1); + expect(Ok, stat); + + stat = GdipGetImageDimension((GpImage*)check_bm, &w, &h); + expectf(WIDTH, w); /* frame index 1: bm1 stats */ + expectf(HEIGHT, h); + + cleanup: + if (bm1) + GdipDisposeImage((GpImage*)bm1); + if (bm2) + GdipDisposeImage((GpImage*)bm2); + ok(DeleteFileA(filename1A), "Delete 1.tif failed.\n"); + + if (check_bm) + { + GdipDisposeImage((GpImage*)check_bm); + ok(DeleteFileA(filename2A), "Delete 2.tif failed.\n"); + } +} + static void test_encoders(void) { GpStatus stat; @@ -4888,36 +5101,6 @@ static void test_CloneBitmapArea(void) GdipDisposeImage((GpImage *)bitmap); }
-static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid) -{ - GpStatus status; - UINT n_codecs, info_size, i; - ImageCodecInfo *info; - BOOL ret = FALSE; - - status = GdipGetImageEncodersSize(&n_codecs, &info_size); - expect(Ok, status); - - info = GdipAlloc(info_size); - - status = GdipGetImageEncoders(n_codecs, info_size, info); - expect(Ok, status); - - for (i = 0; i < n_codecs; i++) - { - if (!lstrcmpW(info[i].MimeType, mime)) - { - *format = info[i].FormatID; - *clsid = info[i].Clsid; - ret = TRUE; - break; - } - } - - GdipFree(info); - return ret; -} - static void test_supported_encoders(void) { static const WCHAR bmp_mimetype[] = { 'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p',0 }; @@ -5700,6 +5883,7 @@ START_TEST(image) test_GdipImageGetFrameDimensionsCount(); test_LoadingImages(); test_SavingImages(); + test_SavingMultiPageTiff(); test_encoders(); test_LockBits(); test_LockBits_UserBuf();