46#include <ufo/io/file_handler.hpp>
47#include <ufo/io/image_properties.hpp>
48#include <ufo/vision/color.hpp>
49#include <ufo/vision/image.hpp>
77bool readPNG(std::FILE* fp,
void* image, std::size_t
length,
int fmt);
97bool writePNG(std::FILE* fp,
void const* image, std::size_t
length, std::uint32_t width,
98 std::uint32_t height,
int color_type,
int bit_depth);
137template <ColorType CT,
class T,
bool Alpha,
bool Weight>
143 std::println(stderr,
"[UFO | Read PNG] Failed to open file: {}", file.string());
147 auto fun = [&image](std::FILE* fp,
auto& tmp,
int fmt) {
148 using C =
typename std::remove_cvref_t<
decltype(tmp)>::value_type;
149 if (detail::readPNG(fp, tmp.data(),
sizeof(C) * tmp.size(), fmt)) {
150 if constexpr (has_alpha_v<C>) {
151 for (
auto& p : tmp) {
153 if constexpr (ColorType::GRAY == color_type_v<C>) {
163 image = convert<Color<CT, T, Alpha, Weight>>(tmp);
170 if (prop.alpha && prop.grayscale && 8 >= prop.bit_depth) {
173 return fun(fp.
get(), tmp, fmt);
174 }
else if (prop.grayscale && 16 == prop.bit_depth) {
178 return fun(fp.
get(), tmp, fmt);
179 }
else if (prop.alpha && !prop.grayscale && 8 == prop.bit_depth) {
182 return fun(fp.
get(), tmp, fmt);
183 }
else if (!prop.grayscale && 16 == prop.bit_depth) {
186 return fun(fp.
get(), tmp, fmt);
187 }
else if (!prop.alpha && prop.grayscale && 8 >= prop.bit_depth) {
191 return fun(fp.
get(), tmp, fmt);
192 }
else if (!prop.alpha && !prop.grayscale && 8 == prop.bit_depth) {
195 return fun(fp.
get(), tmp, fmt);
197 std::println(stderr,
"[UFO | Read PNG] Unknown PNG type");
220template <ColorType CT,
class T,
bool Alpha,
bool Weight>
227 std::println(stderr,
"[UFO | Write PNG] Failed to create file: {}", file.string());
231 std::uint32_t
const width = image.cols();
232 std::uint32_t
const height = image.rows();
233 int const bit_depth =
sizeof(std::uint8_t) <
sizeof(T) ? 16 : 8;
236 constexpr int color_type = (ColorType::GRAY == CT) ? (
Alpha ? 4 : 0)
238 constexpr int channels = (ColorType::GRAY == CT) ? (
Alpha ? 2 : 1) : (
Alpha ? 4 : 3);
240 std::size_t
const length =
241 static_cast<std::size_t
>(width) * height * (bit_depth / 8) * channels;
244 constexpr ColorType CT2 = (ColorType::GRAY == CT) ? ColorType::GRAY : ColorType::RGB;
246 std::conditional_t<
sizeof(std::uint8_t) <
sizeof(T), std::uint16_t, std::uint8_t>;
248 if constexpr (CT == CT2 && std::is_same_v<T, T2> && !
Weight) {
249 return detail::writePNG(fp.
get(), image.data(),
length, width, height, color_type,
253 std::ranges::transform(image, data.
begin(), [](
auto x) {
254 return convert<Color<CT2, T2, Alpha, false>>(x);
256 return detail::writePNG(fp.
get(), data.
data(),
length, width, height, color_type,
RAII wrapper around a C std::FILE* handle.
std::FILE * get() const noexcept
Returns the underlying FILE*.
Image class for storing and manipulating 2D pixel data.
auto data(this auto &self) noexcept
Returns a pointer to the underlying contiguous pixel array.
auto begin(this auto &self) noexcept
Returns an iterator to the first pixel.
Identifies any UFO color instantiation (Gray, Lab, Lch, Lrgb, Rgb).
@ Alpha
Include an alpha channel.
All vision-related classes and functions.
bool readPNG(std::filesystem::path const &file, Image< Color< CT, T, Alpha, Weight > > &image)
Reads a PNG file into an Image of the specified colour type.
constexpr T length(Vec< Dim, T > const &v) noexcept
Computes the Euclidean length (magnitude) of a vector.
bool writePNG(std::filesystem::path const &file, Image< Color< CT, T, Alpha, Weight > > const &image)
Writes an Image to a PNG file.
ImageProperties imagePropertiesPNG(std::filesystem::path const &file)
Reads the metadata of a PNG file without decoding pixel data.
constexpr alpha_type_t< C > alpha(C color) noexcept
Returns the un-weighted alpha of color.
Represents a generic scalar weight as a single float value.