Create upscale sprite function

This commit is contained in:
Nacho 2026-05-28 01:31:03 +02:00
parent 0b5c56b5e3
commit dc44a695be
4 changed files with 179 additions and 90 deletions

124
src/storage/read_file.cpp Normal file
View File

@ -0,0 +1,124 @@
#include "storage.h"
#include "memory/memory.h"
#include "defs/defs.h"
#include "utils/utils.h"
const char* TAG_SR = "[STORAGE]";
void storage_readFile(const char* path, struct SpriteData* spriteData) {
File file = SPIFFS.open(path, "r");
if (!file) {
printf("%s Failed to open file for reading\n", TAG_SR);
return;
}
uint8_t width, height, spriteNumber;
file.read(&width, 1);
file.read(&height, 1);
file.read(&spriteNumber, 1);
if (spriteData->spriteData != NULL) {
memory_free(spriteData);
}
const uint8_t scaledW = width * SPRITE_SCALE;
const uint8_t scaledH = height * SPRITE_SCALE;
uint16_t** scaled =
(uint16_t**) ps_malloc(spriteNumber * sizeof(uint16_t*));
if (!scaled) {
printf("%s PSRAM alloc failed for pointer table\n", TAG_SR);
file.close();
return;
}
for (uint8_t i = 0; i < spriteNumber; i++) {
scaled[i] =
(uint16_t*) ps_malloc(scaledW * scaledH * sizeof(uint16_t));
if (!scaled[i]) {
printf("%s PSRAM alloc failed for sprite %d\n", TAG_SR, i);
for (uint8_t j = 0; j < i; j++) {
free(scaled[j]);
}
free(scaled);
file.close();
return;
}
}
uint16_t* spriteBuf =
(uint16_t*) malloc(width * height * sizeof(uint16_t));
if (!spriteBuf) {
printf("%s scratch alloc failed\n", TAG_SR);
for (uint8_t i = 0; i < spriteNumber; i++) {
free(scaled[i]);
}
free(scaled);
file.close();
return;
}
printf(
"%s Read header: width=%d, height=%d, numSprites=%d -> scaled to %dx%d\n",
TAG_SR,
width,
height,
spriteNumber,
scaledW,
scaledH
);
for (int sprN = 0; sprN < spriteNumber; sprN++) {
// Read original sprite into temporary buffer
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
uint8_t hi, lo;
file.read(&hi, 1);
file.read(&lo, 1);
spriteBuf[y * width + x] =
(lo << 8) | hi;
}
}
// Upscale sprite
utils_upscaleSprite(
spriteBuf,
width,
height,
scaled[sprN]
);
}
free(spriteBuf);
file.close();
spriteData->spriteWidth = scaledW;
spriteData->spriteHeight = scaledH;
spriteData->spriteNumber = spriteNumber;
spriteData->spriteData = scaled;
printf(
"%s Loaded & upscaled %s (%d sprites, each %dx%d px)\n",
TAG_SR,
path,
spriteNumber,
scaledW,
scaledH
);
}

View File

