use new phosg::Image class
This commit is contained in:
@@ -14,6 +14,7 @@ CTestTestfile.cmake
|
||||
install_manifest.txt
|
||||
Makefile
|
||||
Testing
|
||||
build
|
||||
|
||||
# Files modified by the user and/or server that don't have defaults
|
||||
system/config.json
|
||||
@@ -35,6 +36,7 @@ system/patch-bb/.metadata-cache.json
|
||||
# repository
|
||||
files
|
||||
make_release.py
|
||||
notes-private
|
||||
old-khyller
|
||||
old-newserv
|
||||
release
|
||||
|
||||
+10
-11
@@ -35,7 +35,7 @@ struct GVRHeader {
|
||||
be_uint16_t height;
|
||||
} __packed_ws__(GVRHeader, 0x10);
|
||||
|
||||
string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const string& internal_name, uint32_t global_index) {
|
||||
string encode_gvm(const phosg::ImageRGBA8888& img, GVRDataFormat data_format, const string& internal_name, uint32_t global_index) {
|
||||
int8_t dimensions_field = -2;
|
||||
{
|
||||
size_t h = img.get_height();
|
||||
@@ -90,17 +90,16 @@ string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const stri
|
||||
for (size_t x = 0; x < img.get_width(); x += 4) {
|
||||
for (size_t yy = 0; yy < 4; yy++) {
|
||||
for (size_t xx = 0; xx < 4; xx++) {
|
||||
uint64_t a, r, g, b;
|
||||
img.read_pixel(x + xx, y + yy, &r, &g, &b, &a);
|
||||
uint32_t c = img.read(x + xx, y + yy);
|
||||
switch (data_format) {
|
||||
case GVRDataFormat::RGB565:
|
||||
w.put_u16b(encode_rgb565(r, g, b));
|
||||
w.put_u16b(phosg::rgb565_for_rgba8888(c));
|
||||
break;
|
||||
case GVRDataFormat::RGB5A3:
|
||||
w.put_u16b(encode_rgb5a3(r, g, b, a));
|
||||
w.put_u16b(encode_rgb5a3(c));
|
||||
break;
|
||||
case GVRDataFormat::ARGB8888:
|
||||
w.put_u32b(encode_argb8888(r, g, b, a));
|
||||
w.put_u32b(phosg::argb8888_for_rgba8888(c));
|
||||
break;
|
||||
default:
|
||||
throw logic_error("cannot encode pixel format");
|
||||
@@ -115,15 +114,15 @@ string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const stri
|
||||
|
||||
static const array<uint32_t, 4> fon_colors = {0x000000FF, 0x555555FF, 0xAAAAAAFF, 0xFFFFFFFF};
|
||||
|
||||
phosg::Image decode_fon(const string& data, size_t width) {
|
||||
phosg::ImageRGB888 decode_fon(const string& data, size_t width) {
|
||||
size_t num_pixels = data.size() * 4;
|
||||
size_t height = num_pixels / width;
|
||||
phosg::Image ret(width, height);
|
||||
phosg::ImageRGB888 ret(width, height);
|
||||
|
||||
phosg::BitReader r(data);
|
||||
for (size_t y = 0; y < height; y++) {
|
||||
for (size_t x = 0; x < width; x++) {
|
||||
ret.write_pixel(x, y, fon_colors[r.read(2)]);
|
||||
ret.write(x, y, fon_colors[r.read(2)]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -133,11 +132,11 @@ constexpr size_t uabs(size_t a, size_t b) {
|
||||
return (a > b) ? (a - b) : (b - a);
|
||||
}
|
||||
|
||||
string encode_fon(const phosg::Image& img) {
|
||||
string encode_fon(const phosg::ImageRGB888& img) {
|
||||
phosg::BitWriter w;
|
||||
for (size_t y = 0; y < img.get_height(); y++) {
|
||||
for (size_t x = 0; x < img.get_width(); x++) {
|
||||
uint32_t color = img.read_pixel(x, y);
|
||||
uint32_t color = img.read(x, y);
|
||||
|
||||
size_t result_delta = 0x400;
|
||||
size_t result_index = 0;
|
||||
|
||||
+20
-34
@@ -19,43 +19,29 @@ enum class GVRDataFormat : uint8_t {
|
||||
DXT1 = 0x0E,
|
||||
};
|
||||
|
||||
std::string encode_gvm(const phosg::Image& img, GVRDataFormat data_format, const std::string& internal_name, uint32_t global_index);
|
||||
phosg::Image decode_fon(const std::string& data, size_t width);
|
||||
std::string encode_fon(const phosg::Image& img);
|
||||
std::string encode_gvm(
|
||||
const phosg::ImageRGBA8888& img, GVRDataFormat data_format, const std::string& internal_name, uint32_t global_index);
|
||||
phosg::ImageRGB888 decode_fon(const std::string& data, size_t width);
|
||||
std::string encode_fon(const phosg::ImageRGB888& img);
|
||||
|
||||
constexpr uint16_t encode_rgb565(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return ((r << 8) & 0xF800) | ((g << 3) & 0x07E0) | ((b >> 3) & 0x001F);
|
||||
}
|
||||
|
||||
constexpr uint16_t encode_rgb5a3(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
if ((a & 0xE0) == 0xE0) {
|
||||
return 0x8000 | ((r << 7) & 0x7C00) | ((g << 2) & 0x03E0) | ((b >> 3) & 0x001F);
|
||||
constexpr uint16_t encode_rgb5a3(uint32_t c) {
|
||||
if ((phosg::get_a(c) & 0xE0) == 0xE0) {
|
||||
return 0x8000 | ((phosg::get_r(c) << 7) & 0x7C00) | ((phosg::get_g(c) << 2) & 0x03E0) | ((phosg::get_b(c) >> 3) & 0x001F);
|
||||
} else {
|
||||
return ((a << 7) & 0x7000) | ((r << 4) & 0x0F00) | (g & 0x00F0) | ((b >> 4) & 0x000F);
|
||||
return ((phosg::get_a(c) << 7) & 0x7000) | ((phosg::get_r(c) << 4) & 0x0F00) | (phosg::get_g(c) & 0x00F0) | ((phosg::get_b(c) >> 4) & 0x000F);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr uint32_t encode_argb8888(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
constexpr uint16_t encode_argb8888_to_argb1555(uint32_t argb8888) {
|
||||
// In: aaaaaaaarrrrrrrrggggggggbbbbbbbb
|
||||
// Out: arrrrrgggggbbbbb
|
||||
return ((argb8888 >> 9) & 0x7C00) | ((argb8888 >> 6) & 0x03E0) | ((argb8888 >> 3) & 0x001F) | ((argb8888 >> 16) & 0x8000);
|
||||
}
|
||||
|
||||
constexpr uint16_t encode_rgba8888_to_argb1555(uint32_t rgba8888) {
|
||||
// In: rrrrrrrrggggggggbbbbbbbbaaaaaaaa
|
||||
// Out: arrrrrgggggbbbbb
|
||||
return ((rgba8888 >> 17) & 0x7C00) | ((rgba8888 >> 14) & 0x03E0) | ((rgba8888 >> 11) & 0x001F) | ((rgba8888 << 8) & 0x8000);
|
||||
}
|
||||
|
||||
constexpr uint32_t decode_argb1555_to_rgba8888(uint16_t argb1555) {
|
||||
// In: arrrrrgggggbbbbb
|
||||
// Out: rrrrrrrrggggggggbbbbbbbbaaaaaaaa
|
||||
return ((argb1555 << 17) & 0xF8000000) | ((argb1555 << 12) & 0x07000000) |
|
||||
((argb1555 << 14) & 0x00F80000) | ((argb1555 << 9) & 0x00070000) |
|
||||
((argb1555 << 11) & 0x0000F800) | ((argb1555 << 6) & 0x00000700) |
|
||||
((argb1555 & 0x8000) ? 0x000000FF : 0x00000000);
|
||||
template <phosg::PixelFormat Format>
|
||||
bool has_any_transparent_pixels(const phosg::Image<Format>& img) {
|
||||
if constexpr (phosg::Image<Format>::HAS_ALPHA) {
|
||||
for (size_t y = 0; y < img.get_height(); y++) {
|
||||
for (size_t x = 0; x < img.get_height(); x++) {
|
||||
if (phosg::get_a(img.read(x, y)) != 0xFF) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+22
-21
@@ -1166,7 +1166,7 @@ Action a_decode_gci_snapshot(
|
||||
}
|
||||
|
||||
auto img = file.decode_image();
|
||||
string saved = img.save(phosg::Image::Format::WINDOWS_BITMAP);
|
||||
string saved = img.serialize(phosg::ImageFormat::WINDOWS_BITMAP);
|
||||
write_output_data(args, saved.data(), saved.size(), "bmp");
|
||||
});
|
||||
|
||||
@@ -1177,13 +1177,16 @@ Action a_encode_gvm(
|
||||
GVM file can be used as an Episode 3 lobby banner.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
const string& input_filename = args.get<string>(1, false);
|
||||
phosg::Image img;
|
||||
string data;
|
||||
if (!input_filename.empty() && (input_filename != "-")) {
|
||||
img = phosg::Image(input_filename);
|
||||
data = phosg::load_file(input_filename);
|
||||
} else {
|
||||
img = phosg::Image(stdin);
|
||||
data = phosg::read_all(stdin);
|
||||
}
|
||||
string encoded = encode_gvm(img, img.get_has_alpha() ? GVRDataFormat::RGB5A3 : GVRDataFormat::RGB565, "image.gvr", 0);
|
||||
auto img = phosg::ImageRGBA8888::from_file_data(data);
|
||||
// If the image has any transparent pixels at all, use RGB5A3
|
||||
string encoded = encode_gvm(
|
||||
img, has_any_transparent_pixels(img) ? GVRDataFormat::RGB5A3 : GVRDataFormat::RGB565, "image.gvr", 0);
|
||||
write_output_data(args, encoded.data(), encoded.size(), "gvm");
|
||||
});
|
||||
|
||||
@@ -1196,7 +1199,7 @@ Action a_decode_bitmap_font(
|
||||
+[](phosg::Arguments& args) {
|
||||
std::string data = read_input_data(args);
|
||||
size_t width = args.get<size_t>("width");
|
||||
std::string bmp_data = decode_fon(data, width).save(phosg::Image::Format::WINDOWS_BITMAP);
|
||||
std::string bmp_data = decode_fon(data, width).serialize(phosg::ImageFormat::WINDOWS_BITMAP);
|
||||
write_output_data(args, bmp_data.data(), bmp_data.size(), "bmp");
|
||||
});
|
||||
Action a_encode_bitmap_font(
|
||||
@@ -1207,12 +1210,13 @@ Action a_encode_bitmap_font(
|
||||
original fon\'s dimensions.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
const string& input_filename = args.get<string>(1, false);
|
||||
phosg::Image img;
|
||||
string data;
|
||||
if (!input_filename.empty() && (input_filename != "-")) {
|
||||
img = phosg::Image(input_filename);
|
||||
data = phosg::load_file(input_filename);
|
||||
} else {
|
||||
img = phosg::Image(stdin);
|
||||
data = phosg::read_all(stdin);
|
||||
}
|
||||
auto img = phosg::ImageRGB888::from_file_data(data);
|
||||
string encoded = encode_fon(img);
|
||||
write_output_data(args, encoded.data(), encoded.size(), "fon");
|
||||
});
|
||||
@@ -2591,22 +2595,19 @@ Action a_generate_ep3_cards_html(
|
||||
phosg::parallel_range<uint32_t>([&](uint32_t index, size_t) -> bool {
|
||||
auto& info = this->card_infos[index];
|
||||
if (!info.large_filename.empty()) {
|
||||
phosg::Image img(info.large_filename);
|
||||
phosg::Image cropped(512, 399);
|
||||
cropped.blit(img, 0, 0, 512, 399, 0, 0);
|
||||
info.large_data_url = cropped.png_data_url();
|
||||
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(info.large_filename));
|
||||
img.resize(512, 399);
|
||||
info.large_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
if (!info.medium_filename.empty()) {
|
||||
phosg::Image img(info.medium_filename);
|
||||
phosg::Image cropped(184, 144);
|
||||
cropped.blit(img, 0, 0, 184, 144, 0, 0);
|
||||
info.medium_data_url = cropped.png_data_url();
|
||||
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(info.medium_filename));
|
||||
img.resize(184, 144);
|
||||
info.medium_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
if (!info.small_filename.empty()) {
|
||||
phosg::Image img(info.small_filename);
|
||||
phosg::Image cropped(58, 43);
|
||||
cropped.blit(img, 0, 0, 58, 43, 0, 0);
|
||||
info.small_data_url = cropped.png_data_url();
|
||||
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(info.small_filename));
|
||||
img.resize(58, 43);
|
||||
info.small_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
+3
-13
@@ -218,16 +218,7 @@ bool PSOGCSnapshotFile::checksum_correct() const {
|
||||
return (crc == this->checksum);
|
||||
}
|
||||
|
||||
static uint32_t decode_rgb565(uint16_t c) {
|
||||
// Input bits: rrrrrggg gggbbbbb
|
||||
// Output bits: rrrrrrrr gggggggg bbbbbbbb aaaaaaaa
|
||||
return ((c << 16) & 0xF8000000) | ((c << 11) & 0x07000000) | // R
|
||||
((c << 13) & 0x00FC0000) | ((c << 7) & 0x00030000) | // G
|
||||
((c << 11) & 0x0000F800) | ((c << 6) & 0x00000700) | // B
|
||||
0x000000FF; // A
|
||||
}
|
||||
|
||||
phosg::Image PSOGCSnapshotFile::decode_image() const {
|
||||
phosg::ImageRGB888 PSOGCSnapshotFile::decode_image() const {
|
||||
size_t width = this->width ? this->width.load() : 256;
|
||||
size_t height = this->height ? this->height.load() : 192;
|
||||
if (width != 256) {
|
||||
@@ -238,14 +229,13 @@ phosg::Image PSOGCSnapshotFile::decode_image() const {
|
||||
}
|
||||
|
||||
// 4x4 blocks of pixels
|
||||
phosg::Image ret(width, height, false);
|
||||
phosg::ImageRGB888 ret(width, height);
|
||||
size_t offset = 0;
|
||||
for (size_t y = 0; y < this->height; y += 4) {
|
||||
for (size_t x = 0; x < this->width; x += 4) {
|
||||
for (size_t yy = 0; yy < 4; yy++) {
|
||||
for (size_t xx = 0; xx < 4; xx++) {
|
||||
uint32_t color = decode_rgb565(this->pixels[offset++]);
|
||||
ret.write_pixel(x + xx, y + yy, color);
|
||||
ret.write(x + xx, y + yy, phosg::rgba8888_for_rgb565(this->pixels[offset++]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1066,7 +1066,7 @@ struct PSOGCSnapshotFile {
|
||||
/* 1818C */
|
||||
|
||||
bool checksum_correct() const;
|
||||
phosg::Image decode_image() const;
|
||||
phosg::ImageRGB888 decode_image() const;
|
||||
} __packed_ws__(PSOGCSnapshotFile, 0x1818C);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+2
-2
@@ -966,10 +966,10 @@ void ServerState::load_config_early() {
|
||||
} else if (lower_path.ends_with(".gvm")) {
|
||||
decompressed_gvm_data = phosg::load_file(path);
|
||||
} else if (lower_path.ends_with(".bmp")) {
|
||||
phosg::Image img(path);
|
||||
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(path));
|
||||
decompressed_gvm_data = encode_gvm(
|
||||
img,
|
||||
img.get_has_alpha() ? GVRDataFormat::RGB5A3 : GVRDataFormat::RGB565,
|
||||
has_any_transparent_pixels(img) ? GVRDataFormat::RGB5A3 : GVRDataFormat::RGB565,
|
||||
std::format("bnr{}", banner_index),
|
||||
0x80 | banner_index);
|
||||
banner_index++;
|
||||
|
||||
+5
-5
@@ -98,14 +98,14 @@ void TeamIndex::Team::save_config() const {
|
||||
}
|
||||
|
||||
void TeamIndex::Team::load_flag() {
|
||||
phosg::Image img(this->flag_filename());
|
||||
auto img = phosg::ImageRGBA8888::from_file_data(phosg::load_file(this->flag_filename()));
|
||||
if (img.get_width() != 32 || img.get_height() != 32) {
|
||||
throw runtime_error("incorrect flag image dimensions");
|
||||
}
|
||||
this->flag_data.reset(new parray<le_uint16_t, 0x20 * 0x20>());
|
||||
for (size_t y = 0; y < 32; y++) {
|
||||
for (size_t x = 0; x < 32; x++) {
|
||||
this->flag_data->at(y * 0x20 + x) = encode_rgba8888_to_argb1555(img.read_pixel(x, y));
|
||||
this->flag_data->at(y * 0x20 + x) = phosg::argb1555_for_rgba8888(img.read(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,13 +114,13 @@ void TeamIndex::Team::save_flag() const {
|
||||
if (!this->flag_data) {
|
||||
return;
|
||||
}
|
||||
phosg::Image img(32, 32, true);
|
||||
phosg::ImageRGBA8888 img(32, 32);
|
||||
for (size_t y = 0; y < 32; y++) {
|
||||
for (size_t x = 0; x < 32; x++) {
|
||||
img.write_pixel(x, y, decode_argb1555_to_rgba8888(this->flag_data->at(y * 0x20 + x)));
|
||||
img.write(x, y, phosg::rgba8888_for_argb1555(this->flag_data->at(y * 0x20 + x)));
|
||||
}
|
||||
}
|
||||
img.save(this->flag_filename(), phosg::Image::Format::WINDOWS_BITMAP);
|
||||
phosg::save_file(this->flag_filename(), img.serialize(phosg::ImageFormat::WINDOWS_BITMAP));
|
||||
}
|
||||
|
||||
void TeamIndex::Team::delete_files() const {
|
||||
|
||||
Reference in New Issue
Block a user