diff --git a/imgconvert/main.c b/imgconvert/main.c index e9eab35..0a37ba6 100644 --- a/imgconvert/main.c +++ b/imgconvert/main.c @@ -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; xpalette[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; yh; y++) { + for (int x=0; xw; 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; yh; y++) { + for (int x=0; xw; 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; xpalette[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; yh; y++) { - for (int x=0; xw; 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(); diff --git a/joeylib/joeylib.pro b/joeylib/joeylib.pro index 947a018..a79274a 100644 --- a/joeylib/joeylib.pro +++ b/joeylib/joeylib.pro @@ -1,6 +1,6 @@ JOEY = /home/scott/joey -CONFIG += SDL12 -#CONFIG += SDL2 +#CONFIG += SDL12 +CONFIG += SDL2 TEMPLATE = app diff --git a/joeylib/src/test.c b/joeylib/src/test.c index 491de1d..b625ba1 100644 --- a/joeylib/src/test.c +++ b/joeylib/src/test.c @@ -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(); } diff --git a/scripts/exportXCFLayers.scm b/scripts/exportXCFLayers.scm new file mode 100644 index 0000000..58644c9 --- /dev/null +++ b/scripts/exportXCFLayers.scm @@ -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" "/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)) + ) + ) + ) +) diff --git a/scripts/installer.sh b/scripts/installer.sh index ff2c943..079fd64 100755 --- a/scripts/installer.sh +++ b/scripts/installer.sh @@ -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 diff --git a/scripts/xcf2sta.sh b/scripts/xcf2sta.sh index 6a66054..42411b2 100755 --- a/scripts/xcf2sta.sh +++ b/scripts/xcf2sta.sh @@ -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}