From 8130845de859119dcf02388c0ac06402632f8731 Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Fri, 11 Oct 2024 07:53:32 -0400 Subject: [PATCH] Microsoft RIFF palette support --- BinxelviewForm.cs | 95 +++++++++++++++++++++++++++++++++++++++++------ readme.txt | 2 + 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/BinxelviewForm.cs b/BinxelviewForm.cs index 28cd1d9..a23a758 100644 --- a/BinxelviewForm.cs +++ b/BinxelviewForm.cs @@ -323,14 +323,16 @@ string parseOption(string optline) } if (opt == "PAL") // load palette file { - bool image = + int paltype = 0; + if ( valu.EndsWith(".BMP") || valu.EndsWith(".GIF") || valu.EndsWith(".PNG") || - valu.EndsWith(".TIF"); - bool vga = - valu.EndsWith(".VGA"); - if (!loadPalette(val,image,vga)) return "Could not load palette file: "+val+"\n"+palette_error; + valu.EndsWith(".TIF")) + paltype = 1; + if (valu.EndsWith(".VGA")) paltype = 2; + if (valu.EndsWith(".RIFF")) paltype = 3; + if (!loadPalette(val,paltype)) return "Could not load palette file: "+val+"\n"+palette_error; return ""; } if (opt == "AUTOPAL") @@ -1055,10 +1057,14 @@ void initCustomPalette() palette_mode = PaletteMode.PALETTE_CUSTOM; } - bool loadPalette(string path, bool image, bool sixbit_vga) + bool loadPalette(string path, int filetype) { + // filetype <=0,>=4: RGB24 + // 1: image (BMP, GIF, PNG, TIF) + // 2: VGA RGB18 stored in the low 6 bits of each byte. + // 3: Microsoft RIFF PAL - if (image) + if (filetype == 1) // image { Image img; try @@ -1100,13 +1106,79 @@ bool loadPalette(string path, bool image, bool sixbit_vga) return false; } + if (filetype == 3) // Microsoft RIFF palette format + { + // verify RIFF header + if (read_data.Length < 12 || + read_data[ 0] != 'R' || + read_data[ 1] != 'I' || + read_data[ 2] != 'F' || + read_data[ 3] != 'F' || + read_data[ 8] != 'P' || + read_data[ 9] != 'A' || + read_data[10] != 'L' || + read_data[11] != ' ') + { + palette_error = "Microsoft RIFF PAL has invalid header."; + return false; + } + + // find data chunk + int chunk_len = 0; + int riff_pos = 12; + while ((riff_pos+8) < read_data.Length) + { + chunk_len = + (read_data[riff_pos+4] << 0) | + (read_data[riff_pos+5] << 8) | + (read_data[riff_pos+6] << 16) | + (read_data[riff_pos+7] << 24); + if (chunk_len < 0) + { + palette_error = "Microsoft RIFF PAL has invalid chunk size."; + return false; + } + + if (read_data[riff_pos+0] == 'd' && + read_data[riff_pos+1] == 'a' && + read_data[riff_pos+2] == 't' && + read_data[riff_pos+3] == 'a') + break; + riff_pos += 8 + chunk_len; // skip to next chunk + } + if ((riff_pos+8) >= read_data.Length) + { + palette_error = "Microsoft RIFF PAL missing data chunk."; + return false; + } + if ((riff_pos+8+chunk_len) > read_data.Length || chunk_len < 4) + { + palette_error = "Microsoft RIFF PAL data chunk incomplete."; + return false; + } + + // replace read_data with converted data chunk + riff_pos += 12; // 8 byte 'data' + size header, 4 bytes ignored: 00 03 00 01 (unknown meaning) + chunk_len -= 4; // first 4 bytes skipped + byte[] riff_convert = new byte[(chunk_len / 4) * 3]; + for (int i=0; (i+2)