@ -8,8 +8,6 @@
const char* TAG_S = "[STORAGE]"; const char* TAG_S = "[STORAGE]";
#define SPRITE_SCALE 6
void storage_init() { void storage_init() {
if (!SPIFFS.begin(true)) { if (!SPIFFS.begin(true)) {
printf("%s Failed to mount file system\n", TAG_S); printf("%s Failed to mount file system\n", TAG_S);
@ -19,94 +17,6 @@ void storage_init() {
} }
void storage_readFile(const char* path, struct SpriteData* spriteData) {
File file = SPIFFS.open(path, "r");
if (!file) {
printf("%s Failed to open file for reading\n", TAG_S);
return;
}
uint8_t width, height, spriteNumber;
file.read(&width, 1);
file.read(&height, 1);
file.read(&spriteNumber, 1);
if (spriteData->spriteData != NULL) {
memory_free(spriteData);
}
const uint8_t scaledW = width * SPRITE_SCALE;
const uint8_t scaledH = height * SPRITE_SCALE;
uint16_t** scaled = (uint16_t**) ps_malloc(spriteNumber * sizeof(uint16_t*));
if (!scaled) {
printf("%s PSRAM alloc failed for pointer table\n", TAG_S);
file.close();
return;
}
for (uint8_t i = 0; i < spriteNumber; i++) {
scaled[i] = (uint16_t*) ps_malloc(scaledW * scaledH * sizeof(uint16_t));
if (!scaled[i]) {
printf("%s PSRAM alloc failed for sprite %d\n", TAG_S, i);
for (uint8_t j = 0; j < i; j++) free(scaled[j]);
free(scaled);
file.close();
return;
}
}
uint16_t* rowBuf = (uint16_t*) malloc(width * sizeof(uint16_t));
if (!rowBuf) {
printf("%s scratch alloc failed\n", TAG_S);
for (uint8_t i = 0; i < spriteNumber; i++) free(scaled[i]);
free(scaled);
file.close();
return;
}
printf(
"%s Read header: width=%d, height=%d, numSprites=%d -> scaled to %dx%d\n",
TAG_S, width, height, spriteNumber, scaledW, scaledH
);
for (int sprN = 0; sprN < spriteNumber; sprN++) {
uint16_t* dst = scaled[sprN];
for (int srcY = 0; srcY < height; srcY++) {
for (int srcX = 0; srcX < width; srcX++) {
uint8_t hi, lo;
file.read(&hi, 1);
file.read(&lo, 1);
rowBuf[srcX] = (lo << 8) | hi;
}
for (int dy = 0; dy < SPRITE_SCALE; dy++) {
uint16_t* dstRow = dst + (srcY * SPRITE_SCALE + dy) * scaledW;
for (int srcX = 0; srcX < width; srcX++) {
uint16_t color = rowBuf[srcX];
uint16_t* dstPixel = dstRow + srcX * SPRITE_SCALE;
for (int dx = 0; dx < SPRITE_SCALE; dx++) {
dstPixel[dx] = color;
}
}
}
}
}
free(rowBuf);
file.close();
spriteData->spriteWidth = scaledW;
spriteData->spriteHeight = scaledH;
spriteData->spriteNumber = spriteNumber;
spriteData->spriteData = scaled;
printf("%s Loaded & upscaled %s (%d sprites, each %dx%d px)\n",
TAG_S, path, spriteNumber, scaledW, scaledH);
}
void storage_initBackground(const char* path, TFT_eSprite& bg) { void storage_initBackground(const char* path, TFT_eSprite& bg) {
File file = SPIFFS.open(path, "r"); File file = SPIFFS.open(path, "r");
if (!file) { if (!file) {

View File

@ -0,0 +1,41 @@
#include "utils.h"
#include "defs/defs.h"
/**
* Upscale a sprite using nearest-neighbor scaling.
*
* @param src Pointer to source sprite pixels
* @param srcWidth Original sprite width
* @param srcHeight Original sprite height
* @param dst Destination buffer for upscaled sprite
*/
void utils_upscaleSprite(
const uint16_t* src,
uint8_t srcWidth,
uint8_t srcHeight,
uint16_t* dst
) {
const uint8_t scaledW = srcWidth * SPRITE_SCALE;
for (int srcY = 0; srcY < srcHeight; srcY++) {
for (int dy = 0; dy < SPRITE_SCALE; dy++) {
uint16_t* dstRow =
dst + ((srcY * SPRITE_SCALE + dy) * scaledW);
for (int srcX = 0; srcX < srcWidth; srcX++) {
uint16_t color = src[srcY * srcWidth + srcX];
uint16_t* dstPixel =
dstRow + (srcX * SPRITE_SCALE);
for (int dx = 0; dx < SPRITE_SCALE; dx++) {
dstPixel[dx] = color;
}
}
}
}
}

14
src/utils/utils.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef UTILS_H
#define UTILS_H
#include <Arduino.h>
void utils_upscaleSprite(
const uint16_t* src,
uint8_t srcWidth,
uint8_t srcHeight,
uint16_t* dst
);
#endif