[ion] Simulator: key layouts assets are PNG instead of JPG IV (fix linux)

This commit is contained in:
Émilie Feral
2020-09-17 11:54:46 +02:00
committed by EmilieNumworks
parent 1946c68ef8
commit 165b129385
3 changed files with 141 additions and 52 deletions

View File

@@ -27,20 +27,20 @@ endif
LDFLAGS += -ljpeg
jpg_assets = background horizontal_arrow vertical_arrow round small_squircle large_squircle
assets = background.jpg horizontal_arrow.png vertical_arrow.png round.png small_squircle.png large_squircle.png
jpg_images = $(foreach i,$(jpg_assets),ion/src/simulator/assets/$(i).jpg)
assets_paths = $(foreach i,$(assets),ion/src/simulator/assets/$(i))
$(eval $(call rule_for, \
LINUX_ASSETS, \
ion/src/simulator/linux/assets.s, \
$(jpg_images), \
$$(PYTHON) ion/src/simulator/linux/assets.py --files $(jpg_assets) --implementation $$@, \
$(assets_paths), \
$$(PYTHON) ion/src/simulator/linux/assets.py --files $(assets) --implementation $$@, \
global \
))
assets_address_ranges_declaration = $(foreach i,$(jpg_assets),extern unsigned char _ion_simulator_$(i)_start;)
assets_address_ranges_declaration += $(foreach i,$(jpg_assets),extern unsigned char _ion_simulator_$(i)_end;)
assets_address_ranges_definition = $(foreach i,$(jpg_assets), {"$(i).jpg", &_ion_simulator_$(i)_start, &_ion_simulator_$(i)_end},)
assets_address_ranges_declaration = $(foreach i,$(assets),extern unsigned char _ion_simulator_$(basename $(i))_start;)
assets_address_ranges_declaration += $(foreach i,$(assets),extern unsigned char _ion_simulator_$(basename $(i))_end;)
assets_address_ranges_definition = $(foreach i,$(assets), {"$(i)", &_ion_simulator_$(basename $(i))_start, &_ion_simulator_$(basename $(i))_end},)
$(call object_for,ion/src/simulator/linux/images.cpp): CXXFLAGS += -DASSETS_ADDRESS_RANGES_DECLARATION='$(assets_address_ranges_declaration)' -DASSETS_ADDRESS_RANGES_DEFINITION='$(assets_address_ranges_definition)'

View File

@@ -1,27 +1,29 @@
# This script generates a .s file representing jpg assets in order to access
# This script generates a .s file representing assets in order to access
# them from C code
import sys
import re
import argparse
import io
import os
parser = argparse.ArgumentParser(description="Process some jpg files.")
parser.add_argument('--files', nargs='+', help='a list of jpg file names')
parser = argparse.ArgumentParser(description="Process some asset files.")
parser.add_argument('--files', nargs='+', help='a list of file names')
parser.add_argument('--implementation', help='the .s file to generate')
args = parser.parse_args()
def print_jpg(f, jpg):
f.write(".global _ion_simulator_" + jpg + "_start\n")
f.write(".global _ion_simulator_" + jpg + "_end\n")
f.write("_ion_simulator_" + jpg + "_start:\n")
f.write(" .incbin \"ion/src/simulator/assets/" + jpg + ".jpg\"\n")
f.write("_ion_simulator_" + jpg + "_end:\n\n")
def print_asset(f, asset):
asset_basename = os.path.splitext(asset)[0]
f.write(".global _ion_simulator_" + asset_basename + "_start\n")
f.write(".global _ion_simulator_" + asset_basename + "_end\n")
f.write("_ion_simulator_" + asset_basename + "_start:\n")
f.write(" .incbin \"ion/src/simulator/assets/" + asset + "\"\n")
f.write("_ion_simulator_" + asset_basename + "_end:\n\n")
def print(files, path):
f = open(path, "w")
for jpg in files:
print_jpg(f, jpg)
for asset in files:
print_asset(f, asset)
f.close()

View File

