/* Global flags */
static int verbose = 0;
static char *outname = "out";
+static int usepalette = 1;
static const char *progname;
#define errmsg(fmt, ...) (\
goto err;
}
- png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_PALETTE,
+
+ png_set_IHDR(png, info, width, height, 8,
+ usepalette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
- png_set_PLTE(png, info, (png_colorp)palette, 256);
+
+ if (usepalette)
+ png_set_PLTE(png, info, (png_colorp)palette, 256);
png_set_rows(png, info, framedata);
png_init_io(png, of);
return -1;
}
-int decode(LBX_IMG *img, FILE *palf, char **argv)
+static int loadpalette(LBX_IMG *img, struct lbx_imginfo *info,
+ FILE *palf, struct lbx_colour palette[static 256])
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ palette[i] = (struct lbx_colour){0xff, 0x00, 0xff};
+
+ if (palf) {
+ if (lbximg_loadpalette(palf, palette) == -1) {
+ errmsg("error reading palette: %s\n", lbx_strerror());
+ return -1;
+ }
+ } else if (!info->haspalette) {
+ errmsg("no palette available.\n", 0);
+ return -1;
+ }
+
+ if (lbximg_getpalette(img, palette) == -1) {
+ errmsg("error reading embedded palette: %s\n", lbx_strerror());
+ return -1;
+ }
+
+ return 0;
+}
+
+int decode(LBX_IMG *img, FILE *palf, FILE *override, char **argv)
{
unsigned char *framebits;
struct lbx_colour palette[256];
framebits = malloc(info.nframes / CHAR_BIT + 1);
if (!framebits) {
- return -1;
+ return EXIT_FAILURE;
}
/* Figure out what images we're extracting. */
}
}
- /* Read image palette */
- if (palf) {
- if (lbximg_loadpalette(palf, palette) == -1) {
- errmsg("error reading palette: %s\n", lbx_strerror());
+ if (usepalette && loadpalette(img, &info, palf, palette) == -1) {
+ goto err;
+ }
+
+ if (override) {
+ LBX_IMG *overimg = lbximg_fopen(override);
+ struct lbx_imginfo info;
+
+ if (!overimg) {
+ errmsg("failed to open override image: %s\n",
+ lbx_strerror());
goto err;
}
- } else {
- fprintf(stderr, "warning: no palette specified; "
- "decoded images will likely be very pink.\n");
+ lbximg_getinfo(overimg, &info);
- for (i = 0; i < 256; i++)
- palette[i] = (struct lbx_colour){0xff, 0x00, 0xff};
- }
+ if (!info.haspalette) {
+ errmsg("override image has no palette.\n", 0);
+ lbximg_close(overimg);
+ goto err;
+ }
- if (lbximg_getpalette(img, palette) == -1) {
- errmsg("error reading palette override: %s\n", lbx_strerror());
- goto err;
+ if (lbximg_getpalette(overimg, palette) == -1) {
+ errmsg("error reading override palette: %s\n",
+ lbx_strerror());
+ lbximg_close(overimg);
+ goto err;
+ }
+
+ lbximg_close(overimg);
}
/* Extract the images, in order. */
int main(int argc, char **argv)
{
int mode = MODE_NONE;
- FILE *inf = stdin, *palf = NULL;
+ FILE *inf = stdin, *palf = NULL, *overf = NULL;
const char *name = "stdin";
LBX_IMG *img;
int opt;
- static const char *sopts = "idvf:p:";
+ static const char *sopts = "idvf:p:O:";
static const struct option lopts[] = {
- { "info", 0, NULL, 'i' },
- { "decode", 0, NULL, 'd' },
- { "verbose", 0, NULL, 'v' },
- { "file", 1, NULL, 'f' },
- { "palette", 1, NULL, 'p' },
+ { "info", 0, NULL, 'i' },
+ { "decode", 0, NULL, 'd' },
+ { "verbose", 0, NULL, 'v' },
+ { "file", 1, NULL, 'f' },
+ { "palette", 1, NULL, 'p' },
+ { "override", 1, NULL, 'p' },
+
+ { "nopalette", 0, &usepalette, 0 },
{ 0 }
};
}
break;
- default:
+ case 'O':
+ overf = fopen(optarg, "rb");
+ if (!overf) {
+ errmsg("failed to open %s: %m\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ case '?':
+ case ':':
return EXIT_FAILURE;
}
}
struct lbx_imginfo info;
lbximg_getinfo(img, &info);
- printf("%s is %ux%u LBX image, %u frames\n",
- name, info.width, info.height, info.nframes);
+ printf("%s is %ux%u LBX image, %u frame(s)%s%s\n",
+ name, info.width, info.height, info.nframes,
+ info.haspalette ? ", embedded palette" : "",
+ info.looping ? ", loops" : "");
}
switch (mode) {
case MODE_DECODE:
- if (decode(img, palf, &argv[optind])) {
+ if (decode(img, palf, overf, &argv[optind])) {
lbximg_close(img);
return EXIT_FAILURE;
}