xfc2sta/imgconvert now uses GIMP instead of xcftools and produces optional stencil buffers.
This commit is contained in:
parent
66b7d8b38b
commit
9690c278b0
6 changed files with 275 additions and 90 deletions
|
@ -9,6 +9,118 @@
|
||||||
#include "joey.h"
|
#include "joey.h"
|
||||||
|
|
||||||
|
|
||||||
|
void convertColor(char *filename, char *basename, bool showIt);
|
||||||
|
void convertStencil(char *filename, char *basename);
|
||||||
|
bool fileExists(char *filename);
|
||||||
|
Uint32 getPixel(SDL_Surface *surface, int x, int y);
|
||||||
|
SDL_Surface *loadImage(char *filename);
|
||||||
|
|
||||||
|
|
||||||
|
void convertColor(char *filename, char *basename, bool showIt) {
|
||||||
|
|
||||||
|
int colors = INT_MAX;
|
||||||
|
SDL_Color *c = NULL;
|
||||||
|
SDL_Surface *image = loadImage(filename);
|
||||||
|
|
||||||
|
if (image == NULL) return;
|
||||||
|
|
||||||
|
colors = image->format->palette->ncolors;
|
||||||
|
c = image->format->palette->colors;
|
||||||
|
|
||||||
|
jlStaT *sta = NULL;
|
||||||
|
jlStaCreate(sta);
|
||||||
|
|
||||||
|
for (int x=0; x<colors; x++) {
|
||||||
|
sta->palette[x].r = c[x].r / 16;
|
||||||
|
sta->palette[x].g = c[x].g / 16;
|
||||||
|
sta->palette[x].b = c[x].b / 16;
|
||||||
|
//printf("Palette %03d = R%03d G%03d B%03d\n", x, sta->palette[x].r, sta->palette[x].g, sta->palette[x].b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colors < 16) {
|
||||||
|
for (int x=colors; x<16; x++) {
|
||||||
|
sta->palette[x].r = 0;
|
||||||
|
sta->palette[x].g = 0;
|
||||||
|
sta->palette[x].b = 0;
|
||||||
|
//printf("Palette %03d = R000 G000 B000 (added)\n", x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int p = 0;
|
||||||
|
for (int y=0; y<image->h; y++) {
|
||||||
|
for (int x=0; x<image->w; x+=2) {
|
||||||
|
//printf("%02X %02X ", getPixel(image, x, y), getPixel(image, x + 1, y));
|
||||||
|
// These are backwards - no idea why yet.
|
||||||
|
sta->pixels[p].r = (unsigned char)getPixel(image, x, y);
|
||||||
|
sta->pixels[p++].l = (unsigned char)getPixel(image, x + 1, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jlStaSave(sta, basename);
|
||||||
|
|
||||||
|
SDL_FreeSurface(image);
|
||||||
|
|
||||||
|
if (showIt) {
|
||||||
|
jlStaDisplay(sta);
|
||||||
|
jlDisplayPresent();
|
||||||
|
jlKeyWaitForAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
jlStaFree(sta);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void convertStencil(char *filename, char *basename) {
|
||||||
|
|
||||||
|
// Stencil files aren't required
|
||||||
|
if (!fileExists(filename)) return;
|
||||||
|
|
||||||
|
int bytes = 0;
|
||||||
|
byte data = 0;
|
||||||
|
int bits = 0;
|
||||||
|
SDL_Surface *image = loadImage(filename);
|
||||||
|
char name[2048];
|
||||||
|
FILE *out;
|
||||||
|
|
||||||
|
snprintf(name, 2048, "%s.stn", basename);
|
||||||
|
out = fopen(name, "wb");
|
||||||
|
if (!out) {
|
||||||
|
fprintf(stderr, "Unable to save stencil: %s\n", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputc('S', out);
|
||||||
|
fputc('T', out);
|
||||||
|
fputc('N', out);
|
||||||
|
fputc( 0, out);
|
||||||
|
|
||||||
|
for (int y=0; y<image->h; y++) {
|
||||||
|
for (int x=0; x<image->w; x++) {
|
||||||
|
data <<= 1;
|
||||||
|
data |= (getPixel(image, x, y) == 0);
|
||||||
|
bits++;
|
||||||
|
if (bits > 7) {
|
||||||
|
bytes++;
|
||||||
|
bits = 0;
|
||||||
|
fputc(data, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool fileExists(char *filename) {
|
||||||
|
FILE *file;
|
||||||
|
if ((file = fopen(filename, "r+"))) {
|
||||||
|
fclose(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||||
|
|
||||||
|
@ -47,85 +159,51 @@ Uint32 getPixel(SDL_Surface *surface, int x, int y) {
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
|
||||||
|
SDL_Surface *loadImage(char *filename) {
|
||||||
|
|
||||||
|
if (!fileExists(filename)) {
|
||||||
|
fprintf(stderr, "Unable to load image: %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface *image = IMG_Load(filename);
|
||||||
|
int colors = INT_MAX;
|
||||||
|
|
||||||
|
if (image->format->palette != NULL) {
|
||||||
|
colors = image->format->palette->ncolors;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("%s = %dx%d, %d bits per pixel, %d colors\n", filename, image->w, image->h, image->format->BitsPerPixel, colors);
|
||||||
|
|
||||||
|
if (image->w != 320 || image->h != 200 || colors > 16) {
|
||||||
|
fprintf(stderr, "Image must be 320x200 pixels, 8 bits per pixel, with 16 or fewer colors.\n");
|
||||||
|
free(image);
|
||||||
|
image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
printf("Usage: %s [infile] [outfile] {anyting}\n", argv[0]);
|
printf("Usage: %s [color.png] [stencil.png] [outfile] {anyting}\n", argv[0]);
|
||||||
printf("(If {anything} is provided, image will be displayed as converted until keypress.)\n");
|
printf("(If {anything} is provided, image will be displayed as converted until keypress.)\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
jlUtilStartup("STA Converter");
|
jlUtilStartup("STA/STN Converter");
|
||||||
|
|
||||||
int imageFlags = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF;
|
int imageFlags = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF;
|
||||||
int imageResult = IMG_Init(imageFlags);
|
int imageResult = IMG_Init(imageFlags);
|
||||||
if ((imageResult & imageFlags) != imageFlags) {
|
if ((imageResult & imageFlags) != imageFlags) {
|
||||||
printf("Failed to initialize SDL2_Image: %s\n", IMG_GetError());
|
fprintf(stderr, "Failed to initialize SDL2_Image: %s\n", IMG_GetError());
|
||||||
jlUtilShutdown();
|
jlUtilShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface *image = IMG_Load(argv[1]);
|
convertColor(argv[1], argv[3], argc > 4);
|
||||||
int colors = INT_MAX;
|
convertStencil(argv[2], argv[3]);
|
||||||
SDL_Color *c = NULL;
|
|
||||||
|
|
||||||
if (image->format->palette != NULL) {
|
|
||||||
colors = image->format->palette->ncolors;
|
|
||||||
if (colors > 16) {
|
|
||||||
colors = 16;
|
|
||||||
printf("Source palette has more than 16 colors. Only the first 16 will be used.\n");
|
|
||||||
}
|
|
||||||
c = image->format->palette->colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s = %dx%d, %d bits per pixel, %d colors\n", argv[1], image->w, image->h, image->format->BitsPerPixel, colors);
|
|
||||||
|
|
||||||
if (image->w != 320 || image->h != 200 || image->format->BitsPerPixel != 8 || colors > 16) {
|
|
||||||
printf("Image must be 320x200 pixels, 8 bits per pixel, with 16 or fewer colors.\n");
|
|
||||||
free(image);
|
|
||||||
IMG_Quit();
|
|
||||||
jlUtilShutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
jlStaT *sta = NULL;
|
|
||||||
jlStaCreate(sta);
|
|
||||||
|
|
||||||
for (int x=0; x<colors; x++) {
|
|
||||||
sta->palette[x].r = c[x].r / 16;
|
|
||||||
sta->palette[x].g = c[x].g / 16;
|
|
||||||
sta->palette[x].b = c[x].b / 16;
|
|
||||||
printf("Palette %03d = R%03d G%03d B%03d\n", x, sta->palette[x].r, sta->palette[x].g, sta->palette[x].b);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors < 16) {
|
|
||||||
for (int x=colors; x<16; x++) {
|
|
||||||
sta->palette[x].r = 0;
|
|
||||||
sta->palette[x].g = 0;
|
|
||||||
sta->palette[x].b = 0;
|
|
||||||
printf("Palette %03d = R000 G000 B000 (added)\n", x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int p = 0;
|
|
||||||
for (int y=0; y<image->h; y++) {
|
|
||||||
for (int x=0; x<image->w; x+=2) {
|
|
||||||
//printf("%02X %02X ", getPixel(image, x, y), getPixel(image, x + 1, y));
|
|
||||||
// These are backwards - no idea why yet.
|
|
||||||
sta->pixels[p].r = (unsigned char)getPixel(image, x, y);
|
|
||||||
sta->pixels[p++].l = (unsigned char)getPixel(image, x + 1, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jlStaSave(sta, argv[2]);
|
|
||||||
|
|
||||||
SDL_FreeSurface(image);
|
|
||||||
|
|
||||||
if (argc > 3) {
|
|
||||||
jlStaDisplay(sta);
|
|
||||||
jlDisplayPresent();
|
|
||||||
jlKeyWaitForAny();
|
|
||||||
}
|
|
||||||
|
|
||||||
jlStaFree(sta);
|
|
||||||
|
|
||||||
IMG_Quit();
|
IMG_Quit();
|
||||||
jlUtilShutdown();
|
jlUtilShutdown();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
JOEY = /home/scott/joey
|
JOEY = /home/scott/joey
|
||||||
CONFIG += SDL12
|
#CONFIG += SDL12
|
||||||
#CONFIG += SDL2
|
CONFIG += SDL2
|
||||||
|
|
||||||
|
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|
|
@ -33,7 +33,7 @@ segment "testapp";
|
||||||
|
|
||||||
|
|
||||||
//extern jint16 asmTest(jlSurfaceT source);
|
//extern jint16 asmTest(jlSurfaceT source);
|
||||||
//extern void asmDrawLine(jlSurfaceT target, jint16 color, jint16 x1, jint16 y1, jint16 x2, jint16 y2);
|
extern void asmDrawLine(jlSurfaceT target, jint16 color, jint16 x1, jint16 y1, jint16 x2, jint16 y2);
|
||||||
|
|
||||||
|
|
||||||
// Font hacking!
|
// Font hacking!
|
||||||
|
@ -96,13 +96,11 @@ void lineTest(void) {
|
||||||
printAt(font, 1, y++, "Drawing %s ", what);
|
printAt(font, 1, y++, "Drawing %s ", what);
|
||||||
|
|
||||||
jlDrawColorSet((byte)color);
|
jlDrawColorSet((byte)color);
|
||||||
/*
|
|
||||||
if (phase < 2) {
|
if (phase < 2) {
|
||||||
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, x2, y2, 319-x2, 199-y2);
|
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, x2, y2, 319-x2, 199-y2);
|
||||||
} else {
|
} else {
|
||||||
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, 319-x2, 199-y2, x2, y2);
|
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, 319-x2, 199-y2, x2, y2);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
ox = x2;
|
ox = x2;
|
||||||
oy = y2;
|
oy = y2;
|
||||||
op = phase;
|
op = phase;
|
||||||
|
@ -148,13 +146,11 @@ void lineTest(void) {
|
||||||
jlDisplayPresent();
|
jlDisplayPresent();
|
||||||
|
|
||||||
jlDrawColorSet((byte)0);
|
jlDrawColorSet((byte)0);
|
||||||
/*
|
|
||||||
if (op < 2) {
|
if (op < 2) {
|
||||||
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, ox, oy, 319-ox, 199-oy);
|
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, ox, oy, 319-ox, 199-oy);
|
||||||
} else {
|
} else {
|
||||||
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, 319-ox, 199-oy, ox, oy);
|
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, 319-ox, 199-oy, ox, oy);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
color = nextColor;
|
color = nextColor;
|
||||||
nextColor++;
|
nextColor++;
|
||||||
|
@ -207,8 +203,8 @@ void blitTest(void) {
|
||||||
int main(void) {
|
int main(void) {
|
||||||
jlUtilStartup("JoeyLib Test");
|
jlUtilStartup("JoeyLib Test");
|
||||||
|
|
||||||
//lineTest();
|
lineTest();
|
||||||
blitTest();
|
//blitTest();
|
||||||
|
|
||||||
jlUtilShutdown();
|
jlUtilShutdown();
|
||||||
}
|
}
|
||||||
|
|
67
scripts/exportXCFLayers.scm
Normal file
67
scripts/exportXCFLayers.scm
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
(script-fu-register
|
||||||
|
"script-fu-export-joeylib" ;func name
|
||||||
|
"Export to JoeyLib" ;menu label
|
||||||
|
"Exports layers as individual 16 color PNGs." ;description
|
||||||
|
"Scott Duensing" ;author
|
||||||
|
"Copyright 2020 Scott Duensing" ;copyright notice
|
||||||
|
"May 6, 2020" ;date created
|
||||||
|
"" ;image type that the script works on
|
||||||
|
SF-FILENAME "XCF File" "input.xcf" ;default parameters
|
||||||
|
)
|
||||||
|
(script-fu-menu-register "script-fu-export-joeylib" "<Image>/File/Create/JoeyLib")
|
||||||
|
(define (script-fu-export-joeylib infile)
|
||||||
|
(let*
|
||||||
|
(
|
||||||
|
(image (car (gimp-xcf-load 1 infile infile)))
|
||||||
|
(basename (car (gimp-image-get-filename image)))
|
||||||
|
(count 1)
|
||||||
|
)
|
||||||
|
(when (string=? basename "")
|
||||||
|
(set! basename
|
||||||
|
(string-append
|
||||||
|
(car (gimp-temp-name ""))
|
||||||
|
(car (gimp-image-get-name image))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(let loop
|
||||||
|
(
|
||||||
|
(layers (vector->list (cadr (gimp-image-get-layers image))))
|
||||||
|
)
|
||||||
|
(unless (null? layers)
|
||||||
|
(gimp-edit-copy (car layers))
|
||||||
|
(let
|
||||||
|
(
|
||||||
|
(img (car (gimp-edit-paste-as-new)))
|
||||||
|
(new-name
|
||||||
|
(string-append
|
||||||
|
basename
|
||||||
|
"-DoNtEvErDoThIs-"
|
||||||
|
(number->string count)
|
||||||
|
".png"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(gimp-image-convert-indexed img
|
||||||
|
NO-DITHER
|
||||||
|
MAKE-PALETTE
|
||||||
|
16
|
||||||
|
FALSE
|
||||||
|
FALSE
|
||||||
|
"")
|
||||||
|
(set! count (+ count 1))
|
||||||
|
(file-png-save
|
||||||
|
1
|
||||||
|
img
|
||||||
|
(aref (cadr (gimp-image-get-layers img)) 0)
|
||||||
|
new-name
|
||||||
|
new-name
|
||||||
|
TRUE 9 TRUE TRUE TRUE TRUE TRUE
|
||||||
|
)
|
||||||
|
(gimp-image-delete img)
|
||||||
|
)
|
||||||
|
(loop (cdr layers))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
|
@ -925,6 +925,7 @@ function start() {
|
||||||
bison \
|
bison \
|
||||||
build-essential \
|
build-essential \
|
||||||
bzip2 \
|
bzip2 \
|
||||||
|
ciopfs \
|
||||||
clang \
|
clang \
|
||||||
cmake \
|
cmake \
|
||||||
cpio \
|
cpio \
|
||||||
|
@ -934,6 +935,7 @@ function start() {
|
||||||
gdb-mingw-w64 \
|
gdb-mingw-w64 \
|
||||||
genisoimage \
|
genisoimage \
|
||||||
gettext \
|
gettext \
|
||||||
|
gimp \
|
||||||
git \
|
git \
|
||||||
gzip \
|
gzip \
|
||||||
hatari \
|
hatari \
|
||||||
|
@ -975,7 +977,6 @@ function start() {
|
||||||
unzip \
|
unzip \
|
||||||
uuid-dev \
|
uuid-dev \
|
||||||
wget \
|
wget \
|
||||||
xcftools \
|
|
||||||
xz-utils
|
xz-utils
|
||||||
if [[ ! -z ${G_AUTOMATED} ]]; then
|
if [[ ! -z ${G_AUTOMATED} ]]; then
|
||||||
DOINSTALL=1
|
DOINSTALL=1
|
||||||
|
|
|
@ -1,24 +1,67 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [ -z $1 ]; then
|
# Did we get an image to convert?
|
||||||
echo $0 [name.xcf] {anything}
|
if [[ ! -f "$1" ]]; then
|
||||||
|
echo Usage: $0 [gimpPic.xcf] {anythingToPreview}
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
NAME=$(basename $1 .xcf)
|
# Find information about the image
|
||||||
DIR=$(dirname $1)
|
IMAGE=$(realpath "$1")
|
||||||
TARGET=/tmp/xcf2sta
|
FILENAME=$(basename "${IMAGE}")
|
||||||
TEMPIMAGE=${TARGET}/fixImageTemp.png
|
DIRNAME=$(dirname "${IMAGE}")
|
||||||
|
NAME=$(basename "$1" .xcf)
|
||||||
|
|
||||||
echo Converting ${1} to ${NAME}.sta...
|
# Is it really an XCF?
|
||||||
|
file "${IMAGE}" | grep -q "GIMP XCF"
|
||||||
|
if [[ "$?" -ne "0" ]]; then
|
||||||
|
echo ${FILENAME} is not a GIMP XCF image! >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p ${TARGET}/data
|
# Switch to folder where the image exists
|
||||||
xcf2png ${1} > ${TEMPIMAGE}
|
pusd "${DIRNAME}" &> /dev/null
|
||||||
|
|
||||||
pushd ${TARGET} &> /dev/null
|
# Run our Script-Fu to convert each layer to a PNG
|
||||||
${JOEY}/utils/imgconvert ${TEMPIMAGE} ${NAME} $2
|
gimp -i -d -f -s -c -b "(script-fu-export-joeylib \"${IMAGE}\")" -b "(gimp-quit 0)" &> /dev/null
|
||||||
|
|
||||||
|
# Count the PNGs we found
|
||||||
|
COUNT=$(find . -maxdepth 1 -name "${FILENAME}-DoNtEvErDoThIs-*.png" -printf '.' | wc -m)
|
||||||
|
|
||||||
|
# Did nothing come back out?
|
||||||
|
if [[ "${COUNT}" -eq "0" ]]; then
|
||||||
|
echo Unable to extract layers from ${FILENAME}! >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We only do the first two layers. If there's more, warn them.
|
||||||
|
if [[ "${COUNT}" -gt "2" ]]; then
|
||||||
|
echo ${COUNT} layers found. Only the first two will be used.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If there's no data dir, make one and remove it later.
|
||||||
|
if [[ -d data ]]; then
|
||||||
|
HASDATA=1
|
||||||
|
else
|
||||||
|
HASDATA=0
|
||||||
|
mkdir -p data
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Call custom converter
|
||||||
|
#${JOEY}/utils
|
||||||
|
./imgconvert "${FILENAME}-DoNtEvErDoThIs-1.png" "${FILENAME}-DoNtEvErDoThIs-2.png" "${NAME}"
|
||||||
|
mv "data/${NAME}.sta" .
|
||||||
|
|
||||||
|
# Remove data folder if we created one
|
||||||
|
if [[ "${HASDATA}" -eq "0" ]]; then
|
||||||
|
rm -rf data
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up temp PNG files
|
||||||
|
find . -maxdepth 1 -type f -name "${FILENAME}-DoNtEvErDoThIs-*.png" -exec rm -f {} \;
|
||||||
|
|
||||||
|
# Clean up JLSTATS
|
||||||
|
rm -f JLSTATS
|
||||||
|
|
||||||
|
# Back to our original directory
|
||||||
popd &> /dev/null
|
popd &> /dev/null
|
||||||
|
|
||||||
mv -f ${TARGET}/data/${NAME}.sta ${DIR}/${NAME}.sta
|
|
||||||
|
|
||||||
rm ${TEMPIMAGE}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue