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"
|
||||
|
||||
|
||||
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 ignored "-Wcast-align"
|
||||
|
||||
|
@ -47,85 +159,51 @@ Uint32 getPixel(SDL_Surface *surface, int x, int y) {
|
|||
#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[]) {
|
||||
|
||||
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");
|
||||
return 1;
|
||||
}
|
||||
|
||||
jlUtilStartup("STA Converter");
|
||||
jlUtilStartup("STA/STN Converter");
|
||||
|
||||
int imageFlags = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF;
|
||||
int imageResult = IMG_Init(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();
|
||||
}
|
||||
|
||||
SDL_Surface *image = IMG_Load(argv[1]);
|
||||
int colors = INT_MAX;
|
||||
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);
|
||||
convertColor(argv[1], argv[3], argc > 4);
|
||||
convertStencil(argv[2], argv[3]);
|
||||
|
||||
IMG_Quit();
|
||||
jlUtilShutdown();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
JOEY = /home/scott/joey
|
||||
CONFIG += SDL12
|
||||
#CONFIG += SDL2
|
||||
#CONFIG += SDL12
|
||||
CONFIG += SDL2
|
||||
|
||||
|
||||
TEMPLATE = app
|
||||
|
|
|
@ -33,7 +33,7 @@ segment "testapp";
|
|||
|
||||
|
||||
//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!
|
||||
|
@ -96,13 +96,11 @@ void lineTest(void) {
|
|||
printAt(font, 1, y++, "Drawing %s ", what);
|
||||
|
||||
jlDrawColorSet((byte)color);
|
||||
/*
|
||||
if (phase < 2) {
|
||||
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, x2, y2, 319-x2, 199-y2);
|
||||
} else {
|
||||
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, 319-x2, 199-y2, x2, y2);
|
||||
}
|
||||
*/
|
||||
ox = x2;
|
||||
oy = y2;
|
||||
op = phase;
|
||||
|
@ -148,13 +146,11 @@ void lineTest(void) {
|
|||
jlDisplayPresent();
|
||||
|
||||
jlDrawColorSet((byte)0);
|
||||
/*
|
||||
if (op < 2) {
|
||||
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, ox, oy, 319-ox, 199-oy);
|
||||
} else {
|
||||
asmDrawLine(_jlDrawTargetActual, _jlDrawColor, 319-ox, 199-oy, ox, oy);
|
||||
}
|
||||
*/
|
||||
|
||||
color = nextColor;
|
||||
nextColor++;
|
||||
|
@ -207,8 +203,8 @@ void blitTest(void) {
|
|||
int main(void) {
|
||||
jlUtilStartup("JoeyLib Test");
|
||||
|
||||
//lineTest();
|
||||
blitTest();
|
||||
lineTest();
|
||||
//blitTest();
|
||||
|
||||
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 \
|
||||
build-essential \
|
||||
bzip2 \
|
||||
ciopfs \
|
||||
clang \
|
||||
cmake \
|
||||
cpio \
|
||||
|
@ -934,6 +935,7 @@ function start() {
|
|||
gdb-mingw-w64 \
|
||||
genisoimage \
|
||||
gettext \
|
||||
gimp \
|
||||
git \
|
||||
gzip \
|
||||
hatari \
|
||||
|
@ -975,7 +977,6 @@ function start() {
|
|||
unzip \
|
||||
uuid-dev \
|
||||
wget \
|
||||
xcftools \
|
||||
xz-utils
|
||||
if [[ ! -z ${G_AUTOMATED} ]]; then
|
||||
DOINSTALL=1
|
||||
|
|
|
@ -1,24 +1,67 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ -z $1 ]; then
|
||||
echo $0 [name.xcf] {anything}
|
||||
# Did we get an image to convert?
|
||||
if [[ ! -f "$1" ]]; then
|
||||
echo Usage: $0 [gimpPic.xcf] {anythingToPreview}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NAME=$(basename $1 .xcf)
|
||||
DIR=$(dirname $1)
|
||||
TARGET=/tmp/xcf2sta
|
||||
TEMPIMAGE=${TARGET}/fixImageTemp.png
|
||||
# Find information about the image
|
||||
IMAGE=$(realpath "$1")
|
||||
FILENAME=$(basename "${IMAGE}")
|
||||
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
|
||||
xcf2png ${1} > ${TEMPIMAGE}
|
||||
# Switch to folder where the image exists
|
||||
pusd "${DIRNAME}" &> /dev/null
|
||||
|
||||
pushd ${TARGET} &> /dev/null
|
||||
${JOEY}/utils/imgconvert ${TEMPIMAGE} ${NAME} $2
|
||||
# Run our Script-Fu to convert each layer to a PNG
|
||||
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
|
||||
|
||||
mv -f ${TARGET}/data/${NAME}.sta ${DIR}/${NAME}.sta
|
||||
|
||||
rm ${TEMPIMAGE}
|
||||
|
|
Loading…
Add table
Reference in a new issue