Replace checksums with PNG image expectations for rectangles

This CL replaces the use of MD5 checksums with PNG image expectations
for the rectangles.pdf and many_rectangles.pdf test files. This change
uses the CompareBitmapToPngWithExpectationSuffix() function and
introduces new functions to test with PNG expectations.

This improves the clarity of these comparisons allowing the addition of
visual verification, which is more robust than the prior MD5 checksum.

The change also adds new PNG Comparison test helper functions such as
TestRenderPageBitmapWithMatrixToPng(),
TestRenderPageBitmapWithExternalMemoryAndNoStrideToPng() and many more.

Bug: 468228360
Change-Id: I8b7dfc61f2db08cad5c43d56bbd9ee61de9d6b3c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/139930
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index ab4df77..8294349 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -2382,10 +2382,11 @@
   ScopedPage page = LoadScopedPage(0);
   ASSERT_TRUE(page);
 
-  using pdfium::ManyRectanglesChecksum;
+  using pdfium::kManyRectanglesPng;
   {
     ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
-    CompareBitmap(page_bitmap.get(), 200, 300, ManyRectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(page_bitmap.get(),
+                                            kManyRectanglesPng);
   }
 
   // Add a black rectangle.
@@ -2429,7 +2430,8 @@
   FPDFPageObj_Destroy(added_object);
   {
     ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
-    CompareBitmap(page_bitmap.get(), 200, 300, ManyRectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(page_bitmap.get(),
+                                            kManyRectanglesPng);
   }
   EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
 
@@ -2448,7 +2450,8 @@
   EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
   {
     ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
-    CompareBitmap(page_bitmap.get(), 200, 300, ManyRectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(page_bitmap.get(),
+                                            kManyRectanglesPng);
   }
 
   CloseSavedPage(saved_page);
diff --git a/fpdfsdk/fpdf_editpage_embeddertest.cpp b/fpdfsdk/fpdf_editpage_embeddertest.cpp
index 67f2ad3..41dde03 100644
--- a/fpdfsdk/fpdf_editpage_embeddertest.cpp
+++ b/fpdfsdk/fpdf_editpage_embeddertest.cpp
@@ -40,8 +40,8 @@
       EXPECT_EQ(200, page_width);
       EXPECT_EQ(300, page_height);
       ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-      CompareBitmap(bitmap.get(), page_width, page_height,
-                    pdfium::RectanglesChecksum());
+      CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                              pdfium::kRectanglesPng);
     }
 
     FPDFPage_SetRotation(page.get(), 1);
@@ -515,8 +515,8 @@
   {
     // Render the page as is.
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), page_width, page_height,
-                  pdfium::RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   {
@@ -530,8 +530,8 @@
     EXPECT_EQ(8, FPDFPage_CountObjects(saved_page));
 
     ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
-    CompareBitmap(bitmap.get(), page_width, page_height,
-                  pdfium::RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
 
     CloseSavedPage(saved_page);
     CloseSavedDocument();
@@ -659,8 +659,8 @@
   {
     // Sanity check rectangles.pdf before modifying it.
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), page_width, page_height,
-                  pdfium::RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
     EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(page.get()));
   }
 
@@ -711,8 +711,8 @@
   EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), page_width, page_height,
-                  pdfium::RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
     // `path` can still be found. It is just deactivated.
     EXPECT_EQ(kObjectCountWithNewPath, FPDFPage_CountObjects(page.get()));
   }
@@ -725,8 +725,8 @@
     ASSERT_TRUE(saved_page);
 
     ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
-    CompareBitmap(bitmap.get(), page_width, page_height,
-                  pdfium::RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
     // `path` did not get written out to the saved PDF.
     EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
 
diff --git a/fpdfsdk/fpdf_editpath_embeddertest.cpp b/fpdfsdk/fpdf_editpath_embeddertest.cpp
index 16ac8f6..6bcf1cc 100644
--- a/fpdfsdk/fpdf_editpath_embeddertest.cpp
+++ b/fpdfsdk/fpdf_editpath_embeddertest.cpp
@@ -10,8 +10,6 @@
 #include "testing/embedder_test_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using pdfium::RectanglesChecksum;
-
 using FPDFEditPathEmbedderTest = EmbedderTest;
 
 namespace {
@@ -97,8 +95,8 @@
 
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   FPDF_PAGEOBJECT path = FPDFPage_GetObject(page.get(), 0);
@@ -117,8 +115,8 @@
   ASSERT_TRUE(FPDFPageObj_SetMatrix(path, &matrix));
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   ASSERT_TRUE(FPDFPage_GenerateContent(page.get()));
@@ -126,12 +124,11 @@
 
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
-  VerifySavedDocument(kExpectedRectangleWidth, kExpectedRectangleHeight,
-                      RectanglesChecksum());
+  VerifySavedDocumentToPngWithExpectationSuffix(pdfium::kRectanglesPng);
 }
 
 TEST_F(FPDFEditPathEmbedderTest, GetAndSetMatrixForFormWithPath) {
@@ -141,8 +138,8 @@
 
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   FPDF_PAGEOBJECT form = FPDFPage_GetObject(page.get(), 0);
@@ -161,8 +158,8 @@
   ASSERT_TRUE(FPDFPageObj_SetMatrix(form, &matrix));
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   FPDF_PAGEOBJECT path = FPDFFormObj_GetObject(form, 0);
@@ -180,8 +177,8 @@
   ASSERT_TRUE(FPDFPageObj_SetMatrix(path, &matrix));
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   ASSERT_TRUE(FPDFPage_GenerateContent(page.get()));
@@ -189,12 +186,11 @@
 
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
-  VerifySavedDocument(kExpectedRectangleWidth, kExpectedRectangleHeight,
-                      RectanglesChecksum());
+  VerifySavedDocumentToPngWithExpectationSuffix(pdfium::kRectanglesPng);
 }
 
 TEST_F(FPDFEditPathEmbedderTest, AddPathToRectangles) {
@@ -204,8 +200,8 @@
 
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   ScopedFPDFPageObject path = CreateBlackTriangle();
@@ -238,8 +234,8 @@
 
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), kExpectedRectangleWidth,
-                  kExpectedRectangleHeight, RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   ScopedFPDFPageObject path = CreateBlackTriangle();
diff --git a/fpdfsdk/fpdf_ppo_embeddertest.cpp b/fpdfsdk/fpdf_ppo_embeddertest.cpp
index 1e66db1..34493cb 100644
--- a/fpdfsdk/fpdf_ppo_embeddertest.cpp
+++ b/fpdfsdk/fpdf_ppo_embeddertest.cpp
@@ -303,7 +303,8 @@
 
   {
     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-    CompareBitmap(bitmap.get(), 200, 300, pdfium::RectanglesChecksum());
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                            pdfium::kRectanglesPng);
   }
 
   FPDF_PAGEOBJECT page_object = FPDF_NewFormObjectFromXObject(xobject);
diff --git a/fpdfsdk/fpdf_transformpage_embeddertest.cpp b/fpdfsdk/fpdf_transformpage_embeddertest.cpp
index 8ca7c19..9a38629 100644
--- a/fpdfsdk/fpdf_transformpage_embeddertest.cpp
+++ b/fpdfsdk/fpdf_transformpage_embeddertest.cpp
@@ -13,8 +13,6 @@
 #include "testing/scoped_locale.h"
 #endif
 
-using pdfium::RectanglesChecksum;
-
 namespace {
 
 const char* ShrunkChecksum() {
@@ -226,8 +224,8 @@
       EXPECT_EQ(200, page_width);
       EXPECT_EQ(300, page_height);
       ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-      CompareBitmap(bitmap.get(), page_width, page_height,
-                    RectanglesChecksum());
+      CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                              pdfium::kRectanglesPng);
     }
 
     FPDFPage_SetCropBox(page.get(), 10, 20, 100, 150);
@@ -304,8 +302,8 @@
       EXPECT_EQ(200, page_width);
       EXPECT_EQ(300, page_height);
       ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-      CompareBitmap(bitmap.get(), page_width, page_height,
-                    RectanglesChecksum());
+      CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                              pdfium::kRectanglesPng);
     }
 
     FPDFPage_SetMediaBox(page.get(), 20, 30, 100, 150);
@@ -425,8 +423,8 @@
       EXPECT_EQ(200, page_width);
       EXPECT_EQ(300, page_height);
       ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-      CompareBitmap(bitmap.get(), page_width, page_height,
-                    RectanglesChecksum());
+      CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                              pdfium::kRectanglesPng);
     }
 
     {
@@ -443,8 +441,8 @@
       EXPECT_EQ(200, page_width);
       EXPECT_EQ(300, page_height);
       ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-      CompareBitmap(bitmap.get(), page_width, page_height,
-                    RectanglesChecksum());
+      CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                              pdfium::kRectanglesPng);
     }
   }
 
