libeuropa/util: Move 4bpp/8bpp paint support

This commit is contained in:
Lily Tsuru 2025-01-16 20:56:42 -05:00
parent 69e9ecd35c
commit 6a565e3244
4 changed files with 46 additions and 33 deletions

View file

@ -17,6 +17,7 @@ namespace europa::structs {
struct [[gnu::packed]] YatfHeader {
enum class TextureFormat : u8 {
// V1 formats.
kTextureFormatV1_8Bpp = 0,
kTextureFormatV1_24Bpp = 2,
kTextureFormatV1_32Bpp = 3,
@ -34,11 +35,11 @@ namespace europa::structs {
u32 magic;
u16 version; // 0x1 for starfighter, 0x2 for jsf
u16 version; // 0x1 for starfighter, 0x2 for new jsf files
TextureFormat format;
u8 unkThing2; // flags? some palbpp?
u8 unkThing2; // flags? some palbpp? V2 seems to end up usually matching
// Always zeroed.
u32 zero;

View file

@ -78,6 +78,21 @@ namespace europa::util {
void Resize(Size newSize);
// FIXME: For now, these APIs will work. It may actually make sense
// to have a ImageSurface hold a Unique<IPixelBuffer>, that knows about
// format and can optionally output pixels or provide raw buffer access
// if desired.
//
// basically support other than RGBA8888 out of the box and deal with it nicely
/// Paint from a 4bpp source.
/// Assumes this image has been initalized to the proper size already.
void PaintFromSource_4bpp(std::uint8_t const* pSrc, Pixel const* pPalette);
/// Paint from a 8bpp source.
/// Assumes this image has been initalized to the proper size already.
void PaintFromSource_8bpp(std::uint8_t const* pSrc, Pixel const* pPalette);
private:
UniqueArray<std::uint32_t> imageBuffer;
Size size;

View file

@ -46,16 +46,7 @@ namespace europa::io::yatf {
stream.read(reinterpret_cast<char*>(&palette[0]), sizeof(palette));
stream.read(reinterpret_cast<char*>(&palettizedData[0]), imageSize.Linear());
auto* pDestBuffer = reinterpret_cast<util::Pixel*>(surface.GetBuffer());
for(std::size_t y = 0; y < imageSize.height; ++y) {
for(std::size_t x = 0; x < imageSize.width; ++x) {
auto& pp = palettizedData[y * imageSize.width + x];
auto& dst = pDestBuffer[y * imageSize.width + x];
dst = palette[static_cast<std::size_t>(pp)];
}
}
surface.PaintFromSource_8bpp(&palettizedData[0], &palette[0]);
} break;
case kTextureFormatV1_24Bpp: {
@ -90,20 +81,9 @@ namespace europa::io::yatf {
case kTextureFormatV2_4Bpp: {
util::Pixel palette[16] {};
util::UniqueArray<std::uint8_t> palettizedData(imageSize.Linear() / 2);
stream.read(reinterpret_cast<char*>(&palette[0]), sizeof(palette));
stream.read(reinterpret_cast<char*>(&palettizedData[0]), imageSize.Linear() / 2);
auto* pDestBuffer = reinterpret_cast<util::Pixel*>(surface.GetBuffer());
// can't really get a better loop to work, so i guess this has to do
for(std::size_t y = 0; y < (imageSize.width * imageSize.height) / 2; ++y) {
auto& pp = palettizedData[y];
for(std::size_t b = 0; b < 2; ++b) {
auto col = ((pp & (0x0F << (b * 4))) >> (b * 4));
(*pDestBuffer++) = palette[static_cast<std::size_t>(col)];
}
}
surface.PaintFromSource_4bpp(&palettizedData[0], &palette[0]);
} break;
case kTextureFormatV2_8Bpp: {
@ -113,15 +93,7 @@ namespace europa::io::yatf {
stream.read(reinterpret_cast<char*>(&palette[0]), sizeof(palette));
stream.read(reinterpret_cast<char*>(&palettizedData[0]), imageSize.Linear());
auto* pDestBuffer = reinterpret_cast<util::Pixel*>(surface.GetBuffer());
for(std::size_t y = 0; y < imageSize.height; ++y) {
for(std::size_t x = 0; x < imageSize.width; ++x) {
auto& pp = palettizedData[y * imageSize.width + x];
auto& dst = pDestBuffer[y * imageSize.width + x];
dst = palette[static_cast<std::size_t>(pp)];
}
}
surface.PaintFromSource_8bpp(&palettizedData[0], &palette[0]);
} break;
case kTextureFormatV2_24Bpp: {

View file

@ -26,4 +26,29 @@ namespace europa::util {
return imageBuffer.Data();
}
void ImageSurface::PaintFromSource_4bpp(std::uint8_t const* pSrc, Pixel const* pPalette) {
auto* pDestBuffer = reinterpret_cast<util::Pixel*>(imageBuffer.Data());
// can't really get a better loop to work, so i guess this has to do
for(std::size_t y = 0; y < size.Linear() / 2; ++y) {
auto& pp = pSrc[y];
for(std::size_t b = 0; b < 2; ++b) {
auto col = ((pp & (0x0F << (b * 4))) >> (b * 4));
(*pDestBuffer++) = pPalette[static_cast<std::size_t>(col)];
}
}
}
void ImageSurface::PaintFromSource_8bpp(std::uint8_t const* pSrc, Pixel const* pPalette) {
auto* pDestBuffer = reinterpret_cast<Pixel*>(imageBuffer.Data());
for(std::size_t y = 0; y < size.height; ++y) {
for(std::size_t x = 0; x < size.width; ++x) {
auto& pp = pSrc[y * size.width + x];
auto& dst = pDestBuffer[y * size.width + x];
dst = pPalette[static_cast<std::size_t>(pp)];
}
}
}
} // namespace europa::util