收口颜色格式,删除原来的 RGBA8888 的存储和调用
This commit is contained in:
parent
23a5b50aec
commit
56eec9e9d2
|
|
@ -2,6 +2,7 @@
|
||||||
#include <SDL_image.h>
|
#include <SDL_image.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -49,7 +50,7 @@ namespace
|
||||||
|
|
||||||
struct Image
|
struct Image
|
||||||
{
|
{
|
||||||
std::vector<uint32_t> pixels;
|
std::vector<uint16_t> pixels;
|
||||||
int32_t width;
|
int32_t width;
|
||||||
int32_t height;
|
int32_t height;
|
||||||
|
|
||||||
|
|
@ -65,6 +66,52 @@ namespace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static uint16_t PackRgba5551(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
|
{
|
||||||
|
return static_cast<uint16_t>(
|
||||||
|
((static_cast<uint16_t>(r) >> 3) << 11) |
|
||||||
|
((static_cast<uint16_t>(g) >> 3) << 6) |
|
||||||
|
((static_cast<uint16_t>(b) >> 3) << 1) |
|
||||||
|
(a ? 1u : 0u));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint32 ReadSurfacePixel(const SDL_Surface* surface, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
const uint8_t* row = static_cast<const uint8_t*>(surface->pixels) +
|
||||||
|
static_cast<size_t>(y) * static_cast<size_t>(surface->pitch);
|
||||||
|
const uint8_t* src = row + static_cast<size_t>(x) * static_cast<size_t>(surface->format->BytesPerPixel);
|
||||||
|
|
||||||
|
switch (surface->format->BytesPerPixel)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return src[0];
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
uint16_t pixel = 0;
|
||||||
|
std::memcpy(&pixel, src, sizeof(pixel));
|
||||||
|
return static_cast<Uint32>(pixel);
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
return (static_cast<Uint32>(src[0]) << 16) |
|
||||||
|
(static_cast<Uint32>(src[1]) << 8) |
|
||||||
|
static_cast<Uint32>(src[2]);
|
||||||
|
}
|
||||||
|
return static_cast<Uint32>(src[0]) |
|
||||||
|
(static_cast<Uint32>(src[1]) << 8) |
|
||||||
|
(static_cast<Uint32>(src[2]) << 16);
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
Uint32 pixel = 0;
|
||||||
|
std::memcpy(&pixel, src, sizeof(pixel));
|
||||||
|
return pixel;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AtlasRegion
|
struct AtlasRegion
|
||||||
{
|
{
|
||||||
const SourceSpec* source;
|
const SourceSpec* source;
|
||||||
|
|
@ -105,39 +152,34 @@ namespace
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface* rgba_surface = SDL_ConvertSurfaceFormat(loaded_surface, SDL_PIXELFORMAT_RGBA8888, 0);
|
if (SDL_LockSurface(loaded_surface) != 0)
|
||||||
SDL_FreeSurface(loaded_surface);
|
|
||||||
if (rgba_surface == nullptr)
|
|
||||||
{
|
|
||||||
std::cerr << "SDL_ConvertSurfaceFormat failed: " << SDL_GetError() << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_LockSurface(rgba_surface) != 0)
|
|
||||||
{
|
{
|
||||||
std::cerr << "SDL_LockSurface failed: " << SDL_GetError() << std::endl;
|
std::cerr << "SDL_LockSurface failed: " << SDL_GetError() << std::endl;
|
||||||
SDL_FreeSurface(rgba_surface);
|
SDL_FreeSurface(loaded_surface);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
image.width = rgba_surface->w;
|
image.width = loaded_surface->w;
|
||||||
image.height = rgba_surface->h;
|
image.height = loaded_surface->h;
|
||||||
image.pixels.assign(static_cast<size_t>(image.width) * static_cast<size_t>(image.height), 0);
|
image.pixels.assign(static_cast<size_t>(image.width) * static_cast<size_t>(image.height), 0);
|
||||||
|
|
||||||
for (int32_t y = 0; y < image.height; ++y)
|
for (int32_t y = 0; y < image.height; ++y)
|
||||||
{
|
{
|
||||||
const uint8_t* src_row = static_cast<const uint8_t*>(rgba_surface->pixels) + y * rgba_surface->pitch;
|
|
||||||
const uint32_t* src_pixels = reinterpret_cast<const uint32_t*>(src_row);
|
|
||||||
for (int32_t x = 0; x < image.width; ++x)
|
for (int32_t x = 0; x < image.width; ++x)
|
||||||
{
|
{
|
||||||
const uint32_t pixel = src_pixels[x];
|
uint8_t r = 0;
|
||||||
|
uint8_t g = 0;
|
||||||
|
uint8_t b = 0;
|
||||||
|
uint8_t a = 0;
|
||||||
|
const Uint32 surface_pixel = ReadSurfacePixel(loaded_surface, x, y);
|
||||||
|
SDL_GetRGBA(surface_pixel, loaded_surface->format, &r, &g, &b, &a);
|
||||||
image.pixels[static_cast<size_t>(y) * static_cast<size_t>(image.width) + static_cast<size_t>(x)] =
|
image.pixels[static_cast<size_t>(y) * static_cast<size_t>(image.width) + static_cast<size_t>(x)] =
|
||||||
(pixel & 0xFFu) == 0u ? 0x00000000u : pixel;
|
a == 0 ? 0u : PackRgba5551(r, g, b, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockSurface(rgba_surface);
|
SDL_UnlockSurface(loaded_surface);
|
||||||
SDL_FreeSurface(rgba_surface);
|
SDL_FreeSurface(loaded_surface);
|
||||||
return image.is_valid();
|
return image.is_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,11 +287,11 @@ namespace
|
||||||
return atlas_height > 0;
|
return atlas_height > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<uint32_t> BuildAtlasPixels(const std::vector<AtlasRegion>& regions, int32_t atlas_height)
|
static std::vector<uint16_t> BuildAtlasPixels(const std::vector<AtlasRegion>& regions, int32_t atlas_height)
|
||||||
{
|
{
|
||||||
std::vector<uint32_t> atlas_pixels(
|
std::vector<uint16_t> atlas_pixels(
|
||||||
static_cast<size_t>(AtlasWidth) * static_cast<size_t>(atlas_height),
|
static_cast<size_t>(AtlasWidth) * static_cast<size_t>(atlas_height),
|
||||||
0x00000000u);
|
0u);
|
||||||
|
|
||||||
for (size_t i = 0; i < regions.size(); ++i)
|
for (size_t i = 0; i < regions.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -262,28 +304,15 @@ namespace
|
||||||
static_cast<size_t>(region.x);
|
static_cast<size_t>(region.x);
|
||||||
|
|
||||||
std::copy(
|
std::copy(
|
||||||
region.image.pixels.begin() + static_cast<std::vector<uint32_t>::difference_type>(src_offset),
|
region.image.pixels.begin() + static_cast<std::vector<uint16_t>::difference_type>(src_offset),
|
||||||
region.image.pixels.begin() + static_cast<std::vector<uint32_t>::difference_type>(src_offset + static_cast<size_t>(region.image.width)),
|
region.image.pixels.begin() + static_cast<std::vector<uint16_t>::difference_type>(src_offset + static_cast<size_t>(region.image.width)),
|
||||||
atlas_pixels.begin() + static_cast<std::vector<uint32_t>::difference_type>(dst_offset));
|
atlas_pixels.begin() + static_cast<std::vector<uint16_t>::difference_type>(dst_offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return atlas_pixels;
|
return atlas_pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t rgba8888_to_rgba5551(uint32_t c)
|
|
||||||
{
|
|
||||||
uint32_t r = (c >> 24) & 0xFFu;
|
|
||||||
uint32_t g = (c >> 16) & 0xFFu;
|
|
||||||
uint32_t b = (c >> 8) & 0xFFu;
|
|
||||||
uint32_t a = c & 0xFFu;
|
|
||||||
return static_cast<uint16_t>(
|
|
||||||
((r >> 3) << 11) |
|
|
||||||
((g >> 3) << 6) |
|
|
||||||
((b >> 3) << 1) |
|
|
||||||
(a ? 1u : 0u));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WritePixel5551(std::ofstream& file, uint16_t pixel)
|
static void WritePixel5551(std::ofstream& file, uint16_t pixel)
|
||||||
{
|
{
|
||||||
file << "0x"
|
file << "0x"
|
||||||
|
|
@ -299,7 +328,7 @@ namespace
|
||||||
|
|
||||||
static bool WriteAtlasHeader(
|
static bool WriteAtlasHeader(
|
||||||
const std::vector<AtlasRegion>& regions,
|
const std::vector<AtlasRegion>& regions,
|
||||||
const std::vector<uint32_t>& atlas_pixels,
|
const std::vector<uint16_t>& atlas_pixels,
|
||||||
int32_t atlas_height)
|
int32_t atlas_height)
|
||||||
{
|
{
|
||||||
std::ofstream file(OutputHeaderPath);
|
std::ofstream file(OutputHeaderPath);
|
||||||
|
|
@ -326,7 +355,7 @@ namespace
|
||||||
const size_t end = std::min(i + 12, atlas_pixels.size());
|
const size_t end = std::min(i + 12, atlas_pixels.size());
|
||||||
for (size_t j = i; j < end; ++j)
|
for (size_t j = i; j < end; ++j)
|
||||||
{
|
{
|
||||||
WritePixel5551(file, rgba8888_to_rgba5551(atlas_pixels[j]));
|
WritePixel5551(file, atlas_pixels[j]);
|
||||||
file << ", ";
|
file << ", ";
|
||||||
}
|
}
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|
@ -375,7 +404,7 @@ namespace
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<uint32_t> atlas_pixels = BuildAtlasPixels(regions, atlas_height);
|
const std::vector<uint16_t> atlas_pixels = BuildAtlasPixels(regions, atlas_height);
|
||||||
if (!WriteAtlasHeader(regions, atlas_pixels, atlas_height))
|
if (!WriteAtlasHeader(regions, atlas_pixels, atlas_height))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,10 @@ namespace Asset
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (image.format != RenderData::PixelFormat::RGBA5551)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
size_t pixelCount = 0;
|
size_t pixelCount = 0;
|
||||||
if (!CheckPixelCount(static_cast<uint32_t>(image.width), static_cast<uint32_t>(image.height), pixelCount))
|
if (!CheckPixelCount(static_cast<uint32_t>(image.width), static_cast<uint32_t>(image.height), pixelCount))
|
||||||
|
|
@ -182,21 +186,10 @@ namespace Asset
|
||||||
WriteU32LE(file, static_cast<uint32_t>(image.height));
|
WriteU32LE(file, static_cast<uint32_t>(image.height));
|
||||||
WriteU32LE(file, SpriteFormatRgba5551);
|
WriteU32LE(file, SpriteFormatRgba5551);
|
||||||
|
|
||||||
if (image.format == RenderData::PixelFormat::RGBA5551)
|
const uint16_t* pixels16 = static_cast<const uint16_t*>(image.pixels);
|
||||||
|
for (size_t i = 0; i < pixelCount; ++i)
|
||||||
{
|
{
|
||||||
const uint16_t* pixels16 = static_cast<const uint16_t*>(image.pixels);
|
WritePixel5551(file, pixels16[i]);
|
||||||
for (size_t i = 0; i < pixelCount; ++i)
|
|
||||||
{
|
|
||||||
WritePixel5551(file, pixels16[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const uint32_t* pixels32 = static_cast<const uint32_t*>(image.pixels);
|
|
||||||
for (size_t i = 0; i < pixelCount; ++i)
|
|
||||||
{
|
|
||||||
WritePixel5551(file, RenderData::rgba8888_to_rgba5551(pixels32[i]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return file.good();
|
return file.good();
|
||||||
|
|
|
||||||
|
|
@ -124,53 +124,9 @@ namespace Core
|
||||||
if (dst_x + end_dx > screen_w) end_dx = screen_w - dst_x;
|
if (dst_x + end_dx > screen_w) end_dx = screen_w - dst_x;
|
||||||
if (dst_y + end_dy > screen_h) end_dy = screen_h - dst_y;
|
if (dst_y + end_dy > screen_h) end_dy = screen_h - dst_y;
|
||||||
|
|
||||||
if (img.format == RenderData::PixelFormat::RGBA5551)
|
Core::FramePixel* dst = static_cast<Core::FramePixel*>(frameBuffer->get_buffer());
|
||||||
{
|
const int32_t fb_w = frameBuffer->get_width();
|
||||||
Core::FramePixel* dst = static_cast<Core::FramePixel*>(frameBuffer->get_buffer());
|
const uint16_t* src = static_cast<const uint16_t*>(img.pixels);
|
||||||
const int32_t fb_w = frameBuffer->get_width();
|
|
||||||
const uint16_t* src = static_cast<const uint16_t*>(img.pixels);
|
|
||||||
|
|
||||||
if (scale == 1)
|
|
||||||
{
|
|
||||||
for (int32_t sy = start_dy; sy < end_dy; ++sy)
|
|
||||||
{
|
|
||||||
const int32_t read_y = flip_v ? (src_y + src_h - 1 - sy) : (src_y + sy);
|
|
||||||
const int32_t dst_y_abs = dst_y + sy;
|
|
||||||
Core::FramePixel* dst_row = dst + dst_y_abs * fb_w;
|
|
||||||
|
|
||||||
for (int32_t sx = start_dx; sx < end_dx; ++sx)
|
|
||||||
{
|
|
||||||
const int32_t read_x = flip_h ? (src_x + src_w - 1 - sx) : (src_x + sx);
|
|
||||||
const uint16_t pixel = src[read_y * img_w + read_x];
|
|
||||||
if (!RenderData::rgba5551_is_opaque(pixel)) continue;
|
|
||||||
dst_row[dst_x + sx] = RenderData::rgba5551_to_rgb565(pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32_t dy_abs = start_dy; dy_abs < end_dy; ++dy_abs)
|
|
||||||
{
|
|
||||||
const int32_t sy = dy_abs / scale;
|
|
||||||
const int32_t read_y = flip_v ? (src_y + src_h - 1 - sy) : (src_y + sy);
|
|
||||||
const int32_t dst_y_abs = dst_y + dy_abs;
|
|
||||||
Core::FramePixel* dst_row = dst + dst_y_abs * fb_w;
|
|
||||||
|
|
||||||
for (int32_t dx_abs = start_dx; dx_abs < end_dx; ++dx_abs)
|
|
||||||
{
|
|
||||||
const int32_t sx = dx_abs / scale;
|
|
||||||
const int32_t read_x = flip_h ? (src_x + src_w - 1 - sx) : (src_x + sx);
|
|
||||||
const uint16_t pixel = src[read_y * img_w + read_x];
|
|
||||||
if (!RenderData::rgba5551_is_opaque(pixel)) continue;
|
|
||||||
dst_row[dst_x + dx_abs] = RenderData::rgba5551_to_rgb565(pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool has_key = img.has_color_key;
|
|
||||||
const uint32_t key = RenderData::rgba5551_to_rgba8888(img.color_key);
|
|
||||||
const uint32_t* src32 = static_cast<const uint32_t*>(img.pixels);
|
|
||||||
|
|
||||||
if (scale == 1)
|
if (scale == 1)
|
||||||
{
|
{
|
||||||
|
|
@ -178,14 +134,14 @@ namespace Core
|
||||||
{
|
{
|
||||||
const int32_t read_y = flip_v ? (src_y + src_h - 1 - sy) : (src_y + sy);
|
const int32_t read_y = flip_v ? (src_y + src_h - 1 - sy) : (src_y + sy);
|
||||||
const int32_t dst_y_abs = dst_y + sy;
|
const int32_t dst_y_abs = dst_y + sy;
|
||||||
|
Core::FramePixel* dst_row = dst + dst_y_abs * fb_w;
|
||||||
|
|
||||||
for (int32_t sx = start_dx; sx < end_dx; ++sx)
|
for (int32_t sx = start_dx; sx < end_dx; ++sx)
|
||||||
{
|
{
|
||||||
const int32_t read_x = flip_h ? (src_x + src_w - 1 - sx) : (src_x + sx);
|
const int32_t read_x = flip_h ? (src_x + src_w - 1 - sx) : (src_x + sx);
|
||||||
const uint32_t pixel = src32[read_y * img_w + read_x];
|
const uint16_t pixel = src[read_y * img_w + read_x];
|
||||||
if ((pixel & 0xFFu) == 0u) continue;
|
if (!RenderData::rgba5551_is_opaque(pixel)) continue;
|
||||||
if (has_key && pixel == key) continue;
|
dst_row[dst_x + sx] = RenderData::rgba5551_to_rgb565(pixel);
|
||||||
frameBuffer->set_pixel_unsafe(dst_x + sx, dst_y_abs, pixel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -196,15 +152,15 @@ namespace Core
|
||||||
const int32_t sy = dy_abs / scale;
|
const int32_t sy = dy_abs / scale;
|
||||||
const int32_t read_y = flip_v ? (src_y + src_h - 1 - sy) : (src_y + sy);
|
const int32_t read_y = flip_v ? (src_y + src_h - 1 - sy) : (src_y + sy);
|
||||||
const int32_t dst_y_abs = dst_y + dy_abs;
|
const int32_t dst_y_abs = dst_y + dy_abs;
|
||||||
|
Core::FramePixel* dst_row = dst + dst_y_abs * fb_w;
|
||||||
|
|
||||||
for (int32_t dx_abs = start_dx; dx_abs < end_dx; ++dx_abs)
|
for (int32_t dx_abs = start_dx; dx_abs < end_dx; ++dx_abs)
|
||||||
{
|
{
|
||||||
const int32_t sx = dx_abs / scale;
|
const int32_t sx = dx_abs / scale;
|
||||||
const int32_t read_x = flip_h ? (src_x + src_w - 1 - sx) : (src_x + sx);
|
const int32_t read_x = flip_h ? (src_x + src_w - 1 - sx) : (src_x + sx);
|
||||||
const uint32_t pixel = src32[read_y * img_w + read_x];
|
const uint16_t pixel = src[read_y * img_w + read_x];
|
||||||
if ((pixel & 0xFFu) == 0u) continue;
|
if (!RenderData::rgba5551_is_opaque(pixel)) continue;
|
||||||
if (has_key && pixel == key) continue;
|
dst_row[dst_x + dx_abs] = RenderData::rgba5551_to_rgb565(pixel);
|
||||||
frameBuffer->set_pixel_unsafe(dst_x + dx_abs, dst_y_abs, pixel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ namespace RenderData
|
||||||
{
|
{
|
||||||
enum class PixelFormat
|
enum class PixelFormat
|
||||||
{
|
{
|
||||||
RGBA8888,
|
|
||||||
RGBA5551
|
RGBA5551
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -24,31 +23,6 @@ namespace RenderData
|
||||||
return (c & 0x1u) != 0;
|
return (c & 0x1u) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t rgba5551_to_rgba8888(uint16_t c)
|
|
||||||
{
|
|
||||||
uint32_t r = (c >> 11) & 0x1Fu;
|
|
||||||
uint32_t g = (c >> 6) & 0x1Fu;
|
|
||||||
uint32_t b = (c >> 1) & 0x1Fu;
|
|
||||||
uint32_t a = c & 0x1u;
|
|
||||||
return (r << 27) | (r << 24) |
|
|
||||||
(g << 19) | (g << 16) |
|
|
||||||
(b << 11) | (b << 8) |
|
|
||||||
(a ? 0xFFu : 0x00u);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint16_t rgba8888_to_rgba5551(uint32_t c)
|
|
||||||
{
|
|
||||||
uint32_t r = (c >> 24) & 0xFFu;
|
|
||||||
uint32_t g = (c >> 16) & 0xFFu;
|
|
||||||
uint32_t b = (c >> 8) & 0xFFu;
|
|
||||||
uint32_t a = c & 0xFFu;
|
|
||||||
return static_cast<uint16_t>(
|
|
||||||
((r >> 3) << 11) |
|
|
||||||
((g >> 3) << 6) |
|
|
||||||
((b >> 3) << 1) |
|
|
||||||
(a ? 1u : 0u));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Image
|
struct Image
|
||||||
{
|
{
|
||||||
const void* pixels;
|
const void* pixels;
|
||||||
|
|
@ -61,29 +35,25 @@ namespace RenderData
|
||||||
Image()
|
Image()
|
||||||
: pixels(nullptr), width(0), height(0),
|
: pixels(nullptr), width(0), height(0),
|
||||||
color_key(0), has_color_key(false),
|
color_key(0), has_color_key(false),
|
||||||
format(PixelFormat::RGBA8888) {}
|
format(PixelFormat::RGBA5551) {}
|
||||||
|
|
||||||
Image(const void* pixels, int32_t width, int32_t height,
|
Image(const void* pixels, int32_t width, int32_t height,
|
||||||
PixelFormat fmt = PixelFormat::RGBA8888)
|
PixelFormat fmt = PixelFormat::RGBA5551)
|
||||||
: pixels(pixels), width(width), height(height),
|
: pixels(pixels), width(width), height(height),
|
||||||
color_key(0), has_color_key(false),
|
color_key(0), has_color_key(false),
|
||||||
format(fmt) {}
|
format(fmt) {}
|
||||||
|
|
||||||
Image(const void* pixels, int32_t width, int32_t height,
|
Image(const void* pixels, int32_t width, int32_t height,
|
||||||
uint16_t color_key,
|
uint16_t color_key,
|
||||||
PixelFormat fmt = PixelFormat::RGBA8888)
|
PixelFormat fmt = PixelFormat::RGBA5551)
|
||||||
: pixels(pixels), width(width), height(height),
|
: pixels(pixels), width(width), height(height),
|
||||||
color_key(color_key), has_color_key(true),
|
color_key(color_key), has_color_key(true),
|
||||||
format(fmt) {}
|
format(fmt) {}
|
||||||
|
|
||||||
uint32_t get_pixel(int32_t x, int32_t y) const
|
uint32_t get_pixel(int32_t x, int32_t y) const
|
||||||
{
|
{
|
||||||
if (format == PixelFormat::RGBA5551)
|
return static_cast<uint32_t>(
|
||||||
{
|
static_cast<const uint16_t*>(pixels)[y * width + x]);
|
||||||
return rgba5551_to_rgba8888(
|
|
||||||
static_cast<const uint16_t*>(pixels)[y * width + x]);
|
|
||||||
}
|
|
||||||
return static_cast<const uint32_t*>(pixels)[y * width + x];
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,23 @@
|
||||||
|
|
||||||
namespace Rasterizer
|
namespace Rasterizer
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
inline uint16_t rgba5551_to_rgb565(uint16_t c)
|
||||||
|
{
|
||||||
|
const uint16_t r = static_cast<uint16_t>((c >> 11) & 0x1Fu);
|
||||||
|
const uint16_t g = static_cast<uint16_t>((c >> 6) & 0x1Fu);
|
||||||
|
const uint16_t b = static_cast<uint16_t>((c >> 1) & 0x1Fu);
|
||||||
|
const uint16_t g6 = static_cast<uint16_t>((g << 1) | (g >> 4));
|
||||||
|
return static_cast<uint16_t>((r << 11) | (g6 << 5) | b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool rgba5551_is_opaque(uint16_t c)
|
||||||
|
{
|
||||||
|
return (c & 0x1u) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SpriteRasterizer::DrawImage(const RenderData::Image& image, int32_t x, int32_t y)
|
void SpriteRasterizer::DrawImage(const RenderData::Image& image, int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
DrawSprite(RenderData::Sprite(&image), x, y);
|
DrawSprite(RenderData::Sprite(&image), x, y);
|
||||||
|
|
@ -27,18 +44,21 @@ namespace Rasterizer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::FramePixel* dst = static_cast<Core::FramePixel*>(frameBuffer->get_buffer());
|
||||||
|
const int32_t fb_w = frameBuffer->get_width();
|
||||||
|
|
||||||
for (int32_t sy = minY; sy < maxY; ++sy)
|
for (int32_t sy = minY; sy < maxY; ++sy)
|
||||||
{
|
{
|
||||||
|
Core::FramePixel* dst_row = dst + (y + sy) * fb_w;
|
||||||
for (int32_t sx = minX; sx < maxX; ++sx)
|
for (int32_t sx = minX; sx < maxX; ++sx)
|
||||||
{
|
{
|
||||||
const uint32_t color = sprite.get_pixel_fast(sx, sy);
|
const uint16_t color = sprite.get_pixel_fast(sx, sy);
|
||||||
const uint8_t alpha = static_cast<uint8_t>(color & 0xFF);
|
if (!rgba5551_is_opaque(color))
|
||||||
if (alpha == 0)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
frameBuffer->set_pixel(x + sx, y + sy, color);
|
dst_row[x + sx] = rgba5551_to_rgb565(color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace RenderData
|
||||||
private:
|
private:
|
||||||
int32_t width;
|
int32_t width;
|
||||||
int32_t height;
|
int32_t height;
|
||||||
std::vector<uint32_t> pixels;
|
std::vector<uint16_t> pixels;
|
||||||
|
|
||||||
static bool calculate_pixel_count(int32_t width, int32_t height, size_t& count)
|
static bool calculate_pixel_count(int32_t width, int32_t height, size_t& count)
|
||||||
{
|
{
|
||||||
|
|
@ -47,7 +47,7 @@ namespace RenderData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image(int32_t width, int32_t height, const std::vector<uint32_t>& pixels) : width(0), height(0)
|
Image(int32_t width, int32_t height, const std::vector<uint16_t>& pixels) : width(0), height(0)
|
||||||
{
|
{
|
||||||
size_t pixelCount = 0;
|
size_t pixelCount = 0;
|
||||||
if (calculate_pixel_count(width, height, pixelCount) && pixels.size() == pixelCount)
|
if (calculate_pixel_count(width, height, pixelCount) && pixels.size() == pixelCount)
|
||||||
|
|
@ -64,9 +64,9 @@ namespace RenderData
|
||||||
|
|
||||||
size_t total_pixels() const { return pixels.size(); }
|
size_t total_pixels() const { return pixels.size(); }
|
||||||
|
|
||||||
const uint32_t* data() const { return pixels.data(); }
|
const uint16_t* data() const { return pixels.data(); }
|
||||||
|
|
||||||
uint32_t* data() { return pixels.data(); }
|
uint16_t* data() { return pixels.data(); }
|
||||||
|
|
||||||
bool is_valid() const
|
bool is_valid() const
|
||||||
{
|
{
|
||||||
|
|
@ -74,7 +74,7 @@ namespace RenderData
|
||||||
return calculate_pixel_count(width, height, pixelCount) && pixels.size() == pixelCount;
|
return calculate_pixel_count(width, height, pixelCount) && pixels.size() == pixelCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_pixel(int32_t x, int32_t y) const
|
uint16_t get_pixel(int32_t x, int32_t y) const
|
||||||
{
|
{
|
||||||
if (x < 0 || x >= width || y < 0 || y >= height)
|
if (x < 0 || x >= width || y < 0 || y >= height)
|
||||||
{
|
{
|
||||||
|
|
@ -85,13 +85,13 @@ namespace RenderData
|
||||||
return pixels[index];
|
return pixels[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_pixel_fast(int32_t x, int32_t y) const
|
uint16_t get_pixel_fast(int32_t x, int32_t y) const
|
||||||
{
|
{
|
||||||
size_t index = static_cast<size_t>(y) * width + x;
|
size_t index = static_cast<size_t>(y) * width + x;
|
||||||
return pixels[index];
|
return pixels[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_pixel(int32_t x, int32_t y, uint32_t color)
|
void set_pixel(int32_t x, int32_t y, uint16_t color)
|
||||||
{
|
{
|
||||||
if (x < 0 || x >= width || y < 0 || y >= height)
|
if (x < 0 || x >= width || y < 0 || y >= height)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ namespace RenderData
|
||||||
return x + width <= image->get_width() && y + height <= image->get_height();
|
return x + width <= image->get_width() && y + height <= image->get_height();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_pixel(int32_t localX, int32_t localY) const
|
uint16_t get_pixel(int32_t localX, int32_t localY) const
|
||||||
{
|
{
|
||||||
if (!is_valid() || localX < 0 || localX >= width || localY < 0 || localY >= height)
|
if (!is_valid() || localX < 0 || localX >= width || localY < 0 || localY >= height)
|
||||||
{
|
{
|
||||||
|
|
@ -55,7 +55,7 @@ namespace RenderData
|
||||||
return image->get_pixel(x + localX, y + localY);
|
return image->get_pixel(x + localX, y + localY);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_pixel_fast(int32_t localX, int32_t localY) const
|
uint16_t get_pixel_fast(int32_t localX, int32_t localY) const
|
||||||
{
|
{
|
||||||
return image->get_pixel_fast(x + localX, y + localY);
|
return image->get_pixel_fast(x + localX, y + localY);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,21 @@ namespace
|
||||||
assert(pixels[1] == 0xF800u);
|
assert(pixels[1] == 0xF800u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestImageDefaultsToRgba5551AndReturnsRawPixels()
|
||||||
|
{
|
||||||
|
const uint16_t default_pixels[] = { 0xF801u, 0x0000u };
|
||||||
|
RenderData::Image default_image(default_pixels, 1, 1);
|
||||||
|
assert(default_image.format == RenderData::PixelFormat::RGBA5551);
|
||||||
|
|
||||||
|
const uint16_t explicit_pixels[] = { 0x07C1u };
|
||||||
|
RenderData::Image explicit_image(
|
||||||
|
explicit_pixels,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
RenderData::PixelFormat::RGBA5551);
|
||||||
|
assert(explicit_image.get_pixel(0, 0) == 0x07C1u);
|
||||||
|
}
|
||||||
|
|
||||||
void TestDrawSpriteUsesOneBitAlpha()
|
void TestDrawSpriteUsesOneBitAlpha()
|
||||||
{
|
{
|
||||||
const uint16_t sprite_pixels[] = {
|
const uint16_t sprite_pixels[] = {
|
||||||
|
|
@ -199,6 +214,7 @@ int main()
|
||||||
{
|
{
|
||||||
TestFramePixelIsRgb565();
|
TestFramePixelIsRgb565();
|
||||||
TestFrameBufferStoresRgb565();
|
TestFrameBufferStoresRgb565();
|
||||||
|
TestImageDefaultsToRgba5551AndReturnsRawPixels();
|
||||||
TestDrawSpriteUsesOneBitAlpha();
|
TestDrawSpriteUsesOneBitAlpha();
|
||||||
TestSpriteAssetLoaderRoundTripsRgba5551();
|
TestSpriteAssetLoaderRoundTripsRgba5551();
|
||||||
TestDrawTextUsesBitMaskAndColor();
|
TestDrawTextUsesBitMaskAndColor();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue