Commit ca53cbe3 authored by David Bertoni's avatar David Bertoni Committed by Commit Bot

[Extensions] Added new function to evaluate icon visibility.

The new functions draw the icon into another bitmap, combining it with the background color to determine the visibility of the resulting icon.

Bug: 805600
Change-Id: I592ed5342d6eb3bfb6c36a4da7148280ed2a0f85
Reviewed-on: https://chromium-review.googlesource.com/c/1297398
Commit-Queue: David Bertoni <dbertoni@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602523}
parent ebc30455
......@@ -15,7 +15,9 @@
#include "base/strings/stringprintf.h"
#include "third_party/re2/src/re2/re2.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/utils/SkParse.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/color_utils.h"
......@@ -194,9 +196,51 @@ bool IsIconAtPathSufficientlyVisible(const base::FilePath& path) {
SkBitmap icon;
if (!LoadPngFromFile(path, &icon)) {
return false;
} else {
return image_util::IsIconSufficientlyVisible(icon);
}
return IsIconSufficientlyVisible(icon);
}
bool IsRenderedIconSufficientlyVisible(const SkBitmap& icon,
SkColor background_color) {
// If any of a pixel's RGB values is greater than this number, the pixel is
// considered visible.
constexpr unsigned int kThreshold = 15;
// The minimum "percent" of pixels that must be visible for the icon to be
// considered OK.
constexpr double kMinPercentVisiblePixels = 0.05;
const int total_pixels = icon.height() * icon.width();
// Draw the icon onto a canvas, then draw the background color onto the
// resulting bitmap, using SkBlendMode::kDifference. Then, check the RGB
// values against the threshold. Any pixel with a value greater than the
// threshold is considered visible.
SkBitmap bitmap;
bitmap.allocN32Pixels(icon.width(), icon.height());
bitmap.eraseColor(background_color);
SkCanvas offscreen(bitmap);
offscreen.drawImage(SkImage::MakeFromBitmap(icon), 0, 0);
offscreen.drawColor(background_color, SkBlendMode::kDifference);
int visible_pixels = 0;
for (int x = 0; x < icon.width(); ++x) {
for (int y = 0; y < icon.height(); ++y) {
SkColor pixel = bitmap.getColor(x, y);
if (SkColorGetR(pixel) > kThreshold || SkColorGetB(pixel) > kThreshold ||
SkColorGetG(pixel) > kThreshold) {
++visible_pixels;
}
}
}
return static_cast<double>(visible_pixels) / total_pixels >=
kMinPercentVisiblePixels;
}
bool IsRenderedIconAtPathSufficientlyVisible(const base::FilePath& path,
SkColor background_color) {
SkBitmap icon;
if (!LoadPngFromFile(path, &icon)) {
return false;
}
return IsRenderedIconSufficientlyVisible(icon, background_color);
}
bool LoadPngFromFile(const base::FilePath& path, SkBitmap* dst) {
......
......@@ -44,6 +44,17 @@ bool IsIconSufficientlyVisible(const SkBitmap& bitmap);
// context.
bool IsIconAtPathSufficientlyVisible(const base::FilePath& path);
// Renders the icon bitmap onto another bitmap, combining it with the specified
// background color, then determines whether the rendered icon is sufficiently
// visible against the background.
bool IsRenderedIconSufficientlyVisible(const SkBitmap& bitmap,
SkColor background_color);
// Returns whether an icon image is considered to be visible in its display
// context, according to the previous function.
bool IsRenderedIconAtPathSufficientlyVisible(const base::FilePath& path,
SkColor background_color);
// Load a PNG image from a file into the destination bitmap.
bool LoadPngFromFile(const base::FilePath& path, SkBitmap* dst);
......
......@@ -190,6 +190,8 @@ TEST(ImageUtilTest, IsIconSufficientlyVisible) {
SkBitmap transparent_icon;
ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &transparent_icon));
EXPECT_FALSE(image_util::IsIconSufficientlyVisible(transparent_icon));
EXPECT_FALSE(image_util::IsRenderedIconSufficientlyVisible(transparent_icon,
SK_ColorWHITE));
}
{
// Test with an icon that has one opaque pixel.
......@@ -197,6 +199,8 @@ TEST(ImageUtilTest, IsIconSufficientlyVisible) {
SkBitmap visible_icon;
ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
EXPECT_FALSE(image_util::IsIconSufficientlyVisible(visible_icon));
EXPECT_FALSE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
SK_ColorWHITE));
}
{
// Test with an icon that has one transparent pixel.
......@@ -204,6 +208,8 @@ TEST(ImageUtilTest, IsIconSufficientlyVisible) {
SkBitmap visible_icon;
ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
SK_ColorWHITE));
}
{
// Test with an icon that is completely opaque.
......@@ -211,6 +217,8 @@ TEST(ImageUtilTest, IsIconSufficientlyVisible) {
SkBitmap visible_icon;
ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
SK_ColorWHITE));
}
{
// Test with an icon that is rectangular.
......@@ -218,6 +226,30 @@ TEST(ImageUtilTest, IsIconSufficientlyVisible) {
SkBitmap visible_icon;
ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
SK_ColorWHITE));
}
{
// Test with a solid color icon that is completely opaque. Use the icon's
// color as the background color in the call to analyze its visibility.
// It should be invisible in this case.
icon_path = test_dir.AppendASCII("grey_21x21.png");
SkBitmap solid_icon;
ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &solid_icon));
const SkColor pixel_color = solid_icon.getColor(0, 0);
EXPECT_FALSE(
image_util::IsRenderedIconSufficientlyVisible(solid_icon, pixel_color));
}
{
// Test with a two-color icon that is completely opaque. Use one of the
// icon's colors as the background color in the call to analyze its
// visibility. It should be visible in this case.
icon_path = test_dir.AppendASCII("two_color_21x21.png");
SkBitmap two_color_icon;
ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &two_color_icon));
const SkColor pixel_color = two_color_icon.getColor(0, 0);
EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(two_color_icon,
pixel_color));
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment