6#include "absl/strings/str_format.h"
7#include "absl/strings/str_join.h"
14 const std::vector<uint8_t>& indices,
int width,
int height,
16 if (width <= 0 || height <= 0 ||
17 indices.size() !=
static_cast<size_t>(width) * height) {
18 return absl::InvalidArgumentError(
"Clipboard image has no pixels");
20 std::vector<std::array<uint8_t, 4>> palette;
21 for (
size_t i = 0; i < colors.size(); ++i) {
22 palette.push_back({colors[i][0], colors[i][1], colors[i][2],
23 static_cast<uint8_t
>(i == 0 ? 0 : 255)});
29 const std::vector<uint8_t>& png_bytes,
const SheetColors& colors,
30 int max_width,
int max_height) {
32 if (image.
width > max_width || image.
height > max_height) {
33 return absl::InvalidArgumentError(absl::StrFormat(
34 "The clipboard image is %dx%d; a sheet holds at most %dx%d",
40 const size_t count =
static_cast<size_t>(image.
width) * image.
height;
43 bool indices_fit = image.
indexed;
45 for (uint8_t index : image.
indices) {
54 paste.
kept =
static_cast<int>(count);
58 for (
size_t i = 0; i < count; ++i) {
59 std::array<uint8_t, 4> rgba;
61 const uint8_t index = image.
indices[i];
63 : std::array<uint8_t, 4>{0, 0, 0, 0};
65 rgba = {image.
rgba[i * 4], image.
rgba[i * 4 + 1], image.
rgba[i * 4 + 2],
66 image.
rgba[i * 4 + 3]};
74 int best_distance = std::numeric_limits<int>::max();
75 for (
int c = 0; c < 8; ++c) {
76 const int dr = rgba[0] - colors[c][0];
77 const int dg = rgba[1] - colors[c][1];
78 const int db = rgba[2] - colors[c][2];
79 const int distance = dr * dr + dg * dg + db * db;
86 if (c != 0 && distance < best_distance) {
88 best_distance = distance;
91 paste.
indices[i] =
static_cast<uint8_t
>(best);
92 if (best_distance == 0) {
102 std::vector<std::string> parts;
103 if (paste.
kept > 0) {
104 parts.push_back(absl::StrFormat(
"%d kept", paste.
kept));
106 if (paste.
exact > 0) {
107 parts.push_back(absl::StrFormat(
"%d exact", paste.
exact));
110 parts.push_back(absl::StrFormat(
"%d remapped", paste.
remapped));
113 parts.push_back(absl::StrFormat(
"%d transparent", paste.
transparent));
116 parts.push_back(absl::StrFormat(
"%d above color 7", paste.
above_depth));
118 return absl::StrFormat(
"%dx%d: %s", paste.
width, paste.
height,
119 absl::StrJoin(parts,
", "));
#define ASSIGN_OR_RETURN(type_variable_name, expression)
Editors are the view controllers for the application.
absl::StatusOr< ClipboardPaste > MapClipboardPng(const std::vector< uint8_t > &png_bytes, const SheetColors &colors, int max_width, int max_height)
std::array< std::array< uint8_t, 3 >, 8 > SheetColors
The 8 colors a 3bpp sheet shows (index 0 is transparent in game).
absl::StatusOr< std::vector< uint8_t > > EncodeClipboardPng(const std::vector< uint8_t > &indices, int width, int height, const SheetColors &colors)
std::string DescribeClipboardPaste(const ClipboardPaste &paste)
"16x16: 200 kept" / "16x8: 90 exact, 38 remapped, 4 above color 7".
absl::StatusOr< std::vector< uint8_t > > EncodeIndexedPng(int width, int height, const std::vector< uint8_t > &indices, const std::vector< std::array< uint8_t, 4 > > &palette)
absl::StatusOr< PngImage > DecodePng(const std::vector< uint8_t > &bytes)
A clipboard PNG mapped onto a sheet's colors.
std::vector< uint8_t > indices
A decoded PNG: palette indices for indexed files, RGBA otherwise.
std::vector< std::array< uint8_t, 4 > > palette
std::vector< uint8_t > indices
std::vector< uint8_t > rgba