diff options
Diffstat (limited to 'tools/gbagfx/jasc_pal.c')
-rw-r--r-- | tools/gbagfx/jasc_pal.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/tools/gbagfx/jasc_pal.c b/tools/gbagfx/jasc_pal.c new file mode 100644 index 0000000..e5ba9c3 --- /dev/null +++ b/tools/gbagfx/jasc_pal.c @@ -0,0 +1,172 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <string.h> +#include "global.h" +#include "gfx.h" +#include "util.h" + +// Read/write Paint Shop Pro palette files. + +// Format of a Paint Shop Pro palette file, line by line: +// "JASC-PAL\r\n" (signature) +// "0100\r\n" (version; seems to always be "0100") +// "<NUMBER_OF_COLORS>\r\n" (number of colors in decimal) +// +// <NUMBER_OF_COLORS> times: +// "<RED> <GREEN> <BLUE>\r\n" (color entry) +// +// Each color component is a decimal number from 0 to 255. +// Examples: +// Black - "0 0 0\r\n" +// Blue - "0 0 255\r\n" +// Brown - "150 75 0\r\n" + +#define MAX_LINE_LENGTH 11 + +void ReadJascPaletteLine(FILE *fp, char *line) +{ + int c; + int length = 0; + + for (;;) + { + c = fgetc(fp); + + if (c == '\r') + { + c = fgetc(fp); + + if (c != '\n') + FATAL_ERROR("CR line endings aren't supported.\n"); + + line[length] = 0; + + return; + } + + if (c == '\n') + FATAL_ERROR("LF line endings aren't supported.\n"); + + if (c == EOF) + FATAL_ERROR("Unexpected EOF. No CRLF at end of file.\n"); + + if (c == 0) + FATAL_ERROR("NUL character in file.\n"); + + if (length == MAX_LINE_LENGTH) + { + line[length] = 0; + FATAL_ERROR("The line \"%s\" is too long.\n", line); + } + + line[length++] = c; + } +} + +void ReadJascPalette(char *path, struct Palette *palette) +{ + char line[MAX_LINE_LENGTH + 1]; + + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open JASC-PAL file \"%s\" for reading.\n", path); + + ReadJascPaletteLine(fp, line); + + if (strcmp(line, "JASC-PAL") != 0) + FATAL_ERROR("Invalid JASC-PAL signature.\n"); + + ReadJascPaletteLine(fp, line); + + if (strcmp(line, "0100") != 0) + FATAL_ERROR("Unsuported JASC-PAL version.\n"); + + ReadJascPaletteLine(fp, line); + + if (!ParseNumber(line, NULL, 10, &palette->numColors)) + FATAL_ERROR("Failed to parse number of colors.\n"); + + if (palette->numColors < 1 || palette->numColors > 256) + FATAL_ERROR("%d is an invalid number of colors. The number of colors must be in the range [1, 256].\n", palette->numColors); + + for (int i = 0; i < palette->numColors; i++) + { + ReadJascPaletteLine(fp, line); + + char *s = line; + char *end; + + int red; + int green; + int blue; + + if (!ParseNumber(s, &end, 10, &red)) + FATAL_ERROR("Failed to parse red color component.\n"); + + s = end; + + if (*s != ' ') + FATAL_ERROR("Expected a space after red color component.\n"); + + s++; + + if (*s < '0' || *s > '9') + FATAL_ERROR("Expected only a space between red and green color components.\n"); + + if (!ParseNumber(s, &end, 10, &green)) + FATAL_ERROR("Failed to parse green color component.\n"); + + s = end; + + if (*s != ' ') + FATAL_ERROR("Expected a space after green color component.\n"); + + s++; + + if (*s < '0' || *s > '9') + FATAL_ERROR("Expected only a space between green and blue color components.\n"); + + if (!ParseNumber(s, &end, 10, &blue)) + FATAL_ERROR("Failed to parse blue color component.\n"); + + if (*end != 0) + FATAL_ERROR("Garbage after blue color component.\n"); + + if (red < 0 || red > 255) + FATAL_ERROR("Red color component (%d) is outside the range [0, 255].\n", red); + + if (green < 0 || green > 255) + FATAL_ERROR("Green color component (%d) is outside the range [0, 255].\n", green); + + if (blue < 0 || blue > 255) + FATAL_ERROR("Blue color component (%d) is outside the range [0, 255].\n", blue); + + palette->colors[i].red = red; + palette->colors[i].green = green; + palette->colors[i].blue = blue; + } + + if (fgetc(fp) != EOF) + FATAL_ERROR("Garbage after color data.\n"); + + fclose(fp); +} + +void WriteJascPalette(char *path, struct Palette *palette) +{ + FILE *fp = fopen(path, "wb"); + + fputs("JASC-PAL\r\n", fp); + fputs("0100\r\n", fp); + fprintf(fp, "%d\r\n", palette->numColors); + + for (int i = 0; i < palette->numColors; i++) + { + struct Color *color = &palette->colors[i]; + fprintf(fp, "%d %d %d\r\n", color->red, color->green, color->blue); + } + + fclose(fp); +} |