blob: 2f2eb1472b2600d646953bef5314b71422cdf1f0 [file] [log] [blame]
//
// Copyright 2020 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "contrast_swatch.h"
#include <unordered_map>
namespace gtx {
ContrastSwatch::ContrastSwatch(const Color &foreground,
const Color &background) {
foreground_ = foreground;
background_ = background;
}
ContrastSwatch ContrastSwatch::Extract(const Image &image,
const Rect &sub_image_bounds) {
// Extract a histogram of the colors in the given image (in the given bounds).
// To determine the most dominant colors.
std::unordered_map<int32_t, int> color_histogram;
const int max_index = image.width * image.height;
for (int x = 0; x < sub_image_bounds.size.width; x++) {
for (int y = 0; y < sub_image_bounds.size.height; y++) {
int index = (x + sub_image_bounds.origin.x) +
(y + sub_image_bounds.origin.y) * image.width;
if (index >= 0 && index < max_index) {
int32_t packed_color = image.pixels[index].PackedColor();
color_histogram[packed_color] += 1;
}
}
}
// The most dominant color is considered the background color. Note that the
// key 0 may not exist in the histogram, however for colors that dont exist
// the count will be zero causing tap_key to be replaced by an actual color in
// the histogram with count > zero.
int top_key = 0;
int penultimate_key = 0;
// Save the count of entires in histogram *before* processing it since
// accessing keys that dont exist may lead to creating the enties with count
// 0.
int64_t count = (int64_t)color_histogram.size();
for (auto& color : color_histogram) {
auto const& key = color.first;
auto const& value = color.second;
if (value > color_histogram[top_key]) {
penultimate_key = top_key;
top_key = key;
} else if (value > color_histogram[penultimate_key]) {
penultimate_key = key;
}
}
Color background = Color::UnpackedColor(top_key);
Color foreground;
if (count < 2) {
// When image has a single color, background and foreground colors are
// assumed to be the same.
foreground = background;
} else {
foreground = Color::UnpackedColor(penultimate_key);
}
return ContrastSwatch(foreground, background);
}
} // namespace gtx