@@ -484,8 +482,8 @@
       EXPECT_EQ(200, page_width);
       EXPECT_EQ(300, page_height);
       ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-      CompareBitmap(bitmap.get(), page_width, page_height,
-                    RectanglesChecksum());
+      CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                              pdfium::kRectanglesPng);
     }
 
     {
@@ -502,8 +500,8 @@
       EXPECT_EQ(200, page_width);
       EXPECT_EQ(300, page_height);
       ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-      CompareBitmap(bitmap.get(), page_width, page_height,
-                    RectanglesChecksum());
+      CompareBitmapToPngWithExpectationSuffix(bitmap.get(),
+                                              pdfium::kRectanglesPng);
     }
   }
 
diff --git a/fpdfsdk/fpdf_view_embeddertest.cpp b/fpdfsdk/fpdf_view_embeddertest.cpp
index 10464b8..02b6ceb 100644
--- a/fpdfsdk/fpdf_view_embeddertest.cpp
+++ b/fpdfsdk/fpdf_view_embeddertest.cpp
@@ -8,6 +8,7 @@
 #include <limits>
 #include <memory>
 #include <string>
+#include <string_view>
 #include <utility>
 #include <vector>
 
@@ -40,8 +41,6 @@
 #include "third_party/skia/include/core/SkSurface.h"          // nogncheck
 #endif  // defined(PDF_USE_SKIA)
 
-using pdfium::ManyRectanglesChecksum;
-
 namespace {
 
 constexpr char kFirstAlternate[] = "FirstAlternate";
@@ -159,16 +158,37 @@
 
 class FPDFViewEmbedderTest : public EmbedderTest {
  protected:
+  ScopedFPDFBitmap RenderPageBitmapWithMatrix(FPDF_PAGE page,
+                                              int bitmap_width,
+                                              int bitmap_height,
+                                              const FS_MATRIX& matrix,
+                                              const FS_RECTF& rect) {
+    ScopedFPDFBitmap bitmap(FPDFBitmap_Create(bitmap_width, bitmap_height, 0));
+    EXPECT_TRUE(FPDFBitmap_FillRect(bitmap.get(), 0, 0, bitmap_width,
+                                    bitmap_height, 0xFFFFFFFF));
+    FPDF_RenderPageBitmapWithMatrix(bitmap.get(), page, &matrix, &rect, 0);
+    return bitmap;
+  }
+
+  void TestRenderPageBitmapWithMatrixToPng(
+      FPDF_PAGE page,
+      int bitmap_width,
+      int bitmap_height,
+      const FS_MATRIX& matrix,
+      const FS_RECTF& rect,
+      std::string_view expectation_png_name) {
+    ScopedFPDFBitmap bitmap = RenderPageBitmapWithMatrix(
+        page, bitmap_width, bitmap_height, matrix, rect);
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(), expectation_png_name);
+  }
   void TestRenderPageBitmapWithMatrix(FPDF_PAGE page,
                                       int bitmap_width,
                                       int bitmap_height,
                                       const FS_MATRIX& matrix,
                                       const FS_RECTF& rect,
                                       const char* expected_checksum) {
-    ScopedFPDFBitmap bitmap(FPDFBitmap_Create(bitmap_width, bitmap_height, 0));
-    ASSERT_TRUE(FPDFBitmap_FillRect(bitmap.get(), 0, 0, bitmap_width,
-                                    bitmap_height, 0xFFFFFFFF));
-    FPDF_RenderPageBitmapWithMatrix(bitmap.get(), page, &matrix, &rect, 0);
+    ScopedFPDFBitmap bitmap = RenderPageBitmapWithMatrix(
+        page, bitmap_width, bitmap_height, matrix, rect);
     CompareBitmap(bitmap.get(), bitmap_width, bitmap_height, expected_checksum);
   }
 
@@ -191,6 +211,14 @@
     CompareBitmap(bitmap.get(), bitmap_width, bitmap_height, expected_checksum);
   }
 
+  void TestRenderPageBitmapWithInternalMemoryToPng(
+      FPDF_PAGE page,
+      int format,
+      std::string_view expectation_png_name) {
+    TestRenderPageBitmapWithInternalMemoryAndStrideToPng(
+        page, format, /*bitmap_stride=*/0, expectation_png_name);
+  }
+
   void TestRenderPageBitmapWithInternalMemory(FPDF_PAGE page,
                                               int format,
                                               const char* expected_checksum) {
@@ -198,6 +226,22 @@
         page, format, /*bitmap_stride=*/0, expected_checksum);
   }
 
+  void TestRenderPageBitmapWithInternalMemoryAndStrideToPng(
+      FPDF_PAGE page,
+      int format,
+      int bitmap_stride,
+      std::string_view expectation_png_name) {
+    int bitmap_width = static_cast<int>(FPDF_GetPageWidth(page));
+    int bitmap_height = static_cast<int>(FPDF_GetPageHeight(page));
+    int bytes_per_pixel = BytesPerPixelForFormat(format);
+    EXPECT_NE(0, bytes_per_pixel);
+
+    ScopedFPDFBitmap bitmap(FPDFBitmap_CreateEx(
+        bitmap_width, bitmap_height, format, nullptr, bitmap_stride));
+    ASSERT_TRUE(bitmap);
+    RenderPageToBitmapAndCheckToPng(page, bitmap.get(), expectation_png_name);
+  }
+
   void TestRenderPageBitmapWithInternalMemoryAndStride(
       FPDF_PAGE page,
       int format,
@@ -210,21 +254,43 @@
 
     ScopedFPDFBitmap bitmap(FPDFBitmap_CreateEx(
         bitmap_width, bitmap_height, format, nullptr, bitmap_stride));
+    ASSERT_TRUE(bitmap);
     RenderPageToBitmapAndCheck(page, bitmap.get(), expected_checksum);
   }
 
+  int GetBitmapStride(FPDF_PAGE page, int format) {
+    int bitmap_width = static_cast<int>(FPDF_GetPageWidth(page));
+    int bytes_per_pixel = BytesPerPixelForFormat(format);
+    EXPECT_NE(0, bytes_per_pixel);
+
+    int bitmap_stride = bytes_per_pixel * bitmap_width;
+    return bitmap_stride;
+  }
+  void TestRenderPageBitmapWithExternalMemoryToPng(
+      FPDF_PAGE page,
+      int format,
+      std::string_view expectation_png_name) {
+    int bitmap_stride = GetBitmapStride(page, format);
+    return TestRenderPageBitmapWithExternalMemoryImplToPng(
+        page, format, bitmap_stride, expectation_png_name);
+  }
+
   void TestRenderPageBitmapWithExternalMemory(FPDF_PAGE page,
                                               int format,
                                               const char* expected_checksum) {
-    int bitmap_width = static_cast<int>(FPDF_GetPageWidth(page));
-    int bytes_per_pixel = BytesPerPixelForFormat(format);
-    ASSERT_NE(0, bytes_per_pixel);
-
-    int bitmap_stride = bytes_per_pixel * bitmap_width;
+    int bitmap_stride = GetBitmapStride(page, format);
     return TestRenderPageBitmapWithExternalMemoryImpl(
         page, format, bitmap_stride, expected_checksum);
   }
 
+  void TestRenderPageBitmapWithExternalMemoryAndNoStrideToPng(
+      FPDF_PAGE page,
+      int format,
+      std::string_view expectation_png_name) {
+    return TestRenderPageBitmapWithExternalMemoryImplToPng(
+        page, format, /*bitmap_stride=*/0, expectation_png_name);
+  }
+
   void TestRenderPageBitmapWithExternalMemoryAndNoStride(
       FPDF_PAGE page,
       int format,
@@ -234,7 +300,7 @@
   }
 
 #if defined(PDF_USE_SKIA)
-  ScopedFPDFBitmap GetSkpBitmap(FPDF_PAGE page) {
+  void TestRenderPageSkpToPng(FPDF_PAGE page, std::string_view png_name) {
     int width = static_cast<int>(FPDF_GetPageWidth(page));
     int height = static_cast<int>(FPDF_GetPageHeight(page));
 
@@ -250,20 +316,10 @@
       EXPECT_TRUE(picture);
     }
 
-    return SkPictureToPdfiumBitmap(std::move(picture),
-                                   SkISize::Make(width, height));
+    ScopedFPDFBitmap bitmap = SkPictureToPdfiumBitmap(
+        std::move(picture), SkISize::Make(width, height));
+    CompareBitmapToPngWithExpectationSuffix(bitmap.get(), png_name);
   }
