mirror of
https://github.com/nacabaro/nacapet.git
synced 2026-06-05 14:02:53 +00:00
Create upscale sprite function
This commit is contained in:
parent
0b5c56b5e3
commit
dc44a695be
124
src/storage/read_file.cpp
Normal file
124
src/storage/read_file.cpp
Normal 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
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -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) {
|
||||||
|
|||||||
41
src/utils/upscale_sprite.cpp
Normal file
41
src/utils/upscale_sprite.cpp
Normal 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
14
src/utils/utils.h
Normal 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
|
||||||
Loading…
x
Reference in New Issue
Block a user