summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2022-01-23 16:03:22 -0500
committerJune McEnroe <june@causal.agency>2022-01-23 16:03:22 -0500
commitdc94d6a4aa630c46b2e28701a15a2bd9b366fd02 (patch)
treef5433e412ddf04294a37058145c562ec772fbf41
parentAdd ico2png converter (diff)
downloadwep-dc94d6a4aa630c46b2e28701a15a2bd9b366fd02.tar.gz
wep-dc94d6a4aa630c46b2e28701a15a2bd9b366fd02.zip
Account for ICOs lying about bpp, drop BITMAPCOREHEADER
-rw-r--r--tools/ico2png.c45
1 files changed, 20 insertions, 25 deletions
diff --git a/tools/ico2png.c b/tools/ico2png.c
index 71644b6..6e79ed7 100644
--- a/tools/ico2png.c
+++ b/tools/ico2png.c
@@ -128,7 +128,7 @@ int main(int argc, char *argv[]) {
 		icon.colors = SDL_ReadU8(ico);
 		SDL_ReadU8(ico); // reserved
 		icon.planes = SDL_ReadLE16(ico);
-		icon.bpp = SDL_ReadLE16(ico);
+		icon.bpp = SDL_ReadLE16(ico); // some ICOs lie about this...
 		icon.length = SDL_ReadLE32(ico);
 		icon.offset = SDL_ReadLE32(ico);
 		Uint32 score = icon.width * icon.height * icon.colors;
@@ -158,37 +158,32 @@ int main(int argc, char *argv[]) {
 	pngWrite(png, zero, 3);
 	pngUint32(png, ~pngCRC);
 
-	// Copy the palette, reserving index 0 for transparency. We assume at most
-	// 255 colors will be used by the icon.
+	// Read the real bpp and palette count from the DIB header
 	SDL_RWseek(ico, bestIcon.offset, RW_SEEK_SET);
 	Uint32 dibHeaderLength = SDL_ReadLE32(ico);
-	Uint32 paletteCount = 1 << bestIcon.bpp;
-	Uint8 *palette = calloc(1 + paletteCount, 3);
-	if (!palette) errx(1, "calloc failed");
-	if (dibHeaderLength == 0x0C) {
-		SDL_RWseek(ico, bestIcon.offset + dibHeaderLength, RW_SEEK_SET);
-		for (Uint32 i = 0; i < paletteCount; ++i) {
-			palette[3 * (i + 1) + 2] = SDL_ReadU8(ico);
-			palette[3 * (i + 1) + 1] = SDL_ReadU8(ico);
-			palette[3 * (i + 1) + 0] = SDL_ReadU8(ico);
-		}
-	} else if (dibHeaderLength == 0x28) {
-		SDL_RWseek(ico, 0x1C, RW_SEEK_CUR);
-		paletteCount = SDL_ReadLE32(ico);
-		if (!paletteCount) paletteCount = 1 << bestIcon.bpp;
-		SDL_RWseek(ico, bestIcon.offset + dibHeaderLength, RW_SEEK_SET);
-		for (Uint32 i = 0; i < paletteCount; ++i) {
-			palette[3 * (i + 1) + 2] = SDL_ReadU8(ico);
-			palette[3 * (i + 1) + 1] = SDL_ReadU8(ico);
-			palette[3 * (i + 1) + 0] = SDL_ReadU8(ico);
-			SDL_ReadU8(ico);
-		}
-	} else {
+	if (dibHeaderLength != 0x28) {
 		errx(
 			1, "%s: unrecognized DIB header length %u",
 			icoPath, dibHeaderLength
 		);
 	}
+	SDL_RWseek(ico, 0x0A, RW_SEEK_CUR);
+	bestIcon.bpp = SDL_ReadLE16(ico); // the truth
+	SDL_RWseek(ico, 0x10, RW_SEEK_CUR);
+	Uint32 paletteCount = SDL_ReadLE32(ico);
+	if (!paletteCount) paletteCount = 1 << bestIcon.bpp;
+
+	// Copy the palette, reserving index 0 for transparency. We assume at most
+	// 255 colors will be used by the icon.
+	Uint8 *palette = calloc(1 + paletteCount, 3);
+	if (!palette) errx(1, "calloc failed");
+	SDL_RWseek(ico, bestIcon.offset + dibHeaderLength, RW_SEEK_SET);
+	for (Uint32 i = 0; i < paletteCount; ++i) {
+		palette[3 * (i + 1) + 2] = SDL_ReadU8(ico);
+		palette[3 * (i + 1) + 1] = SDL_ReadU8(ico);
+		palette[3 * (i + 1) + 0] = SDL_ReadU8(ico);
+		SDL_ReadU8(ico);
+	}
 	pngChunk(png, "PLTE", 3 * (1 + paletteCount));
 	pngWrite(png, palette, 3 * (1 + paletteCount));
 	pngUint32(png, ~pngCRC);