-
-  void TestRenderPageSkp(FPDF_PAGE page, const char* expected_checksum) {
-    int width = static_cast<int>(FPDF_GetPageWidth(page));
-    int height = static_cast<int>(FPDF_GetPageHeight(page));
-    CompareBitmap(GetSkpBitmap(page).get(), width, height, expected_checksum);
-  }
-
-  void TestRenderPageSkpToPng(FPDF_PAGE page, std::string_view png_name) {
-    CompareBitmapToPng(GetSkpBitmap(page).get(), png_name);
-  }
-
 #endif  // defined(PDF_USE_SKIA)
 
  private:
@@ -281,6 +337,21 @@
     return bitmap;
   }
 
+  void TestRenderPageBitmapWithExternalMemoryImplToPng(
+      FPDF_PAGE page,
+      int format,
+      int bitmap_stride,
+      std::string_view expectation_png_name) {
+    int bitmap_width = static_cast<int>(FPDF_GetPageWidth(page));
+    int bitmap_height = static_cast<int>(FPDF_GetPageHeight(page));
+
+    std::vector<uint8_t> external_memory(bitmap_stride * bitmap_height);
+    ScopedFPDFBitmap bitmap(FPDFBitmap_CreateEx(bitmap_width, bitmap_height,
+                                                format, external_memory.data(),
+                                                bitmap_stride));
+    RenderPageToBitmapAndCheckToPng(page, bitmap.get(), expectation_png_name);
+  }
+
   void TestRenderPageBitmapWithExternalMemoryImpl(
       FPDF_PAGE page,
       int format,
@@ -296,9 +367,7 @@
     RenderPageToBitmapAndCheck(page, bitmap.get(), expected_checksum);
   }
 
-  void RenderPageToBitmapAndCheck(FPDF_PAGE page,
-                                  FPDF_BITMAP bitmap,
-                                  const char* expected_checksum) {
+  void RenderPageToBitmap(FPDF_PAGE page, FPDF_BITMAP bitmap) {
     int bitmap_width = FPDFBitmap_GetWidth(bitmap);
     int bitmap_height = FPDFBitmap_GetHeight(bitmap);
     EXPECT_EQ(bitmap_width, static_cast<int>(FPDF_GetPageWidth(page)));
@@ -307,6 +376,20 @@
                                     0xFFFFFFFF));
     FPDF_RenderPageBitmap(bitmap, page, 0, 0, bitmap_width, bitmap_height, 0,
                           FPDF_ANNOT);
+  }
+  void RenderPageToBitmapAndCheckToPng(FPDF_PAGE page,
+                                       FPDF_BITMAP bitmap,
+                                       std::string_view expectation_png_name) {
+    RenderPageToBitmap(page, bitmap);
+    CompareBitmapToPngWithExpectationSuffix(bitmap, expectation_png_name);
+  }
+
+  void RenderPageToBitmapAndCheck(FPDF_PAGE page,
+                                  FPDF_BITMAP bitmap,
+                                  const char* expected_checksum) {
+    int bitmap_width = FPDFBitmap_GetWidth(bitmap);
+    int bitmap_height = FPDFBitmap_GetHeight(bitmap);
+    RenderPageToBitmap(page, bitmap);
     CompareBitmap(bitmap, bitmap_width, bitmap_height, expected_checksum);
   }
 };
@@ -1089,18 +1172,17 @@
   EXPECT_FLOAT_EQ(200, page_width);
   EXPECT_FLOAT_EQ(300, page_height);
 
-  using pdfium::RectanglesChecksum;
   ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
-  CompareBitmap(bitmap.get(), page_width, page_height, RectanglesChecksum());
+  CompareBitmapToPngWithExpectationSuffix(bitmap.get(), pdfium::kRectanglesPng);
 
   FS_RECTF page_rect{0, 0, page_width, page_height};
 
   // Try rendering with an identity matrix. The output should be the same as
   // the RenderLoadedPage() output.
   FS_MATRIX identity_matrix{1, 0, 0, 1, 0, 0};
