初版网页
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
#include "Pixel_Frame.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
namespace renderive::web {
|
||||
namespace {
|
||||
|
||||
void write_u32_le(char* target, std::uint32_t value) {
|
||||
target[0] = static_cast<char>(value & 0xffU);
|
||||
target[1] = static_cast<char>((value >> 8U) & 0xffU);
|
||||
target[2] = static_cast<char>((value >> 16U) & 0xffU);
|
||||
target[3] = static_cast<char>((value >> 24U) & 0xffU);
|
||||
}
|
||||
|
||||
std::uint8_t flatten(std::uint8_t premultiplied, std::uint8_t alpha,
|
||||
std::uint8_t background) {
|
||||
return static_cast<std::uint8_t>(
|
||||
std::min(255U, static_cast<unsigned>(premultiplied) +
|
||||
(static_cast<unsigned>(background) * (255U - alpha) + 127U) / 255U));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string encode_pixel_frame(Image_View image, Color background) {
|
||||
if (image.empty() || image.format != Pixel_Format::Premultiplied_32 ||
|
||||
image.stride < image.width * static_cast<int>(sizeof(Pixel))) {
|
||||
return {};
|
||||
}
|
||||
const auto width = static_cast<std::size_t>(image.width);
|
||||
const auto height = static_cast<std::size_t>(image.height);
|
||||
if (width > (std::numeric_limits<std::size_t>::max() - pixel_frame_header_size) /
|
||||
(height * sizeof(Pixel))) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::size_t pixel_bytes = width * height * sizeof(Pixel);
|
||||
std::string frame(pixel_frame_header_size + pixel_bytes, '\0');
|
||||
frame[0] = 'R';
|
||||
frame[1] = 'V';
|
||||
frame[2] = 'P';
|
||||
frame[3] = '1';
|
||||
write_u32_le(frame.data() + 4, static_cast<std::uint32_t>(image.width));
|
||||
write_u32_le(frame.data() + 8, static_cast<std::uint32_t>(image.height));
|
||||
write_u32_le(frame.data() + 12,
|
||||
static_cast<std::uint32_t>(image.width * static_cast<int>(sizeof(Pixel))));
|
||||
|
||||
auto* output = reinterpret_cast<std::uint8_t*>(frame.data() + pixel_frame_header_size);
|
||||
for (int y = 0; y < image.height; ++y) {
|
||||
const auto* row = image.data + static_cast<std::ptrdiff_t>(y) * image.stride;
|
||||
for (int x = 0; x < image.width; ++x) {
|
||||
Pixel pixel{};
|
||||
std::memcpy(&pixel, row + static_cast<std::ptrdiff_t>(x) * sizeof(Pixel), sizeof(pixel));
|
||||
const auto alpha = static_cast<std::uint8_t>((pixel >> 24U) & 0xffU);
|
||||
const auto red = static_cast<std::uint8_t>((pixel >> 16U) & 0xffU);
|
||||
const auto green = static_cast<std::uint8_t>((pixel >> 8U) & 0xffU);
|
||||
const auto blue = static_cast<std::uint8_t>(pixel & 0xffU);
|
||||
*output++ = flatten(red, alpha, background.r);
|
||||
*output++ = flatten(green, alpha, background.g);
|
||||
*output++ = flatten(blue, alpha, background.b);
|
||||
*output++ = 255;
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
} // namespace renderive::web
|
||||
Reference in New Issue
Block a user