23 const SDL_PixelFormatDetails *format_details = SDL_GetPixelFormatDetails(
surface->format);
24 if (format_details ==
nullptr || !SDL_LockSurface(
surface)) {
32 const auto *bytes =
static_cast<const std::uint8_t *
>(
surface->pixels);
34 for (
int y = 0; y <
surface->h; ++y) {
35 const auto *row =
reinterpret_cast<const std::uint32_t *
>(bytes +
static_cast<std::size_t
>(y) *
static_cast<std::size_t
>(
surface->pitch));
36 for (
int x = 0; x <
surface->w; ++x) {
41 SDL_GetRGBA(row[x], format_details,
nullptr, &r, &g, &b, &a);
45 min_x = std::min(min_x, x);
46 min_y = std::min(min_y, y);
47 max_x = std::max(max_x, x);
48 max_y = std::max(max_y, y);
54 if (max_x < min_x || max_y < min_y) {
58 const float width =
static_cast<float>(
surface->w);
59 const float height =
static_cast<float>(
surface->h);
61 static_cast<float>(min_x) / width - 0.5f,
62 static_cast<float>(max_x + 1) / width - 0.5f,
63 0.5f -
static_cast<float>(max_y + 1) / height,
64 0.5f -
static_cast<float>(min_y) / height,
70 if (loaded_surface ==
nullptr) {
74 SDL_Surface *
surface = SDL_ConvertSurface(loaded_surface, SDL_PIXELFORMAT_RGBA32);
75 SDL_DestroySurface(loaded_surface);
80 const SDL_PixelFormatDetails *format_details = SDL_GetPixelFormatDetails(
surface->format);
81 if (format_details ==
nullptr) {
83 throw mxvk::Exception(
"Failed to query pixel format details for: " + path);
86 if (!SDL_LockSurface(
surface)) {
91 auto *pixels =
static_cast<std::uint32_t *
>(
surface->pixels);
94 const int pixel_count = width * height;
95 std::vector<std::uint8_t> background(
static_cast<std::size_t
>(pixel_count), 0);
96 std::vector<int> stack;
97 stack.reserve(
static_cast<std::size_t
>(width + height) * 2);
99 const auto is_light_checker_pixel = [&](
const int index) {
104 SDL_GetRGBA(pixels[index], format_details,
nullptr, &r, &g, &b, &a);
105 const int min_channel = std::min({
static_cast<int>(r),
static_cast<int>(g),
static_cast<int>(b)});
106 const int max_channel = std::max({
static_cast<int>(r),
static_cast<int>(g),
static_cast<int>(b)});
107 return a != 0 && min_channel >= 215 && (max_channel - min_channel) <= 28;
110 const auto push_background = [&](
const int index) {
111 if (index < 0 || index >= pixel_count || background[
static_cast<std::size_t
>(index)] != 0 || !is_light_checker_pixel(index)) {
114 background[
static_cast<std::size_t
>(index)] = 1;
115 stack.push_back(index);
118 for (
int x = 0; x < width; ++x) {
120 push_background((height - 1) * width + x);
122 for (
int y = 0; y < height; ++y) {
123 push_background(y * width);
124 push_background(y * width + width - 1);
127 while (!stack.empty()) {
128 const int index = stack.back();
130 const int x = index % width;
131 const int y = index / width;
133 push_background(index - 1);
136 push_background(index + 1);
139 push_background(index - width);
141 if (y + 1 < height) {
142 push_background(index + width);
146 for (
int i = 0; i < pixel_count; ++i) {
147 if (background[
static_cast<std::size_t
>(i)] == 0) {
154 SDL_GetRGBA(pixels[i], format_details,
nullptr, &r, &g, &b, &a);
155 pixels[i] = SDL_MapRGBA(format_details,
nullptr, r, g, b, 0);