ansilove

ANSI and ASCII art to PNG converter in C
Log | Files | Refs | README | LICENSE

commit 9acee3ef2c66ac49adb4d0a5b4e1693480a41cd9
parent c4076d28ca0073bcb7507252ce54c6dbb8c162e7
Author: ByteProject <stefan.vogt@byteproject.net>
Date:   Sun,  9 Sep 2012 00:45:55 +0200

Retina image output implementation

Diffstat:
Mansilove/ansilove.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mansilove/ansilove.h | 14+++++++-------
Mansilove/main.c | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 222 insertions(+), 38 deletions(-)

diff --git a/ansilove/ansilove.c b/ansilove/ansilove.c @@ -43,7 +43,7 @@ void alDrawChar(gdImagePtr im, const unsigned char *font_data, int32_t int_bits, } // ANSi -void alAnsiLoader(char *input, char output[], char font[], char bits[], char icecolors[], char *fext) +void alAnsiLoader(char *input, char output[], char retinaout[], char font[], char bits[], char icecolors[], char *fext, bool createRetinaRep) { const unsigned char *font_data; @@ -987,6 +987,26 @@ void alAnsiLoader(char *input, char output[], char font[], char bits[], char ice gdImagePng(im_ANSi, file_Out); fclose(file_Out); + // in case Retina image output is wanted + if (createRetinaRep == true) + { + gdImagePtr im_RetinaANSi; + + // make the Retina image @2x as large as im_ANSi + im_RetinaANSi = gdImageCreate(im_ANSi->sx * 2, im_ANSi->sy * 2); + + gdImageCopyResized(im_RetinaANSi, im_ANSi, 0, 0, 0, 0, + im_RetinaANSi->sx, im_RetinaANSi->sy, + im_ANSi->sx, im_ANSi->sy); + + // create retina output image + FILE *file_RetinaOut = fopen(retinaout, "wb"); + gdImagePng(im_RetinaANSi, file_RetinaOut); + fclose(file_RetinaOut); + + gdImageDestroy(im_RetinaANSi); + } + // free memory free(ansi_buffer); @@ -996,7 +1016,7 @@ void alAnsiLoader(char *input, char output[], char font[], char bits[], char ice } // PCB -void alPcBoardLoader(char *input, char output[], char font[], char bits[]) +void alPcBoardLoader(char *input, char output[], char retinaout[], char font[], char bits[], bool createRetinaRep) { // some type declarations int32_t font_size_x; @@ -1364,12 +1384,32 @@ void alPcBoardLoader(char *input, char output[], char font[], char bits[]) gdImagePng(im_PCB, file_Out); fclose(file_Out); + // in case Retina image output is wanted + if (createRetinaRep == true) + { + gdImagePtr im_RetinaANSi; + + // make the Retina image @2x as large as im_PCB + im_RetinaANSi = gdImageCreate(im_PCB->sx * 2, im_PCB->sy * 2); + + gdImageCopyResized(im_RetinaANSi, im_PCB, 0, 0, 0, 0, + im_RetinaANSi->sx, im_RetinaANSi->sy, + im_PCB->sx, im_PCB->sy); + + // create retina output image + FILE *file_RetinaOut = fopen(retinaout, "wb"); + gdImagePng(im_RetinaANSi, file_RetinaOut); + fclose(file_RetinaOut); + + gdImageDestroy(im_RetinaANSi); + } + // free memory gdImageDestroy(im_PCB); } // BINARY -void alBinaryLoader(char *input, char output[], char columns[], char font[], char bits[], char icecolors[]) +void alBinaryLoader(char *input, char output[], char retinaout[], char columns[], char font[], char bits[], char icecolors[], bool createRetinaRep) { // some type declarations int32_t font_size_x; @@ -1618,13 +1658,33 @@ void alBinaryLoader(char *input, char output[], char columns[], char font[], cha FILE *file_Out = fopen(output, "wb"); gdImagePng(im_Binary, file_Out); fclose(file_Out); + + // in case Retina image output is wanted + if (createRetinaRep == true) + { + gdImagePtr im_RetinaANSi; + + // make the Retina image @2x as large as im_Binary + im_RetinaANSi = gdImageCreate(im_Binary->sx * 2, im_Binary->sy * 2); + + gdImageCopyResized(im_RetinaANSi, im_Binary, 0, 0, 0, 0, + im_RetinaANSi->sx, im_RetinaANSi->sy, + im_Binary->sx, im_Binary->sy); + + // create retina output image + FILE *file_RetinaOut = fopen(retinaout, "wb"); + gdImagePng(im_RetinaANSi, file_RetinaOut); + fclose(file_RetinaOut); + + gdImageDestroy(im_RetinaANSi); + } // free memory gdImageDestroy(im_Binary); } // ADF -void alArtworxLoader(char *input, char output[], char bits[]) +void alArtworxLoader(char *input, char output[], char retinaout[], char bits[], bool createRetinaRep) { const unsigned char *font_data; unsigned char *font_data_adf; @@ -1727,12 +1787,32 @@ void alArtworxLoader(char *input, char output[], char bits[]) gdImagePng(im_ADF, file_Out); fclose(file_Out); + // in case Retina image output is wanted + if (createRetinaRep == true) + { + gdImagePtr im_RetinaANSi; + + // make the Retina image @2x as large as im_ADF + im_RetinaANSi = gdImageCreate(im_ADF->sx * 2, im_ADF->sy * 2); + + gdImageCopyResized(im_RetinaANSi, im_ADF, 0, 0, 0, 0, + im_RetinaANSi->sx, im_RetinaANSi->sy, + im_ADF->sx, im_ADF->sy); + + // create retina output image + FILE *file_RetinaOut = fopen(retinaout, "wb"); + gdImagePng(im_RetinaANSi, file_RetinaOut); + fclose(file_RetinaOut); + + gdImageDestroy(im_RetinaANSi); + } + // nuke garbage gdImageDestroy(im_ADF); } // IDF -void alIcedrawLoader(char *input, char output[], char bits[], bool fileHasSAUCE) +void alIcedrawLoader(char *input, char output[], char retinaout[], char bits[], bool fileHasSAUCE, bool createRetinaRep) { const unsigned char *font_data; unsigned char *font_data_idf; @@ -1900,12 +1980,32 @@ void alIcedrawLoader(char *input, char output[], char bits[], bool fileHasSAUCE) gdImagePng(im_IDF, file_Out); fclose(file_Out); + // in case Retina image output is wanted + if (createRetinaRep == true) + { + gdImagePtr im_RetinaANSi; + + // make the Retina image @2x as large as im_IDF + im_RetinaANSi = gdImageCreate(im_IDF->sx * 2, im_IDF->sy * 2); + + gdImageCopyResized(im_RetinaANSi, im_IDF, 0, 0, 0, 0, + im_RetinaANSi->sx, im_RetinaANSi->sy, + im_IDF->sx, im_IDF->sy); + + // create retina output image + FILE *file_RetinaOut = fopen(retinaout, "wb"); + gdImagePng(im_RetinaANSi, file_RetinaOut); + fclose(file_RetinaOut); + + gdImageDestroy(im_RetinaANSi); + } + // nuke garbage gdImageDestroy(im_IDF); } // TUNDRA -void alTundraLoader(char *input, char output[], char font[], char bits[]) +void alTundraLoader(char *input, char output[], char retinaout[], char font[], char bits[], bool createRetinaRep) { int32_t columns = 80; int32_t font_size_x; @@ -2121,12 +2221,32 @@ void alTundraLoader(char *input, char output[], char font[], char bits[]) gdImagePng(im_Tundra, file_Out); fclose(file_Out); + // in case Retina image output is wanted + if (createRetinaRep == true) + { + gdImagePtr im_RetinaANSi; + + // make the Retina image @2x as large as im_Tundra + im_RetinaANSi = gdImageCreate(im_Tundra->sx * 2, im_Tundra->sy * 2); + + gdImageCopyResized(im_RetinaANSi, im_Tundra, 0, 0, 0, 0, + im_RetinaANSi->sx, im_RetinaANSi->sy, + im_Tundra->sx, im_Tundra->sy); + + // create retina output image + FILE *file_RetinaOut = fopen(retinaout, "wb"); + gdImagePng(im_RetinaANSi, file_RetinaOut); + fclose(file_RetinaOut); + + gdImageDestroy(im_RetinaANSi); + } + // free memory gdImageDestroy(im_Tundra); } // XBIN -void alXbinLoader(char *input, char output[], char bits[]) +void alXbinLoader(char *input, char output[], char retinaout[], char bits[], bool createRetinaRep) { const unsigned char *font_data; unsigned char *font_data_xbin; @@ -2333,6 +2453,26 @@ void alXbinLoader(char *input, char output[], char bits[]) gdImagePng(im_XBIN, file_Out); fclose(file_Out); + // in case Retina image output is wanted + if (createRetinaRep == true) + { + gdImagePtr im_RetinaANSi; + + // make the Retina image @2x as large as im_XBIN + im_RetinaANSi = gdImageCreate(im_XBIN->sx * 2, im_XBIN->sy * 2); + + gdImageCopyResized(im_RetinaANSi, im_XBIN, 0, 0, 0, 0, + im_RetinaANSi->sx, im_RetinaANSi->sy, + im_XBIN->sx, im_XBIN->sy); + + // create retina output image + FILE *file_RetinaOut = fopen(retinaout, "wb"); + gdImagePng(im_RetinaANSi, file_RetinaOut); + fclose(file_RetinaOut); + + gdImageDestroy(im_RetinaANSi); + } + // nuke garbage gdImageDestroy(im_XBIN); } diff --git a/ansilove/ansilove.h b/ansilove/ansilove.h @@ -44,13 +44,13 @@ void alDrawChar(gdImagePtr im, const unsigned char *font_data, int32_t int_bits, int32_t font_size_x, int32_t font_size_y, int32_t position_x, int32_t position_y, int32_t color_background, int32_t color_foreground, unsigned char character); -void alAnsiLoader(char *input, char output[], char font[], char bits[], char icecolors[], char *fext); -void alPcBoardLoader(char *input, char output[], char font[], char bits[]); -void alBinaryLoader(char *input, char output[], char columns[], char font[], char bits[], char icecolors[]); -void alArtworxLoader(char *input, char output[], char bits[]); -void alIcedrawLoader(char *input, char output[], char bits[], bool fileHasSAUCE); -void alTundraLoader(char *input, char output[], char font[], char bits[]); -void alXbinLoader(char *input, char output[], char bits[]); +void alAnsiLoader(char *input, char output[], char retinaout[], char font[], char bits[], char icecolors[], char *fext, bool createRetinaRep); +void alPcBoardLoader(char *input, char output[], char retinaout[], char font[], char bits[], bool createRetinaRep); +void alBinaryLoader(char *input, char output[], char retinaout[], char columns[], char font[], char bits[], char icecolors[], bool createRetinaRep); +void alArtworxLoader(char *input, char output[], char retinaout[], char bits[], bool createRetinaRep); +void alIcedrawLoader(char *input, char output[], char retinaout[], char bits[], bool fileHasSAUCE, bool createRetinaRep); +void alTundraLoader(char *input, char output[], char retinaout[], char font[], char bits[], bool createRetinaRep); +void alXbinLoader(char *input, char output[], char retinaout[], char bits[], bool createRetinaRep); // helper functions char *str_replace(const char *string, const char *substr, const char *replacement); diff --git a/ansilove/main.c b/ansilove/main.c @@ -52,11 +52,17 @@ void showHelp(void) void listExamples(void) { printf("\nEXAMPLES:\n"); - printf(" ansilove file.ans -i (output identical input with .png suffix, no operands)\n" - " ansilove file.ans -o foo/out.png (custom path for output, no operands)\n" + printf(" ansilove file.ans -i (output path/name identical to input, no operands)\n" + " ansilove file.ans -ir (same as -i, adds Retina @2x output file)\n" + " ansilove file.ans -o dir/file (custom path/name for output, no operands)\n" + " ansilove file.ans -or dir/file (same as -o, adds Retina @2x output file)\n" " ansilove file.bin -s (just display SAUCE record, don't generate output)\n" " ansilove file.bin -i terminus 8 1 202 (set font, bits, icecolors, columns)\n" - " ansilove file.ans -o out.png terminus 8 1 (custom font, bits, icecolors)\n\n"); + " ansilove file.ans -o dir/file terminus 8 1 (custom font, bits, icecolors)\n" + " ansilove file.ans -or dir/file 80x25 8 1 (DOS font, bits, iCE, Retina)\n\n" + "HINT:\n" + " Don't add .png suffix when specifying a custom path/name for output as it\n" + " will be added automatically.\n\n"); } void versionInfo(void) @@ -74,17 +80,21 @@ void versionInfo(void) void synopsis(void) { printf("\nSYNOPSIS:\n" - " ansilove file -i [operands]\n" - " ansilove file -o file.png [operands]\n" - " ansilove file -s\n" + " ansilove input -i [operands]\n" + " ansilove input -ir [operands]\n" + " ansilove input -o output [operands]\n" + " ansilove input -or output [operands]\n" + " ansilove input -s\n" " ansilove -vhe\n\n" "OPTIONS:\n" - " -i output identical to input with .png suffix added\n" - " -o specify custom file name / path for output\n" - " -s display SAUCE record without generating output\n" - " -v version information, equivalent to --version\n" - " -h show help, equivalent to --help\n" - " -e print a list of examples\n\n" + " -i output identical to input with .png suffix added\n" + " -ir same as -i, creates additional Retina @2x output file\n" + " -o specify custom file name/path for output\n" + " -or same as -o, creates additional Retina @2x output file\n" + " -s display SAUCE record without generating output\n" + " -v version information, equivalent to --version\n" + " -h show help, equivalent to --help\n" + " -e print a list of examples\n\n" "OPERANDS:\n" " font bits icecolors columns\n\n"); } @@ -98,6 +108,9 @@ int main(int argc, char *argv[]) bool justDisplaySAUCE = false; bool fileHasSAUCE = false; + // retina output bool type + bool createRetinaRep = false; + // analyze options and do what has to be done bool outputIdentical = false; bool fileIsBinary = false; @@ -121,14 +134,20 @@ int main(int argc, char *argv[]) listExamples(); return EXIT_SUCCESS; } - if ((argv[2] && (strcmp(argv[2], "-s") == 0)) || - (argv[2] && (strcmp(argv[2], "-i") == 0)) || - (argv[2] && (strcmp(argv[2], "-o") == 0))) + if ((argv[2] && (strcmp(argv[2], "-s") == 0)) || + (argv[2] && (strcmp(argv[2], "-i") == 0)) || + (argv[2] && (strcmp(argv[2], "-ir") == 0)) || + (argv[2] && (strcmp(argv[2], "-o") == 0)) || + (argv[2] && (strcmp(argv[2], "-or") == 0))) { if (strcmp(argv[2], "-s") == 0) { justDisplaySAUCE = true; } + if (strcmp(argv[2], "-ir") == 0 || strcmp(argv[2], "-or") == 0) { + createRetinaRep = true; + } + // let's check the file for a valid SAUCE record sauce *record = sauceReadFileName(argv[1]); @@ -150,6 +169,7 @@ int main(int argc, char *argv[]) // declaration of types we pass to ansilove.c char *input = argv[1]; char output[1000] = { 0 }; + char retinaout[1000] = { 0 }; char columns[1000] = { 0 }; char font[1000] = { 0 }; char bits[1000] = { 0 }; @@ -172,16 +192,31 @@ int main(int argc, char *argv[]) fext = "none"; } - // in case we got arguments for input and the '-i' flag is set + // in case we got arguments for input and the '-i' or '-ir' flag is set if (strcmp(argv[2], "-i") == 0) { // append .png suffix to file name sprintf(output, "%s.png", input); + sprintf(retinaout, "placeholder_%s.png", input); + outputIdentical = true; + } + + if (strcmp(argv[2], "-ir") == 0) { + // again, append .png and also add @2x for retina output + sprintf(output, "%s.png", input); + sprintf(retinaout, "%s@2x.png", input); outputIdentical = true; } if ((strcmp(argv[2], "-o") == 0) && argv[3]) { // so the user provided an alternate path / file name - sprintf(output, "%s", argv[3]); + sprintf(output, "%s.png", argv[3]); + sprintf(retinaout, "placeholder_%s.png", input); + } + + if ((strcmp(argv[2], "-or") == 0) && argv[3]) { + // alternate path and retina? damn you! even more work. + sprintf(output, "%s.png", argv[3]); + sprintf(retinaout, "%s@2x.png", argv[3]); } if ((strcmp(argv[2], "-o") == 0) && !argv[3]) { @@ -190,6 +225,12 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } + if ((strcmp(argv[2], "-or") == 0) && !argv[3]) { + // y u no enter output file argument? + printf("\nOption -or is invalid without output file argument.\n\n"); + return EXIT_FAILURE; + } + // check for operands and apply them based on the file extension if ((strcmp(fext, ".bin") == 0) && outputIdentical == true) { @@ -310,39 +351,42 @@ int main(int argc, char *argv[]) // create the output file by invoking the appropiate function if (strcmp(fext, ".pcb") == 0) { // params: input, output, font, bits, icecolors - alPcBoardLoader(input, output, font, bits); + alPcBoardLoader(input, output, retinaout, font, bits, createRetinaRep); fileIsPCBoard = true; } else if (strcmp(fext, ".bin") == 0) { // params: input, output, columns, font, bits, icecolors - alBinaryLoader(input, output, columns, font, bits, icecolors); + alBinaryLoader(input, output, retinaout, columns, font, bits, icecolors, createRetinaRep); fileIsBinary = true; } else if (strcmp(fext, ".adf") == 0) { // params: input, output, bits - alArtworxLoader(input, output, bits); + alArtworxLoader(input, output, retinaout, bits, createRetinaRep); } else if (strcmp(fext, ".idf") == 0) { // params: input, output, bits - alIcedrawLoader(input, output, bits, fileHasSAUCE); + alIcedrawLoader(input, output, retinaout, bits, fileHasSAUCE, createRetinaRep); } else if (strcmp(fext, ".tnd") == 0) { - alTundraLoader(input, output, font, bits); + alTundraLoader(input, output, retinaout, font, bits, createRetinaRep); fileIsTundra = true; } else if (strcmp(fext, ".xb") == 0) { // params: input, output, bits - alXbinLoader(input, output, bits); + alXbinLoader(input, output, retinaout, bits, createRetinaRep); } else { // params: input, output, font, bits, icecolors, fext - alAnsiLoader(input, output, font, bits, icecolors, fext); + alAnsiLoader(input, output, retinaout, font, bits, icecolors, fext, createRetinaRep); fileIsANSi = true; } // gather information and report to the command line printf("\nInput File: %s\n", input); printf("Output File: %s\n", output); + if (createRetinaRep == true) { + printf("Retina Output File: %s\n", retinaout); + } if (fileIsANSi == true || fileIsBinary == true || fileIsPCBoard == true || fileIsTundra == true) { printf("Font: %s\n", font);