Image generation?

This commit is contained in:
2025-08-27 22:43:38 -05:00
parent 6c11096fd2
commit 31fa4948d5
7 changed files with 80 additions and 38 deletions

View File

@@ -3,6 +3,5 @@
# This software is released under the MIT License. # This software is released under the MIT License.
# https://opensource.org/licenses/MIT # https://opensource.org/licenses/MIT
add_asset(test.palette.png) add_asset(first.palette.png)
# add_asset(first.palette.png) add_asset(entities.tsx)
# add_asset(entities.tsx)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 B

View File

@@ -40,18 +40,6 @@ errorret_t assetInit(void) {
// Did we open the asset? // Did we open the asset?
if(ASSET.zip == NULL) errorThrow("Failed to open asset file."); if(ASSET.zip == NULL) errorThrow("Failed to open asset file.");
// Get "test.palette.dpf" file.
zip_file_t *file = zip_fopen(ASSET.zip, "test.palette.dpf", 0);
if(file == NULL) errorThrow("Failed to open test.palette.dpf in asset file.");
// Read it
char_t buffer[256];
zip_int64_t n = zip_fread(file, buffer, 256);
if(n < 0) {
zip_fclose(file);
errorThrow("Failed to read test.palette.dpf in asset file.");
}
errorOk(); errorOk();
} }
@@ -98,6 +86,8 @@ void assetLoad(
return; return;
} }
printf("Loading asset: %s\n", filename);
// Determine length of the file (uncompressed) // Determine length of the file (uncompressed)
struct zip_stat st; struct zip_stat st;
if(zip_stat(ASSET.zip, filename, 0, &st) != 0) { if(zip_stat(ASSET.zip, filename, 0, &st) != 0) {

View File

@@ -35,7 +35,7 @@ errorret_t engineInit(void) {
errorChain(assetInit()); errorChain(assetInit());
errorChain(displayInit()); errorChain(displayInit());
assetLoad("test.palette.dpf", assetLoadCallback, NULL); assetLoad("first.palette.dpf", assetLoadCallback, NULL);
if(ASSET.state == ASSET_STATE_ERROR) errorChain(ASSET.error); if(ASSET.state == ASSET_STATE_ERROR) errorChain(ASSET.error);
sceneTestAdd(); sceneTestAdd();

View File

@@ -2,6 +2,10 @@ import os
from args import args from args import args
from PIL import Image from PIL import Image
import struct import struct
import sys
from assethelpers import getAssetRelativePath
PALETTES = []
def extractPaletteFromImage(image): def extractPaletteFromImage(image):
# goes through and finds all unique colors in the image # goes through and finds all unique colors in the image
@@ -10,6 +14,9 @@ def extractPaletteFromImage(image):
pixels = list(image.getdata()) pixels = list(image.getdata())
uniqueColors = [] uniqueColors = []
for color in pixels: for color in pixels:
# We treat alpha 0 as rgba(0,0,0,0) for palette purposes
if color[3] == 0:
color = (0, 0, 0, 0)
if color not in uniqueColors: if color not in uniqueColors:
uniqueColors.append(color) uniqueColors.append(color)
return uniqueColors return uniqueColors
@@ -40,21 +47,70 @@ def processPalette(assetPath):
outputRelative = os.path.relpath(outputFilePath, args.output_assets) outputRelative = os.path.relpath(outputFilePath, args.output_assets)
return { palette = {
"outputFile": outputRelative, "outputFile": outputRelative,
"paletteColors": len(pixels), "paletteColors": len(pixels),
"files": [ outputFilePath ] "files": [ outputFilePath ],
"pixels": pixels
} }
PALETTES.append(palette)
return palette
def processImage(assetPath): def processImage(assetPath):
print(f"Processing image: {assetPath}") print(f"Processing image: {assetPath}")
# Load the image # Load the image
image = Image.open(assetPath) image = Image.open(assetPath)
pixels = extractPaletteFromImage(image)
# Get the image's palette because we are going to try and find a matching
# palette from the already processed palettes...
imagePalette = extractPaletteFromImage(image)
# Now find which palette has every single color in this image's palette
paletteIndex = -1
for i, palette in enumerate(PALETTES):
paletteColors = palette["pixels"]
if all(color in paletteColors for color in imagePalette):
paletteIndex = i
break
# Did we manage to find a matching palette?
if paletteIndex == -1:
print(f"Error: No matching palette found for image {assetPath}. Please process a suitable palette first.")
sys.exit(1)
# We found the palette, so now we can convert the image to use that palette
palette = PALETTES[paletteIndex]
indexes = []
for color in imagePalette:
if color in palette["pixels"]:
index = palette["pixels"].index(color)
indexes.append(index)
else:
print(f"Error: Color {color} in image {assetPath} not found in palette.")
sys.exit(1)
relative = getAssetRelativePath(assetPath)
fileNameWithoutExt = os.path.splitext(os.path.basename(assetPath))[0]
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dpi")
outputFilePath = os.path.join(args.output_assets, outputFileRelative)
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
with open(outputFilePath, "wb") as f:
# Write header
f.write(b"DPI") # Dusk Palettized Image
f.write(struct.pack("<i", image.width)) # Width
f.write(struct.pack("<i", image.height)) # Height
f.write(struct.pack("<i", paletteIndex)) # Palette index
# Write uint8_t pixel index.
for index in indexes:
f.write(struct.pack("B", index))
return { return {
# "outputFile": os.path.relpath(assetPath, args.input_assets), "paletteIndex": paletteIndex,
# "paletteColors": len(pixels), "palette": PALETTES[paletteIndex],
"files": [ assetPath ] "outputFile": outputFileRelative,
"files": [ assetPath, outputFilePath ]
} }

View File

@@ -47,32 +47,28 @@ def processTileset(assetPath):
relativeFile = getAssetRelativePath(assetPath) relativeFile = getAssetRelativePath(assetPath)
relativeDir = os.path.dirname(relativeFile) relativeDir = os.path.dirname(relativeFile)
data = "DTF" # Header for Dusk Tileset Format
# Write width (int32_t)
data += tilewidth.to_bytes(4, byteorder='little').decode('latin1')
# Write height (int32_t)
data += tileheight.to_bytes(4, byteorder='little').decode('latin1')
# Write tilecount (int32_t)
data += tilecount.to_bytes(4, byteorder='little').decode('latin1')
# Write column count (int32_t)
data += columns.to_bytes(4, byteorder='little').decode('latin1')
# Write row count (int32_t)
rows = (tilecount + columns - 1) // columns rows = (tilecount + columns - 1) // columns
data += rows.to_bytes(4, byteorder='little').decode('latin1')
buf = bytearray(b"DTF")
buf += tilewidth.to_bytes(4, byteorder='little')
buf += tileheight.to_bytes(4, byteorder='little')
buf += tilecount.to_bytes(4, byteorder='little')
buf += columns.to_bytes(4, byteorder='little')
buf += rows.to_bytes(4, byteorder='little')
# Write image source file name, padd to ASSET_FILE_NAME_MAX_LENGTH # Write image source file name, padd to ASSET_FILE_NAME_MAX_LENGTH
imageSourceBytes = image["outputFile"].encode('utf-8') imageSourceBytes = image["outputFile"].encode('utf-8')
data += len(imageSourceBytes).to_bytes(4, byteorder='little').decode('latin1') buf += len(imageSourceBytes).to_bytes(4, byteorder='little')
data += imageSourceBytes.decode('latin1') buf += imageSourceBytes
paddingLength = max(0, ASSET_FILE_NAME_MAX_LENGTH - len(imageSourceBytes)) paddingLength = max(0, ASSET_FILE_NAME_MAX_LENGTH - len(imageSourceBytes))
data += '\x00' * paddingLength buf += b'\x00' * paddingLength
# Write to output file # Write to output file
fileNameWithoutExt = os.path.splitext(os.path.basename(assetPath))[0] fileNameWithoutExt = os.path.splitext(os.path.basename(assetPath))[0]
outputFilePath = os.path.join(args.output_assets, relativeDir, f"{fileNameWithoutExt}.dtf") outputFilePath = os.path.join(args.output_assets, relativeDir, f"{fileNameWithoutExt}.dtf")
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True) os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
with open(outputFilePath, 'wb') as f: with open(outputFilePath, 'wb') as f:
f.write(data.encode('latin1')) f.write(buf)
return { return {
"outputFile": os.path.relpath(outputFilePath, args.output_assets), "outputFile": os.path.relpath(outputFilePath, args.output_assets),
@@ -81,5 +77,6 @@ def processTileset(assetPath):
"tileCount": tilecount, "tileCount": tilecount,
"columns": columns, "columns": columns,
"rows": rows, "rows": rows,
"image": image "image": image,
"files": [ outputFilePath ] + image["files"]
} }