From 3332b4333081f27ccc0572a80e0438ab10bb3ee5 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Wed, 4 Mar 2015 13:45:01 +0000 Subject: [PATCH] Save and load support for GIMP palettes (.GPL files) * Implemented by 00ai99 * Fixes https://code.google.com/p/grafx2/issues/detail?id=518 git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@2112 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- src/const.h | 1 + src/loadsave.c | 8 ++- src/miscfileformats.c | 161 ++++++++++++++++++++++++++++++++++++++++++ src/realpath.c | 1 + 4 files changed, 170 insertions(+), 1 deletion(-) diff --git a/src/const.h b/src/const.h index 8f3417e2..e317565f 100644 --- a/src/const.h +++ b/src/const.h @@ -131,6 +131,7 @@ enum FILE_FORMATS FORMAT_C64, FORMAT_KCF, FORMAT_PAL, + FORMAT_GPL, FORMAT_SCR, FORMAT_CM5, FORMAT_XPM, diff --git a/src/loadsave.c b/src/loadsave.c index 9043ea52..922ba04e 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -103,6 +103,11 @@ void Test_PAL(T_IO_Context *); void Load_PAL(T_IO_Context *); void Save_PAL(T_IO_Context *); +// -- GPL ------------------------------------------------------------------- +void Test_GPL(T_IO_Context *); +void Load_GPL(T_IO_Context *); +void Save_GPL(T_IO_Context *); + // -- PI1 ------------------------------------------------------------------- void Test_PI1(T_IO_Context *); void Load_PI1(T_IO_Context *); @@ -148,7 +153,7 @@ void Load_SDL_Image(T_IO_Context *); // ENUM Name TestFunc LoadFunc SaveFunc PalOnly Comment Layers Ext Exts T_Format File_formats[] = { - {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;iff;lbm;ilbm;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;koala;fli;bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;cm5"}, + {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;iff;lbm;ilbm;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;gpl;c64;koa;koala;fli;bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;cm5"}, {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"}, {FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 0, 1, 1, "gif", "gif"}, #ifndef __no_pnglib__ @@ -167,6 +172,7 @@ T_Format File_formats[] = { {FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 0, 0, 0, "neo", "neo"}, {FORMAT_KCF, " kcf", Test_KCF, Load_KCF, Save_KCF, 1, 0, 0, "kcf", "kcf"}, {FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 1, 0, 0, "pal", "pal"}, + {FORMAT_GPL, " gpl", Test_GPL, Load_GPL, Save_GPL, 1, 0, 0, "gpl", "gpl"}, {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, 0, "c64", "c64;koa;koala;fli;bml;cdu;prg"}, {FORMAT_SCR, " cpc", NULL, NULL, Save_SCR, 0, 0, 0, "cpc", "cpc;scr"}, {FORMAT_CM5, " cm5", Test_CM5, Load_CM5, Save_CM5, 0, 0, 1, "cm5", "cm5"}, diff --git a/src/miscfileformats.c b/src/miscfileformats.c index b0cf3616..5a8f94f8 100644 --- a/src/miscfileformats.c +++ b/src/miscfileformats.c @@ -90,6 +90,167 @@ void Test_PAL(T_IO_Context * context) } } +void Test_GPL(T_IO_Context * context) +{ + FILE *file; + char filename[MAX_PATH_CHARACTERS]; + long file_size; + + Get_full_filename(filename, context->File_name, context->File_directory); + + File_error = 1; + + if ((file = fopen(filename, "rb"))) + { + file_size = File_length_file(file); + if (file_size > 33) { + // minimum header length == 33 + // "GIMP Palette" == 12 + fread(filename, 1, 12, file); + if (strncmp(filename,"GIMP Palette",12) == 0) + File_error = 0; + } + } + fclose(file); +} + +// skip the padding before a space-padded field. + +static int skip_padding(FILE *file, int max_chars) +{ + char buffer[1]; + int chars_read = 0; + int latest_chars_read = 0; + size_t tmp; + buffer[0] = ' '; + while (buffer[0] == ' '){ + latest_chars_read = fread(buffer, 1, 1, file); + if ((latest_chars_read != 1) || (chars_read == max_chars)) + return chars_read; // eof + chars_read += latest_chars_read; + } + + if (chars_read > 0){ + tmp = ftell(file); +// printf ("rewinding to %d", tmp - 1); + fseek(file, tmp - 1, SEEK_SET); + } + return chars_read; +} + +// -- Load file with format GPL ----------------------------------------- +void Load_GPL(T_IO_Context * context) +{ + FILE *file; + char filename[MAX_PATH_CHARACTERS]; // full filename + long file_size; + long pos; + + Get_full_filename(filename, context->File_name, context->File_directory); + File_error=0; + + // Open file + if ((file=fopen(filename, "rb"))) + { + fread(filename, 1, 13, file); + file_size = File_length_file(file); + if (strncmp(filename,"GIMP Palette\n",13) == 0) + { + int i, j, r, g, b, columns, chars_read; + fscanf(file, "Name: %s\n", filename); + printf("DBG: Escaped nominal destruction ~%s~\n", filename); // y + fscanf(file, "Columns: %d\n", &columns); + // TODO: set grafx2 columns setting to match. + printf("DBG: Escaped architectural destruction %d\n", columns); // y + // # + fread(filename,1, 2, file); + filename[2] = 0; + printf("DBG: Escaped grammatical destruction ~%s~\n", filename); + + for (i = 0; i < 256; i++) + { + + pos = ftell(file); + skip_padding(file, 32); + fscanf(file, "%d", &r); + skip_padding(file, 32); + fscanf(file, "%d", &g); + skip_padding(file, 32); + fscanf(file, "%d\t", &b); + filename[0] = 0; + j = 0; + do { + + chars_read = fscanf(file, "%s", filename+j); + if (chars_read > 0){ + j += chars_read; + // space or newline follows. + fread(filename+j, 1, 1, file); + } + else{ + filename[j] = '\n'; + } + } while (filename[j] != '\n'); + filename[j] = 0; + if (ftell(file) == pos) + break; // no more colors. + + // TODO: analyze color names to build shade table + + printf("DBG: %d: %s\n", i, filename); + context->Palette[i].R = r; + context->Palette[i].G = g; + context->Palette[i].B = b; + } + } else + File_error = 2; + + // close the file + fclose(file); + } + else + // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur + File_error=1; +} + + +void +Save_GPL (T_IO_Context * context) +{ + FILE *file; + char filename[MAX_PATH_CHARACTERS]; // full filename + + Get_full_filename(filename, context->File_name, context->File_directory); + + File_error=0; + + // Open output file + if ((file=fopen(filename,"w"))){ + int i; + fprintf (file, "GIMP Palette\n"); + fprintf (file, "Name: %s\n", context->File_name); + // TODO: use actual columns value + fprintf (file, "Columns: %d\n#\n", 16); + + for (i = 0; i < 256 && File_error==0; i++) + { + // TODO: build names from shade table data + if (fprintf(file,"%d %d %d\tUntitled\n",context->Palette[i].R, context->Palette[i].G, context->Palette[i].B) <= 0) + File_error=1; + } + fclose(file); + + if (File_error) + remove(filename); + } + else + { + // unable to open output file, nothing saved. + File_error=1; + } +} + + // -- Lire un fichier au format PAL ----------------------------------------- void Load_PAL(T_IO_Context * context) diff --git a/src/realpath.c b/src/realpath.c index a3333fb7..88c6e690 100644 --- a/src/realpath.c +++ b/src/realpath.c @@ -118,6 +118,7 @@ return _fullpath(resolved_path,_path,260); } #else +#include // Use the stdlib function. char *Realpath(const char *_path, char *resolved_path) {