From 6791295a4e8c99097e6d75870871e128284f8cb5 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Fri, 10 Mar 2017 15:15:33 -0500 Subject: Normalize channels when transforming CMYK to RGB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PDF spec, section 'DeviceCMYK Color Space' states that: 'Each component is specified by a number in the range 0.0 to 1.0' BUG=chromium:699459 Change-Id: Ie476bbe8740c7b1b33c80be3e3dc4207df5e6e28 Reviewed-on: https://pdfium-review.googlesource.com/2954 Commit-Queue: Nicolás Peña Reviewed-by: Tom Sepez --- BUILD.gn | 1 + core/fpdfapi/page/cpdf_devicecs_unittest.cpp | 115 +++++++++++++++++++++++++++ core/fpdfapi/page/fpdf_page_colors.cpp | 12 +-- 3 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 core/fpdfapi/page/cpdf_devicecs_unittest.cpp diff --git a/BUILD.gn b/BUILD.gn index 8656ee7fb5..2a5a6bd39d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1745,6 +1745,7 @@ test("pdfium_unittests") { "core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp", "core/fpdfapi/font/fpdf_font_cid_unittest.cpp", "core/fpdfapi/font/fpdf_font_unittest.cpp", + "core/fpdfapi/page/cpdf_devicecs_unittest.cpp", "core/fpdfapi/page/cpdf_streamcontentparser_unittest.cpp", "core/fpdfapi/page/cpdf_streamparser_unittest.cpp", "core/fpdfapi/parser/cpdf_array_unittest.cpp", diff --git a/core/fpdfapi/page/cpdf_devicecs_unittest.cpp b/core/fpdfapi/page/cpdf_devicecs_unittest.cpp new file mode 100644 index 0000000000..287fc02fc4 --- /dev/null +++ b/core/fpdfapi/page/cpdf_devicecs_unittest.cpp @@ -0,0 +1,115 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/pageint.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(CPDF_DeviceCSTest, GetRGBFromGray) { + FX_FLOAT R; + FX_FLOAT G; + FX_FLOAT B; + CPDF_DeviceCS deviceGray(nullptr, PDFCS_DEVICEGRAY); + + // Test normal values. For gray, only first value from buf should be used. + FX_FLOAT buf[3] = {0.43f, 0.11f, 0.34f}; + ASSERT_TRUE(deviceGray.GetRGB(buf, R, G, B)); + EXPECT_EQ(0.43f, R); + EXPECT_EQ(0.43f, G); + EXPECT_EQ(0.43f, B); + buf[0] = 0.872f; + ASSERT_TRUE(deviceGray.GetRGB(buf, R, G, B)); + EXPECT_EQ(0.872f, R); + EXPECT_EQ(0.872f, G); + EXPECT_EQ(0.872f, B); + + // Test boundary values + buf[0] = {0.0f}; + ASSERT_TRUE(deviceGray.GetRGB(buf, R, G, B)); + EXPECT_EQ(0.0f, R); + EXPECT_EQ(0.0f, G); + EXPECT_EQ(0.0f, B); + buf[0] = 1.0f; + ASSERT_TRUE(deviceGray.GetRGB(buf, R, G, B)); + EXPECT_EQ(1.0f, R); + EXPECT_EQ(1.0f, G); + EXPECT_EQ(1.0f, B); + + // Test out of range values + buf[0] = -0.01f; + ASSERT_TRUE(deviceGray.GetRGB(buf, R, G, B)); + EXPECT_EQ(0.0f, R); + EXPECT_EQ(0.0f, G); + EXPECT_EQ(0.0f, B); + buf[0] = 12.5f; + ASSERT_TRUE(deviceGray.GetRGB(buf, R, G, B)); + EXPECT_EQ(1.0f, R); + EXPECT_EQ(1.0f, G); + EXPECT_EQ(1.0f, B); +} + +TEST(CPDF_DeviceCSTest, GetRGBFromRGB) { + FX_FLOAT R; + FX_FLOAT G; + FX_FLOAT B; + CPDF_DeviceCS deviceRGB(nullptr, PDFCS_DEVICERGB); + + // Test normal values + FX_FLOAT buf[3] = {0.13f, 1.0f, 0.652f}; + ASSERT_TRUE(deviceRGB.GetRGB(buf, R, G, B)); + EXPECT_EQ(0.13f, R); + EXPECT_EQ(1.0f, G); + EXPECT_EQ(0.652f, B); + buf[0] = 0.0f; + buf[1] = 0.52f; + buf[2] = 0.78f; + ASSERT_TRUE(deviceRGB.GetRGB(buf, R, G, B)); + EXPECT_EQ(0.0f, R); + EXPECT_EQ(0.52f, G); + EXPECT_EQ(0.78f, B); + + // Test out of range values + buf[0] = -10.5f; + buf[1] = 100.0f; + ASSERT_TRUE(deviceRGB.GetRGB(buf, R, G, B)); + EXPECT_EQ(0.0f, R); + EXPECT_EQ(1.0f, G); + EXPECT_EQ(0.78f, B); +} + +TEST(CPDF_DeviceCSTest, GetRGBFromCMYK) { + FX_FLOAT R; + FX_FLOAT G; + FX_FLOAT B; + CPDF_DeviceCS deviceCMYK(nullptr, PDFCS_DEVICECMYK); + // Use an error threshold because of the calculations used here. + FX_FLOAT eps = 1e-6f; + // Test normal values + FX_FLOAT buf[4] = {0.6f, 0.5f, 0.3f, 0.9f}; + ASSERT_TRUE(deviceCMYK.GetRGB(buf, R, G, B)); + EXPECT_TRUE(std::abs(0.0627451f - R) < eps); + EXPECT_TRUE(std::abs(0.0627451f - G) < eps); + EXPECT_TRUE(std::abs(0.105882f - B) < eps); + buf[0] = 0.15f; + buf[2] = 0.0f; + ASSERT_TRUE(deviceCMYK.GetRGB(buf, R, G, B)); + EXPECT_TRUE(std::abs(0.2f - R) < eps); + EXPECT_TRUE(std::abs(0.0862745f - G) < eps); + EXPECT_TRUE(std::abs(0.164706f - B) < eps); + buf[2] = 1.0f; + buf[3] = 0.0f; + ASSERT_TRUE(deviceCMYK.GetRGB(buf, R, G, B)); + EXPECT_TRUE(std::abs(0.850980f - R) < eps); + EXPECT_TRUE(std::abs(0.552941f - G) < eps); + EXPECT_TRUE(std::abs(0.156863f - B) < eps); + + // Test out of range values + buf[2] = 1.5f; + buf[3] = -0.6f; + ASSERT_TRUE(deviceCMYK.GetRGB(buf, R, G, B)); + EXPECT_TRUE(std::abs(0.850980f - R) < eps); + EXPECT_TRUE(std::abs(0.552941f - G) < eps); + EXPECT_TRUE(std::abs(0.156863f - B) < eps); +} diff --git a/core/fpdfapi/page/fpdf_page_colors.cpp b/core/fpdfapi/page/fpdf_page_colors.cpp index 69129e4f2b..54b61df975 100644 --- a/core/fpdfapi/page/fpdf_page_colors.cpp +++ b/core/fpdfapi/page/fpdf_page_colors.cpp @@ -46,13 +46,7 @@ void sRGB_to_AdobeCMYK(FX_FLOAT R, c = 1.0f - R; m = 1.0f - G; y = 1.0f - B; - k = c; - if (m < k) { - k = m; - } - if (y < k) { - k = y; - } + k = std::min(c, std::min(m, y)); } void ReverseRGB(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels) { @@ -101,7 +95,9 @@ bool CPDF_DeviceCS::GetRGB(FX_FLOAT* pBuf, G = 1.0f - std::min(1.0f, pBuf[1] + k); B = 1.0f - std::min(1.0f, pBuf[2] + k); } else { - AdobeCMYK_to_sRGB(pBuf[0], pBuf[1], pBuf[2], pBuf[3], R, G, B); + AdobeCMYK_to_sRGB(NormalizeChannel(pBuf[0]), NormalizeChannel(pBuf[1]), + NormalizeChannel(pBuf[2]), NormalizeChannel(pBuf[3]), + R, G, B); } break; default: -- cgit v1.2.3