Extend the JPEG BGR decode to ICCBased color spaces with sRGB profiles

For an ICCBased color space whose profile is recognized as sRGB,
CPDF_ICCBasedCS::TranslateImageLine() is exactly fxcodec::ReverseRGB(),
the same per-pixel RGB-to-BGR swap that ShouldDecodeJpegToBgr() already
folds into the decode for DeviceRGB and CalRGB.

Accept that case too. The component-count equality mirrors the guard in
TranslateScanline24bppDefaultDecode(), which only translates when the
sample count matches the color space; profiles that are not supported
fall back to the alternate color space's float conversion and profiles
that need a real ICC transform keep using the translate path, so
neither is captured.

Bug: 553831655
Change-Id: I428ae3d08d9020db3aa8840323433c948d7b0ea8
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/156090
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_dib.cpp b/core/fpdfapi/page/cpdf_dib.cpp
index 72ee8d9..6ab8004 100644
--- a/core/fpdfapi/page/cpdf_dib.cpp
+++ b/core/fpdfapi/page/cpdf_dib.cpp
@@ -16,6 +16,7 @@
 
 #include "core/fpdfapi/page/cpdf_colorspace.h"
 #include "core/fpdfapi/page/cpdf_docpagedata.h"
+#include "core/fpdfapi/page/cpdf_iccprofile.h"
 #include "core/fpdfapi/page/cpdf_image.h"
 #include "core/fpdfapi/page/cpdf_imageobject.h"
 #include "core/fpdfapi/page/cpdf_indexedcs.h"
@@ -522,19 +523,39 @@
   return LoadState::kSuccess;
 }
 
+bool CPDF_DIB::ComponentCountMatchesColorSpace() const {
+  return color_space_ && components_ == color_space_->ComponentCount();
+}
+
 // Whether the JPEG decoder should be asked to emit BGR-ordered scanlines.
 // Only true when GetScanline()'s only transformation of the decoded RGB
 // scanline would be TranslateScanline24bppDefaultDecode()'s per-pixel
 // RGB-to-BGR swap, which a BGR decode makes a pass-through:
 // - a default Decode array (no per-component decode arithmetic),
 // - no color key mask (its comparisons read components in R,G,B order),
-// - plain DeviceRGB or CalRGB (both translate as the bare swap; every
-//   other family goes through CPDF_ColorSpace::TranslateImageLine()),
+// - a color space whose whole translation is the bare swap: DeviceRGB,
+//   CalRGB, or ICCBased with an sRGB profile (whose TranslateImageLine()
+//   is exactly fxcodec::ReverseRGB()); every other case goes through a
+//   real conversion,
 // - 3 components at 8 bpc (the swap case).
 bool CPDF_DIB::ShouldDecodeJpegToBgr() const {
-  return default_decode_ && !color_key_ && components_ == 3 && bpc_ == 8 &&
-         (family_ == CPDF_ColorSpace::Family::kDeviceRGB ||
-          family_ == CPDF_ColorSpace::Family::kCalRGB);
+  if (!default_decode_ || color_key_ || components_ != 3 || bpc_ != 8) {
+    return false;
+  }
+  if (family_ == CPDF_ColorSpace::Family::kDeviceRGB ||
+      family_ == CPDF_ColorSpace::Family::kCalRGB) {
+    return true;
+  }
+  // For an sRGB profile, CPDF_ICCBasedCS::TranslateImageLine() is exactly
+  // fxcodec::ReverseRGB(), so the whole translation is the swap. Any other
+  // profile converts through the alternate color space instead, which is not
+  // a swap, so those keep the translate path.
+  if (family_ == CPDF_ColorSpace::Family::kICCBased &&
+      ComponentCountMatchesColorSpace()) {
+    RetainPtr<CPDF_IccProfile> profile = color_space_->GetIccProfile();
+    return profile && profile->IsSRGB();
+  }
+  return false;
 }
 
 bool CPDF_DIB::CreateDCTDecoder(pdfium::span<const uint8_t> src_span,
@@ -1082,7 +1103,7 @@
       return false;
     }
 
-    if (components_ == color_space_->ComponentCount()) {
+    if (ComponentCountMatchesColorSpace()) {
       color_space_->TranslateImageLine(dest_scan, src_scan, GetWidth(),
                                        GetWidth(), GetHeight(), TransMask());
     }
diff --git a/core/fpdfapi/page/cpdf_dib.h b/core/fpdfapi/page/cpdf_dib.h
index 491313e..737da04 100644
--- a/core/fpdfapi/page/cpdf_dib.h
+++ b/core/fpdfapi/page/cpdf_dib.h
@@ -100,6 +100,12 @@
   bool CreateDCTDecoder(pdfium::span<const uint8_t> src_span,
                         const CPDF_Dictionary* pParams,
                         uint8_t resolution_levels_to_skip);
+  // Whether `components_` matches the color space's own component count, which
+  // is the condition under which a scanline gets translated at all. The two
+  // can disagree because LoadColorInfo() overrides `components_` for an
+  // ICCBased color space named DeviceGray, DeviceRGB or DeviceCMYK. Returns
+  // false when there is no color space.
+  bool ComponentCountMatchesColorSpace() const;
   bool ShouldDecodeJpegToBgr() const;
   void TranslateScanline24bpp(pdfium::span<uint8_t> dest_scan,
                               pdfium::span<const uint8_t> src_scan) const;