BuildSystem: Move all userpace libraries under the userspace directory

As the number of libraries is increasing, root directory starts to
expand. This adds better organization for libraries
This commit is contained in:
2024-06-18 13:14:35 +03:00
parent 1b5a01a6c9
commit c69919738b
157 changed files with 46 additions and 30 deletions

View File

@@ -0,0 +1,200 @@
#include <BAN/ScopeGuard.h>
#include <BAN/String.h>
#include <LibImage/Image.h>
#include <LibImage/Netbpm.h>
#include <LibImage/PNG.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
namespace LibImage
{
BAN::ErrorOr<BAN::UniqPtr<Image>> Image::load_from_file(BAN::StringView path)
{
int fd = -1;
if (path.data()[path.size()] == '\0')
{
fd = open(path.data(), O_RDONLY);
}
else
{
BAN::String path_str;
TRY(path_str.append(path));
fd = open(path_str.data(), O_RDONLY);
}
if (fd == -1)
{
fprintf(stddbg, "open: %s\n", strerror(errno));
return BAN::Error::from_errno(errno);
}
BAN::ScopeGuard guard_file_close([fd] { close(fd); });
struct stat st;
if (fstat(fd, &st) == -1)
{
fprintf(stddbg, "fstat: %s\n", strerror(errno));
return BAN::Error::from_errno(errno);
}
void* addr = mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED)
{
fprintf(stddbg, "mmap: %s\n", strerror(errno));
return BAN::Error::from_errno(errno);
}
BAN::ScopeGuard guard_munmap([&] { munmap(addr, st.st_size); });
auto image_data_span = BAN::ConstByteSpan(reinterpret_cast<uint8_t*>(addr), st.st_size);
if (probe_netbpm(image_data_span))
return TRY(load_netbpm(image_data_span));
if (probe_png(image_data_span))
return TRY(load_png(image_data_span));
fprintf(stderr, "unrecognized image format\n");
return BAN::Error::from_errno(ENOTSUP);
}
struct FloatingColor
{
double r, g, b, a;
constexpr FloatingColor() {}
constexpr FloatingColor(double r, double g, double b, double a)
: r(r), g(g), b(b), a(a)
{}
constexpr FloatingColor(Image::Color c)
: r(c.r), g(c.g), b(c.b), a(c.a)
{}
constexpr FloatingColor operator*(double value) const
{
return FloatingColor(r * value, g * value, b * value, a * value);
}
constexpr FloatingColor operator+(FloatingColor other) const
{
return FloatingColor(r + other.r, g + other.g, b + other.b, a + other.a);
}
constexpr Image::Color as_color() const
{
return Image::Color {
.r = static_cast<uint8_t>(BAN::Math::clamp<double>(r, 0.0, 255.0)),
.g = static_cast<uint8_t>(BAN::Math::clamp<double>(g, 0.0, 255.0)),
.b = static_cast<uint8_t>(BAN::Math::clamp<double>(b, 0.0, 255.0)),
.a = static_cast<uint8_t>(BAN::Math::clamp<double>(a, 0.0, 255.0)),
};
}
};
BAN::ErrorOr<BAN::UniqPtr<Image>> Image::resize(uint64_t new_width, uint64_t new_height, ResizeAlgorithm algorithm)
{
if (!validate_size(new_width, new_height))
return BAN::Error::from_errno(EOVERFLOW);
const double ratio_x = (double)width() / new_width;
const double ratio_y = (double)height() / new_height;
const auto get_clamped_color =
[this](int64_t x, int64_t y)
{
x = BAN::Math::clamp<int64_t>(x, 0, width() - 1);
y = BAN::Math::clamp<int64_t>(y, 0, height() - 1);
return get_color(x, y);
};
switch (algorithm)
{
case ResizeAlgorithm::Nearest:
{
BAN::Vector<Color> nearest_bitmap;
TRY(nearest_bitmap.resize(new_width * new_height));
for (uint64_t y = 0; y < new_height; y++)
for (uint64_t x = 0; x < new_width; x++)
nearest_bitmap[y * new_width + x] = get_clamped_color(x * ratio_x, y * ratio_y);
return TRY(BAN::UniqPtr<Image>::create(new_width, new_height, BAN::move(nearest_bitmap)));
}
case ResizeAlgorithm::Linear:
{
BAN::Vector<Color> bilinear_bitmap;
TRY(bilinear_bitmap.resize(new_width * new_height));
for (uint64_t y = 0; y < new_height; y++)
{
for (uint64_t x = 0; x < new_width; x++)
{
const double src_x = x * ratio_x;
const double src_y = y * ratio_y;
const double weight_x = src_x - floor(src_x);
const double weight_y = src_y - floor(src_y);
const Color avg_t = Color::average(
get_clamped_color(src_x + 0.0, src_y),
get_clamped_color(src_x + 1.0, src_y),
weight_x
);
const Color avg_b = Color::average(
get_clamped_color(src_x + 0.0, src_y + 1.0),
get_clamped_color(src_x + 0.0, src_y + 1.0),
weight_x
);
bilinear_bitmap[y * new_width + x] = Color::average(avg_t, avg_b, weight_y);
}
}
return TRY(BAN::UniqPtr<Image>::create(new_width, new_height, BAN::move(bilinear_bitmap)));
}
case ResizeAlgorithm::Cubic:
{
BAN::Vector<Color> bicubic_bitmap;
TRY(bicubic_bitmap.resize(new_width * new_height));
constexpr auto cubic_interpolate =
[](FloatingColor p[4], double x)
{
const auto a = (p[0] * -0.5) + (p[1] * 1.5) + (p[2] * -1.5) + (p[3] * 0.5);
const auto b = p[0] + (p[1] * -2.5) + (p[2] * 2.0) + (p[3] * -0.5);
const auto c = (p[0] * -0.5) + (p[2] * 0.5);
const auto d = p[1];
return (a * x * x * x) + (b * x * x) + (c * x) + d;
};
for (uint64_t y = 0; y < new_height; y++)
{
for (uint64_t x = 0; x < new_width; x++)
{
const double src_x = x * ratio_x;
const double src_y = y * ratio_y;
const double weight_x = src_x - floor(src_x);
const double weight_y = src_y - floor(src_y);
FloatingColor values[4];
for (int64_t m = -1; m <= 2; m++)
{
FloatingColor p[4];
p[0] = get_clamped_color(src_x - 1.0, src_y + m);
p[1] = get_clamped_color(src_x + 0.0, src_y + m);
p[2] = get_clamped_color(src_x + 1.0, src_y + m);
p[3] = get_clamped_color(src_x + 2.0, src_y + m);
values[m + 1] = cubic_interpolate(p, weight_x);
}
bicubic_bitmap[y * new_width + x] = cubic_interpolate(values, weight_y).as_color();
}
}
return TRY(BAN::UniqPtr<Image>::create(new_width, new_height, BAN::move(bicubic_bitmap)));
}
}
return BAN::Error::from_errno(EINVAL);
}
}