Consolidate PNG encoding code
Move EncodePng() from testing/helpers/write.cc to
testing/utils/png_encode.cpp. Then reuse it in
testing/utils/bitmap_saver.cpp. Now BitmapSaver::WriteBitmapToPng()
knows how to handle pre-multiplied bitmaps.
Change-Id: I23907a52c93fa3009004ea44cc9853e4afd87fef
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/141273
Reviewed-by: Andy Phan <andyphan@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/testing/BUILD.gn b/testing/BUILD.gn
index 6c42ebd..2d0efe5 100644
--- a/testing/BUILD.gn
+++ b/testing/BUILD.gn
@@ -33,6 +33,8 @@
"utils/file_util.h",
"utils/hash.cpp",
"utils/hash.h",
+ "utils/png_encode.cpp",
+ "utils/png_encode.h",
]
data = [ "resources/" ]
public_deps = [
diff --git a/testing/helpers/write.cc b/testing/helpers/write.cc
index 6eb56a3..365eedf 100644
--- a/testing/helpers/write.cc
+++ b/testing/helpers/write.cc
@@ -19,13 +19,12 @@
#include "public/fpdf_edit.h"
#include "public/fpdf_thumbnail.h"
#include "testing/fx_string_testhelpers.h"
-#include "testing/image_diff/image_diff_png.h"
+#include "testing/utils/png_encode.h"
#ifdef PDF_ENABLE_SKIA
#include "third_party/skia/include/core/SkData.h" // nogncheck
#include "third_party/skia/include/core/SkImage.h" // nogncheck
#include "third_party/skia/include/core/SkPicture.h" // nogncheck
-#include "third_party/skia/include/core/SkPixmap.h" // nogncheck
#include "third_party/skia/include/core/SkSerialProcs.h" // nogncheck
#include "third_party/skia/include/core/SkStream.h" // nogncheck
#ifdef PDF_ENABLE_RUST_PNG
@@ -190,64 +189,6 @@
NOTREACHED();
}
-#ifdef PDF_ENABLE_SKIA
-std::vector<uint8_t> ConvertToStraightAlpha(pdfium::span<const uint8_t> input,
- int width,
- int height,
- int row_byte_width) {
- SkImageInfo premul_alpha_image_info = SkImageInfo::Make(
- width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
- SkPixmap src_pixmap(premul_alpha_image_info, input.data(), row_byte_width);
-
- std::vector<uint8_t> result(input.size());
- SkImageInfo straight_alpha_image_info = SkImageInfo::Make(
- width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
- SkPixmap dst_pixmap(straight_alpha_image_info, result.data(), row_byte_width);
-
- CHECK(src_pixmap.readPixels(dst_pixmap));
- return result;
-}
-#endif
-
-std::vector<uint8_t> EncodePng(pdfium::span<const uint8_t> input,
- int width,
- int height,
- int stride,
- int format) {
- std::vector<uint8_t> png;
- switch (format) {
- case FPDFBitmap_Unknown:
- break;
- case FPDFBitmap_Gray:
- png = image_diff_png::EncodeGrayPNG(input, width, height, stride);
- break;
- case FPDFBitmap_BGR:
- png = image_diff_png::EncodeBGRPNG(input, width, height, stride);
- break;
- case FPDFBitmap_BGRx:
- png = image_diff_png::EncodeBGRAPNG(input, width, height, stride,
- /*discard_transparency=*/true);
- break;
- case FPDFBitmap_BGRA:
- png = image_diff_png::EncodeBGRAPNG(input, width, height, stride,
- /*discard_transparency=*/false);
- break;
-#ifdef PDF_ENABLE_SKIA
- case FPDFBitmap_BGRA_Premul: {
- std::vector<uint8_t> input_with_straight_alpha =
- ConvertToStraightAlpha(input, width, height, stride);
- png = image_diff_png::EncodeBGRAPNG(input_with_straight_alpha, width,
- height, stride,
- /*discard_transparency=*/false);
- break;
- }
-#endif
- default:
- NOTREACHED();
- }
- return png;
-}
-
#ifdef _WIN32
int CALLBACK EnhMetaFileProc(HDC hdc,
HANDLETABLE* handle_table,
diff --git a/testing/utils/bitmap_saver.cpp b/testing/utils/bitmap_saver.cpp
index 617c4f7..f5809e2 100644
--- a/testing/utils/bitmap_saver.cpp
+++ b/testing/utils/bitmap_saver.cpp
@@ -9,7 +9,7 @@
#include "core/fxcrt/check.h"
#include "core/fxcrt/fx_safe_types.h"
-#include "testing/image_diff/image_diff_png.h"
+#include "testing/utils/png_encode.h"
// static
void BitmapSaver::WriteBitmapToPng(FPDF_BITMAP bitmap,
@@ -26,17 +26,8 @@
pdfium::span(static_cast<const uint8_t*>(FPDFBitmap_GetBuffer(bitmap)),
pdfium::ValueOrDieForType<size_t>(size));
- std::vector<uint8_t> png;
- int format = FPDFBitmap_GetFormat(bitmap);
- if (format == FPDFBitmap_Gray) {
- png = image_diff_png::EncodeGrayPNG(input, width, height, stride);
- } else if (format == FPDFBitmap_BGR) {
- png = image_diff_png::EncodeBGRPNG(input, width, height, stride);
- } else {
- png = image_diff_png::EncodeBGRAPNG(input, width, height, stride,
- /*discard_transparency=*/false);
- }
-
+ std::vector<uint8_t> png =
+ EncodePng(input, width, height, stride, FPDFBitmap_GetFormat(bitmap));
DCHECK(!png.empty());
DCHECK(filename.size() < 256u);
diff --git a/testing/utils/png_encode.cpp b/testing/utils/png_encode.cpp
new file mode 100644
index 0000000..fb15f7e
--- /dev/null
+++ b/testing/utils/png_encode.cpp
@@ -0,0 +1,79 @@
+// Copyright 2026 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/utils/png_encode.h"
+
+#include "core/fxcrt/check.h"
+#include "core/fxcrt/notreached.h"
+#include "public/fpdfview.h"
+#include "testing/image_diff/image_diff_png.h"
+
+#ifdef PDF_ENABLE_SKIA
+#include "third_party/skia/include/core/SkAlphaType.h" // nogncheck
+#include "third_party/skia/include/core/SkColorType.h" // nogncheck
+#include "third_party/skia/include/core/SkImageInfo.h" // nogncheck
+#include "third_party/skia/include/core/SkPixmap.h" // nogncheck
+#endif
+
+namespace {
+
+#ifdef PDF_ENABLE_SKIA
+std::vector<uint8_t> ConvertToStraightAlpha(pdfium::span<const uint8_t> input,
+ int width,
+ int height,
+ int row_byte_width) {
+ SkImageInfo premul_alpha_image_info = SkImageInfo::Make(
+ width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
+ SkPixmap src_pixmap(premul_alpha_image_info, input.data(), row_byte_width);
+
+ std::vector<uint8_t> result(input.size());
+ SkImageInfo straight_alpha_image_info = SkImageInfo::Make(
+ width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
+ SkPixmap dst_pixmap(straight_alpha_image_info, result.data(), row_byte_width);
+
+ CHECK(src_pixmap.readPixels(dst_pixmap));
+ return result;
+}
+#endif
+
+} // namespace
+
+std::vector<uint8_t> EncodePng(pdfium::span<const uint8_t> input,
+ int width,
+ int height,
+ int stride,
+ int format) {
+ std::vector<uint8_t> png;
+ switch (format) {
+ case FPDFBitmap_Unknown:
+ break;
+ case FPDFBitmap_Gray:
+ png = image_diff_png::EncodeGrayPNG(input, width, height, stride);
+ break;
+ case FPDFBitmap_BGR:
+ png = image_diff_png::EncodeBGRPNG(input, width, height, stride);
+ break;
+ case FPDFBitmap_BGRx:
+ png = image_diff_png::EncodeBGRAPNG(input, width, height, stride,
+ /*discard_transparency=*/true);
+ break;
+ case FPDFBitmap_BGRA:
+ png = image_diff_png::EncodeBGRAPNG(input, width, height, stride,
+ /*discard_transparency=*/false);
+ break;
+#ifdef PDF_ENABLE_SKIA
+ case FPDFBitmap_BGRA_Premul: {
+ std::vector<uint8_t> input_with_straight_alpha =
+ ConvertToStraightAlpha(input, width, height, stride);
+ png = image_diff_png::EncodeBGRAPNG(input_with_straight_alpha, width,
+ height, stride,
+ /*discard_transparency=*/false);
+ break;
+ }
+#endif
+ default:
+ NOTREACHED();
+ }
+ return png;
+}
diff --git a/testing/utils/png_encode.h b/testing/utils/png_encode.h
new file mode 100644
index 0000000..4547d67
--- /dev/null
+++ b/testing/utils/png_encode.h
@@ -0,0 +1,20 @@
+// Copyright 2026 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TESTING_UTILS_PNG_ENCODE_H_
+#define TESTING_UTILS_PNG_ENCODE_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "core/fxcrt/span.h"
+
+std::vector<uint8_t> EncodePng(pdfium::span<const uint8_t> input,
+ int width,
+ int height,
+ int stride,
+ int format);
+
+#endif // TESTING_UTILS_PNG_ENCODE_H_