@@ -2,6 +2,7 @@
#include <SDL.h>
#include <jpeglib.h>
#include <png.h>
#include <assert.h>
#ifndef ASSETS_ADDRESS_RANGES_DECLARATION
@@ -17,66 +18,152 @@ static struct {
ASSETS_ADDRESS_RANGES_DEFINITION
};
SDL_Texture * IonSimulatorLoadImage(SDL_Renderer * renderer, const char * identifier, bool withTransparency, uint8_t alpha) {
enum class AssetFormat {
JPG,
PNG
};
png_size_t readSize = 0;
void ReadDataFromMemory(png_structp png, png_bytep outBytes, png_size_t byteSize) {
png_voidp io = png_get_io_ptr(png);
memcpy((char *)outBytes, (char *)io + readSize, byteSize);
readSize += byteSize;
}
bool readPNG(unsigned char * start, size_t size, unsigned char ** bitmapData, unsigned int * width, unsigned int * height, unsigned int * bytesPerPixel, Uint32 * pixelFormat) {
readSize = 0;
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png) { return false; } // Memory failure
png_infop info = png_create_info_struct(png);
if (!info) {
// Memory failure
png_destroy_read_struct(&png, NULL, NULL);
return false;
}
static constexpr size_t k_pngSignatureLength = 8;
if(png_sig_cmp((png_const_bytep)start, 0, k_pngSignatureLength) != 0) { return false; } // Corrupted PNG
png_set_read_fn(png, start, ReadDataFromMemory);
png_read_info(png, info);
int bitDepth = 0;
int colorType = -1;
png_get_IHDR(png, info, width, height, &bitDepth, &colorType, nullptr, nullptr, nullptr);
*bytesPerPixel = bitDepth*4/8;
*pixelFormat = SDL_PIXELFORMAT_ARGB8888;
assert(colorType == PNG_COLOR_TYPE_RGB_ALPHA);
const png_uint_32 bytesPerRow = png_get_rowbytes(png, info);
*bitmapData = new unsigned char[*height * bytesPerRow];
unsigned char * rowData = *bitmapData;
// read single row at a time
for(unsigned int rowIndex = 0; rowIndex < *height; rowIndex++) {
png_read_row(png, (png_bytep)rowData, nullptr);
rowData += bytesPerRow;
}
png_destroy_read_struct(&png, &info, nullptr);
return true;
}
bool readJPG(const unsigned char * start, size_t size, unsigned char ** bitmapData, unsigned int * width, unsigned int * height, unsigned int * bytesPerPixel, Uint32 * pixelFormat) {
*pixelFormat = SDL_PIXELFORMAT_RGB24;
struct jpeg_decompress_struct info;
struct jpeg_error_mgr err;
info.err = jpeg_std_error(&err);
jpeg_create_decompress(&info);
unsigned char * jpegStart = nullptr;
unsigned long jpegSize = 0;
for (size_t i = 0; i < sizeof(resources_addresses)/sizeof(resources_addresses[0]); i++) {
if (strcmp(identifier, resources_addresses[i].identifier) == 0) {
jpegStart = resources_addresses[i].start;
jpegSize = resources_addresses[i].end - resources_addresses[i].start;
break;
}
}
assert(jpegStart);
jpeg_mem_src(&info, jpegStart, jpegSize);
jpeg_mem_src(&info, start, size);
if (jpeg_read_header(&info, TRUE) != 1) {
return nullptr;
return false;
}
jpeg_start_decompress(&info);
int width = info.output_width;
int height = info.output_height;
int bytesPerPixel = info.output_components;
int bitsPerPixel = bytesPerPixel*8;
unsigned char * bitmapData = new unsigned char[height * width * bytesPerPixel];
*width = info.output_width;
*height = info.output_height;
*bytesPerPixel = info.output_components;
*bitmapData = new unsigned char[*height * *width * *bytesPerPixel];
while (info.output_scanline < info.output_height) {
unsigned char * buffer_array[1];
buffer_array[0] = bitmapData + info.output_scanline * width * bytesPerPixel;
buffer_array[0] = *bitmapData + info.output_scanline * *width * *bytesPerPixel;
jpeg_read_scanlines(&info, buffer_array, 1);
}
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
return true;
}
Uint32 surfacePixelFormat = SDL_PIXELFORMAT_RGB24;
assert(bytesPerPixel == SDL_BYTESPERPIXEL(surfacePixelFormat));
SDL_Texture * IonSimulatorLoadImage(SDL_Renderer * renderer, const char * identifier) {
static constexpr const char * jpgExtension = ".jpg";
static constexpr const char * pngExtension = ".png";
SDL_Surface * surface = SDL_CreateRGBSurfaceWithFormatFrom(
bitmapData,
width,
height,
bitsPerPixel,
width * bytesPerPixel,
surfacePixelFormat);
unsigned char * assetStart = nullptr;
unsigned long assertSize = 0;
AssetFormat format;
SDL_SetColorKey(surface, withTransparency, SDL_MapRGB(surface->format, 0xFF, 0xFF, 0xFF));
SDL_SetSurfaceAlphaMod(surface, alpha);
// Find the asset corresponding to identifier
for (size_t i = 0; i < sizeof(resources_addresses)/sizeof(resources_addresses[0]); i++) {
if (strcmp(identifier, resources_addresses[i].identifier) == 0) {
if (strcmp(jpgExtension, identifier + strlen(identifier) - strlen(jpgExtension)) == 0) {
format = AssetFormat::JPG;
} else {
assert(strcmp(pngExtension, identifier + strlen(identifier) - strlen(pngExtension)) == 0);
format = AssetFormat::PNG;
}
assetStart = resources_addresses[i].start;
assertSize = resources_addresses[i].end - resources_addresses[i].start;
break;
}
}
assert(assetStart);
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
unsigned int width;
unsigned int height;
unsigned int bytesPerPixel;
unsigned char * bitmapData;
Uint32 pixelFormat;
switch (format) {
case AssetFormat::JPG:
if (!readJPG(assetStart, assertSize, &bitmapData, &width, &height, &bytesPerPixel, &pixelFormat)) {
return nullptr;
}
break;
default:
assert(format == AssetFormat::PNG);
if (!readPNG(assetStart, assertSize, &bitmapData, &width, &height, &bytesPerPixel, &pixelFormat)) {
return nullptr;
}
}
assert(bytesPerPixel == SDL_BYTESPERPIXEL(pixelFormat));
SDL_Texture * texture = SDL_CreateTexture(
renderer,
pixelFormat,
SDL_TEXTUREACCESS_STATIC,
width,
height
);
SDL_UpdateTexture(
texture,
nullptr,
bitmapData,
width * bytesPerPixel
);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
delete[] bitmapData;
SDL_FreeSurface(surface);
return texture;
}