From 305d65187c78f0148e14f78506b48251a4e5f935 Mon Sep 17 00:00:00 2001
From: treeform <starplant@gmail.com>
Date: Fri, 20 Nov 2020 09:56:34 -0800
Subject: [PATCH] Add supprot for 24bit bitmaps.

---
 src/pixie/fileformats/bmp.nim         |  25 ++++++++++++++++++-------
 tests/images/bmp/knight.24.bmp        | Bin 0 -> 890 bytes
 tests/images/bmp/knight.24.master.bmp | Bin 0 -> 630 bytes
 tests/images/bmp/knight.32.bmp        | Bin 0 -> 890 bytes
 tests/images/bmp/knight.32.master.bmp | Bin 0 -> 890 bytes
 tests/testbmp.nim                     |   5 +++++
 6 files changed, 23 insertions(+), 7 deletions(-)
 create mode 100644 tests/images/bmp/knight.24.bmp
 create mode 100644 tests/images/bmp/knight.24.master.bmp
 create mode 100644 tests/images/bmp/knight.32.bmp
 create mode 100644 tests/images/bmp/knight.32.master.bmp

diff --git a/src/pixie/fileformats/bmp.nim b/src/pixie/fileformats/bmp.nim
index 793ecdf..8ca1cf7 100644
--- a/src/pixie/fileformats/bmp.nim
+++ b/src/pixie/fileformats/bmp.nim
@@ -1,4 +1,4 @@
-import ../images, flatty/binny, flatty/hexPrint, chroma, sequtils
+import ../images, flatty/binny, flatty/hexPrint, chroma, sequtils, print
 
 # See: https://en.wikipedia.org/wiki/BMP_file_format
 
@@ -10,21 +10,32 @@ proc decodeBmp*(data: string): Image =
   let
     width = data.readInt32(0x12).int
     height = data.readInt32(0x16).int
-    # TODO: Handle masks.
+    bits = data.readUint16(0x1C)
+    compression = data.readUint32(0x1E)
   var
     offset = data.readUInt32(0xA).int
 
+  doAssert bits in {32, 24}
+  doAssert compression in {0, 3}
+
   result = newImage(width, height)
 
   for y in 0 ..< result.height:
     for x in 0 ..< result.width:
       var rgba: ColorRGBA
-      rgba.r = data.readUint8(offset+0)
-      rgba.g = data.readUint8(offset+1)
-      rgba.b = data.readUint8(offset+2)
-      rgba.a = data.readUint8(offset+3)
+      if bits == 32:
+        rgba.r = data.readUint8(offset + 0)
+        rgba.g = data.readUint8(offset + 1)
+        rgba.b = data.readUint8(offset + 2)
+        rgba.a = data.readUint8(offset + 3)
+        offset += 4
+      elif bits == 24:
+        rgba.r = data.readUint8(offset + 2)
+        rgba.g = data.readUint8(offset + 1)
+        rgba.b = data.readUint8(offset + 0)
+        rgba.a = 255
+        offset += 3
       result[x, result.height - y - 1] = rgba
-      offset += 4
 
 proc encodeBmp*(image: Image): string =
   ## Encodes an image into bitmap data.
diff --git a/tests/images/bmp/knight.24.bmp b/tests/images/bmp/knight.24.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..ed23acc5f88fcb2c22cadb4fd14485fd826b817c
GIT binary patch
literal 890
zcmb7=v1$TQ5JgukwFu+~wzRWLVI$b5uu(y*B@pcO0|Fsc@bk3vKh}399GNVyap1n0
zH}}jub{FrbVH0sG=V#Hl=%r}Tv<+5U^g8-eDI+@0bgVxPZ5U4+U5fqhcUMzF9wprT
zZ547R-vt-j<AcHHE?@K9p=WkBXIV3BP5R`o-8mR*@61snJnwwR^=A`3JZd>>cxr=L
zdT2VC{gZu|9Q5fSXT0O}L$Aiu%i(U{cE5Lc-;i~`-)gq+4B7u6Q_C>0ctmFK`a5I-
UPCVT0vJ5`Y$mQ%C{r#D_16X|M;{X5v

literal 0
HcmV?d00001

diff --git a/tests/images/bmp/knight.24.master.bmp b/tests/images/bmp/knight.24.master.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..a641e1bc8193d1bc5b7270d356b0c18ef19f2f84
GIT binary patch
literal 630
zcmZ9HF$%&!5JgvO3rmlX&Mt+GlHS552x9FG1TP?nm3TZYy+?fHZH8sT?Dx;i+i|wr
zU*~E3TD0LTI7`kft<aQqxj!aZhUt5}E>%pO{7biQw}e=D+qY9^3&qP+MXy*?g+m1b
zgDE4r@AKX37(J=pQFyjGKEI@Rj9m>yOu06dO|y<5C779CJ`AQ*WH1E905BFShBO$5
tpoDYuF-pKWF05J+L*qFm6AuKy^QX~;FR$2gtGIRe{7Ni#uCSOBz#qkmBc}iW

literal 0
HcmV?d00001

diff --git a/tests/images/bmp/knight.32.bmp b/tests/images/bmp/knight.32.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..ebce0d18b205344051665f5613b9d690da4751a9
GIT binary patch
literal 890
zcmb7=v5EpQ6h%k2)I!)Fn9|P9!bY&)!bSzL7D2Yx4-jOl#n02y|A;wRjy#7nJ8*Mf
za?g7qGygh$H03+x^^i5l8fNvHwjpY>KKp;lW%&|oSXTS*wgmrJQc8{5{a#W{=F#D1
zlVy=TaW6aH9A6AMd-+=C3^U!{=(0L&P3HJ{do7H$d-|vmnS0)G|5=waGHN+%c<Sz(
zIUkRvZ{p1P^0;T*YmaXsi!8NSjpr=#&c>1R-NRGUgU8vvRgamh|3RkaF!YjfPh`lt
XGh}dUdf*<nMe*1p7u`F$^CR;FYpTTu

literal 0
HcmV?d00001

diff --git a/tests/images/bmp/knight.32.master.bmp b/tests/images/bmp/knight.32.master.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..ebce0d18b205344051665f5613b9d690da4751a9
GIT binary patch
literal 890
zcmb7=v5EpQ6h%k2)I!)Fn9|P9!bY&)!bSzL7D2Yx4-jOl#n02y|A;wRjy#7nJ8*Mf
za?g7qGygh$H03+x^^i5l8fNvHwjpY>KKp;lW%&|oSXTS*wgmrJQc8{5{a#W{=F#D1
zlVy=TaW6aH9A6AMd-+=C3^U!{=(0L&P3HJ{do7H$d-|vmnS0)G|5=waGHN+%c<Sz(
zIUkRvZ{p1P^0;T*YmaXsi!8NSjpr=#&c>1R-NRGUgU8vvRgamh|3RkaF!YjfPh`lt
XGh}dUdf*<nMe*1p7u`F$^CR;FYpTTu

literal 0
HcmV?d00001

diff --git a/tests/testbmp.nim b/tests/testbmp.nim
index 0c02aaa..681f974 100644
--- a/tests/testbmp.nim
+++ b/tests/testbmp.nim
@@ -29,3 +29,8 @@ block:
   doAssert image2.width == image.width
   doAssert image2.height == image.height
   doAssert image2.data == image.data
+
+block:
+  for bits in [32, 24]:
+    var image = decodeBmp(readFile("images/bmp/knight." & $bits & ".master.bmp"))
+    writeFile("images/bmp/knight." & $bits & ".bmp", encodeBmp(image))