-  TestRenderPageBitmapWithMatrix(page.get(), page_width, page_height,
-                                 identity_matrix, page_rect,
-                                 RectanglesChecksum());
+  TestRenderPageBitmapWithMatrixToPng(page.get(), page_width, page_height,
+                                      identity_matrix, page_rect,
+                                      pdfium::kRectanglesPng);
 
   // Again render with an identity matrix but with a smaller clipping rect.
   FS_RECTF middle_of_page_rect{page_width / 4, page_height / 4,
@@ -1614,24 +1696,24 @@
   ScopedPage page = LoadScopedPage(0);
   ASSERT_TRUE(page);
 
-  TestRenderPageBitmapWithFlags(page.get(), 0, ManyRectanglesChecksum());
-  TestRenderPageBitmapWithFlags(page.get(), FPDF_ANNOT,
-                                ManyRectanglesChecksum());
-  TestRenderPageBitmapWithFlags(page.get(), FPDF_LCD_TEXT,
-                                ManyRectanglesChecksum());
-  TestRenderPageBitmapWithFlags(page.get(), FPDF_NO_NATIVETEXT,
-                                ManyRectanglesChecksum());
+  TestRenderPageBitmapWithFlagsToPng(page.get(), 0, pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithFlagsToPng(page.get(), FPDF_ANNOT,
+                                     pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithFlagsToPng(page.get(), FPDF_LCD_TEXT,
+                                     pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithFlagsToPng(page.get(), FPDF_NO_NATIVETEXT,
+                                     pdfium::kManyRectanglesPng);
   TestRenderPageBitmapWithFlags(page.get(), FPDF_GRAYSCALE, grayscale_checksum);
-  TestRenderPageBitmapWithFlags(page.get(), FPDF_RENDER_LIMITEDIMAGECACHE,
-                                ManyRectanglesChecksum());
-  TestRenderPageBitmapWithFlags(page.get(), FPDF_RENDER_FORCEHALFTONE,
-                                ManyRectanglesChecksum());
-  TestRenderPageBitmapWithFlags(page.get(), FPDF_PRINTING,
-                                ManyRectanglesChecksum());
-  TestRenderPageBitmapWithFlags(page.get(), FPDF_RENDER_NO_SMOOTHTEXT,
-                                ManyRectanglesChecksum());
-  TestRenderPageBitmapWithFlags(page.get(), FPDF_RENDER_NO_SMOOTHIMAGE,
-                                ManyRectanglesChecksum());
+  TestRenderPageBitmapWithFlagsToPng(page.get(), FPDF_RENDER_LIMITEDIMAGECACHE,
+                                     pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithFlagsToPng(page.get(), FPDF_RENDER_FORCEHALFTONE,
+                                     pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithFlagsToPng(page.get(), FPDF_PRINTING,
+                                     pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithFlagsToPng(page.get(), FPDF_RENDER_NO_SMOOTHTEXT,
+                                     pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithFlagsToPng(page.get(), FPDF_RENDER_NO_SMOOTHIMAGE,
+                                     pdfium::kManyRectanglesPng);
   TestRenderPageBitmapWithFlags(page.get(), FPDF_RENDER_NO_SMOOTHPATH,
                                 no_smoothpath_checksum);
 }
@@ -1679,35 +1761,35 @@
                                                     gray_checksum);
 
   static constexpr int kBgrxStride = 800;  // Width of 200 * 32 bits per pixel.
-  TestRenderPageBitmapWithInternalMemory(page.get(), FPDFBitmap_BGRx,
-                                         ManyRectanglesChecksum());
-  TestRenderPageBitmapWithInternalMemoryAndStride(
-      page.get(), FPDFBitmap_BGRx, kBgrxStride, ManyRectanglesChecksum());
-  TestRenderPageBitmapWithExternalMemory(page.get(), FPDFBitmap_BGRx,
-                                         ManyRectanglesChecksum());
-  TestRenderPageBitmapWithExternalMemoryAndNoStride(page.get(), FPDFBitmap_BGRx,
-                                                    ManyRectanglesChecksum());
+  TestRenderPageBitmapWithInternalMemoryToPng(page.get(), FPDFBitmap_BGRx,
+                                              pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithInternalMemoryAndStrideToPng(
+      page.get(), FPDFBitmap_BGRx, kBgrxStride, pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithExternalMemoryToPng(page.get(), FPDFBitmap_BGRx,
+                                              pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithExternalMemoryAndNoStrideToPng(
+      page.get(), FPDFBitmap_BGRx, pdfium::kManyRectanglesPng);
 
-  TestRenderPageBitmapWithInternalMemory(page.get(), FPDFBitmap_BGRA,
-                                         ManyRectanglesChecksum());
-  TestRenderPageBitmapWithInternalMemoryAndStride(
-      page.get(), FPDFBitmap_BGRA, kBgrxStride, ManyRectanglesChecksum());
-  TestRenderPageBitmapWithExternalMemory(page.get(), FPDFBitmap_BGRA,
-                                         ManyRectanglesChecksum());
-  TestRenderPageBitmapWithExternalMemoryAndNoStride(page.get(), FPDFBitmap_BGRA,
-                                                    ManyRectanglesChecksum());
+  TestRenderPageBitmapWithInternalMemoryToPng(page.get(), FPDFBitmap_BGRA,
+                                              pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithInternalMemoryAndStrideToPng(
+      page.get(), FPDFBitmap_BGRA, kBgrxStride, pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithExternalMemoryToPng(page.get(), FPDFBitmap_BGRA,
+                                              pdfium::kManyRectanglesPng);
+  TestRenderPageBitmapWithExternalMemoryAndNoStrideToPng(
+      page.get(), FPDFBitmap_BGRA, pdfium::kManyRectanglesPng);
 
 #if defined(PDF_USE_SKIA)
   if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
-    TestRenderPageBitmapWithInternalMemory(page.get(), FPDFBitmap_BGRA_Premul,
-                                           ManyRectanglesChecksum());
-    TestRenderPageBitmapWithInternalMemoryAndStride(
+    TestRenderPageBitmapWithInternalMemoryToPng(
+        page.get(), FPDFBitmap_BGRA_Premul, pdfium::kManyRectanglesPng);
+    TestRenderPageBitmapWithInternalMemoryAndStrideToPng(
         page.get(), FPDFBitmap_BGRA_Premul, kBgrxStride,
-        ManyRectanglesChecksum());
-    TestRenderPageBitmapWithExternalMemory(page.get(), FPDFBitmap_BGRA_Premul,
-                                           ManyRectanglesChecksum());
-    TestRenderPageBitmapWithExternalMemoryAndNoStride(
-        page.get(), FPDFBitmap_BGRA_Premul, ManyRectanglesChecksum());
+        pdfium::kManyRectanglesPng);
+    TestRenderPageBitmapWithExternalMemoryToPng(
+        page.get(), FPDFBitmap_BGRA_Premul, pdfium::kManyRectanglesPng);
+    TestRenderPageBitmapWithExternalMemoryAndNoStrideToPng(
+        page.get(), FPDFBitmap_BGRA_Premul, pdfium::kManyRectanglesPng);
   }
 #endif
 }
@@ -2115,7 +2197,7 @@
   ScopedPage page = LoadScopedPage(0);
   ASSERT_TRUE(page);
 
-  TestRenderPageSkp(page.get(), pdfium::RectanglesChecksum());
+  TestRenderPageSkpToPng(page.get(), pdfium::kRectanglesPng);
 }
 
 TEST_F(FPDFViewEmbedderTest, RenderXfaPageToSkp) {
diff --git a/public/fpdfview.h b/public/fpdfview.h
index d96556b..499e954 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -1088,6 +1088,7 @@
 
 // More DIB formats
 // Unknown or unsupported format.
+// All of the colors are listed in order of LSB to MSB.
 #define FPDFBitmap_Unknown 0
 // Gray scale bitmap, one byte per pixel.
 #define FPDFBitmap_Gray 1
diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp
index cf37d64..e56bcfe 100644
--- a/testing/embedder_test.cpp
+++ b/testing/embedder_test.cpp
@@ -20,6 +20,7 @@
 #include "core/fxcrt/numerics/checked_math.h"
 #include "core/fxcrt/numerics/safe_conversions.h"
 #include "core/fxge/cfx_defaultrenderdevice.h"
+#include "core/fxge/dib/fx_dib.h"
 #include "fpdfsdk/cpdfsdk_helpers.h"
 #include "public/cpp/fpdf_scopers.h"
 #include "public/fpdf_dataavail.h"
@@ -352,6 +353,25 @@
   return pixels_different;
 }
 
+#ifdef PDF_USE_SKIA
+int CompareBGRxPremultBitmapToPng(pdfium::span<const uint8_t> bitmap_span,
+                                  size_t bitmap_stride,
+                                  const DecodedPng& decoded_png) {
+  std::vector<uint8_t> bitmap_data(bitmap_span.begin(), bitmap_span.end());
+  pdfium::span<uint8_t> converted_bitmap_span{bitmap_data};
+
+  for (int h = 0; h < decoded_png.height; ++h) {
+    auto bitmap_row = fxcrt::reinterpret_span<FX_BGRA_STRUCT<uint8_t>>(
+        converted_bitmap_span.first(bitmap_stride));
+    converted_bitmap_span = converted_bitmap_span.subspan(bitmap_stride);
+    for (int w = 0; w < decoded_png.width; ++w) {
+      bitmap_row[w] = UnPreMultiplyColor(bitmap_row[w]);
+    }
+  }
+  return CompareBGRxBitmapToPng(bitmap_span, bitmap_stride, decoded_png);
+}
+#endif  // PDF_USE_SKIA
+
 void CompareBitmapToPngData(FPDF_BITMAP bitmap,
                             pdfium::span<const uint8_t> png_data) {
   DecodedPng decoded_png = DecodePngData(png_data);
@@ -380,6 +400,12 @@
           CompareBGRxBitmapToPng(bitmap_span, stride, decoded_png);
       break;
     }
+#ifdef PDF_USE_SKIA
+    case FPDFBitmap_BGRA_Premul:
+      pixels_different =
+          CompareBGRxPremultBitmapToPng(bitmap_span, stride, decoded_png);
+      break;
+#endif  // PDF_USE_SKIA
     default:
       // Support other formats as-needed.
       NOTREACHED();
diff --git a/testing/embedder_test_constants.cpp b/testing/embedder_test_constants.cpp
index 0c6dd40..e4fcd2a 100644
--- a/testing/embedder_test_constants.cpp
+++ b/testing/embedder_test_constants.cpp
@@ -50,20 +50,6 @@
 #endif
 }
 
-const char* ManyRectanglesChecksum() {
-  if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
-    return "4e7e280c1597222afcb0ee3bb90ec119";
-  }
-  return "b0170c575b65ecb93ebafada0ff0f038";
-}
-
-const char* RectanglesChecksum() {
-  if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
-    return "b4e411a6b5ffa59a50efede2efece597";
-  }
-  return "0a90de37f52127619c3dfb642b5fa2fe";
-}
-
 const char* TextFormChecksum() {
   if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
 #if BUILDFLAG(IS_WIN)
diff --git a/testing/embedder_test_constants.h b/testing/embedder_test_constants.h
index 41899cc..9590c4d 100644
--- a/testing/embedder_test_constants.h
+++ b/testing/embedder_test_constants.h
@@ -25,11 +25,11 @@
 // MD5 hash for rendering hello_world.pdf after removing "Goodbye, world!".
 const char* HelloWorldRemovedChecksum();
 
-// MD5 hash for rendering many_rectangles.pdf.
-const char* ManyRectanglesChecksum();
+// Expectation file basename for rendering many_rectangles.pdf.
+inline constexpr char kManyRectanglesPng[] = "many_rectangles";
 
-// MD5 hash for rendering rectangles.pdf.
-const char* RectanglesChecksum();
+// Expectation file basename for rendering rectangles.pdf.
+inline constexpr char kRectanglesPng[] = "rectangles";
 
 // MD5 hash for rendering text_form.pdf.
 const char* TextFormChecksum();
diff --git a/testing/resources/embedder_tests/many_rectangles_agg.png b/testing/resources/embedder_tests/many_rectangles_agg.png
new file mode 100644
index 0000000..430d04c
--- /dev/null
+++ b/testing/resources/embedder_tests/many_rectangles_agg.png
Binary files differ
diff --git a/testing/resources/embedder_tests/many_rectangles_skia.png b/testing/resources/embedder_tests/many_rectangles_skia.png
new file mode 100644
index 0000000..5137ea7
--- /dev/null
+++ b/testing/resources/embedder_tests/many_rectangles_skia.png
Binary files differ
diff --git a/testing/resources/embedder_tests/rectangles_agg.png b/testing/resources/embedder_tests/rectangles_agg.png
new file mode 100644
index 0000000..ee652fa
--- /dev/null
+++ b/testing/resources/embedder_tests/rectangles_agg.png
Binary files differ
diff --git a/testing/resources/embedder_tests/rectangles_skia.png b/testing/resources/embedder_tests/rectangles_skia.png
new file mode 100644
index 0000000..cc2399d
--- /dev/null
+++ b/testing/resources/embedder_tests/rectangles_skia.png
Binary files differ