From 53adf15226ec960b351044de9e3e88aa5aa6686b Mon Sep 17 00:00:00 2001 From: treeform Date: Thu, 30 Apr 2026 09:05:51 -0700 Subject: [PATCH] Use default palettes for indexed BMPs --- src/pixie/fileformats/bmp.nim | 4 +-- tests/test_bmp.nim | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/pixie/fileformats/bmp.nim b/src/pixie/fileformats/bmp.nim index 65d7c051..f7ffe00b 100644 --- a/src/pixie/fileformats/bmp.nim +++ b/src/pixie/fileformats/bmp.nim @@ -77,8 +77,8 @@ proc decodeDib*( if colorPaletteSize < 0 or colorPaletteSize > 256: failInvalid() - if bits == 8 and colorPaletteSize == 0: - colorPaletteSize = 256 + if bits in [1, 4, 8] and colorPaletteSize == 0: + colorPaletteSize = 1 shl bits var colorPalette = newSeq[ColorRGBA](colorPaletteSize) if colorPaletteSize > 0: diff --git a/tests/test_bmp.nim b/tests/test_bmp.nim index 41b583be..4f3f0d5d 100644 --- a/tests/test_bmp.nim +++ b/tests/test_bmp.nim @@ -1,5 +1,46 @@ import os, pixie, pixie/fileformats/bmp +proc addLe16(data: var string, value: int) = + data.add(char(value and 0xff)) + data.add(char((value shr 8) and 0xff)) + +proc addLe32(data: var string, value: int) = + data.add(char(value and 0xff)) + data.add(char((value shr 8) and 0xff)) + data.add(char((value shr 16) and 0xff)) + data.add(char((value shr 24) and 0xff)) + +proc makeIndexedBmp(bits: int, pixelData: string): string = + let + paletteEntries = 1 shl bits + pixelDataOffset = 14 + 40 + paletteEntries * 4 + fileSize = pixelDataOffset + pixelData.len + + result.add("BM") + result.addLe32(fileSize) + result.addLe16(0) + result.addLe16(0) + result.addLe32(pixelDataOffset) + result.addLe32(40) # BITMAPINFOHEADER + result.addLe32(1) # Width + result.addLe32(1) # Height + result.addLe16(1) # Planes + result.addLe16(bits) + result.addLe32(0) # BI_RGB + result.addLe32(pixelData.len) + result.addLe32(0) + result.addLe32(0) + result.addLe32(0) # clrUsed = 0 means use the default palette size. + result.addLe32(0) + + for i in 0 ..< paletteEntries: + if i == paletteEntries - 1: + result.add("\xff\xff\xff\x00") + else: + result.add("\x00\x00\x00\x00") + + result.add(pixelData) + # block: # var image = newImage(4, 2) @@ -37,6 +78,13 @@ block: image = decodeBmp(readFile(path)) writeFile("tests/fileformats/bmp/knight." & $bits & ".bmp", encodeBmp(image)) +block: + for fixture in [(1, "\x80\x00\x00\x00"), (4, "\xf0\x00\x00\x00")]: + let image = decodeBmp(makeIndexedBmp(fixture[0], fixture[1])) + doAssert image.width == 1 + doAssert image.height == 1 + doAssert image.data[0] == rgbx(255, 255, 255, 255) + block: let image = decodeBmp(readFile( "tests/fileformats/bmp/rgb.24.master.bmp"