git.lucas.co / go_mono
git clone https://git.lucas.co/go_mono.git

commita5392f068b20c5126e356d1987f3eb74fffe1af2
parentf9550b04a5
authorentooone <entooone@gmail.com>
date2023-07-09 14:16
bmp: support to decode 8-bit format with up to 256 color palette

If colorUsed is 0, the number of palette is 2 to the power of bit per pixel.
testdata/colormap-251.{bmp,png} are added for testing 8-bit format with colorUsed less than 256.
testdata/colormap-0.{bmp,png} are added for testing 8-bit format with colorUsed 0.

Fixes golang/go#61240

Change-Id: I1a627a570f667874a91c517f4a771e9e97d2af6b
Reviewed-on: https://go-review.googlesource.com/c/image/+/508575
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
Reviewed-by: Nigel Tao (INACTIVE; USE @golang.org INSTEAD) <nigeltao@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Nigel Tao <nigeltao@golang.org>

 bmp/reader.go             |  14 +++++++++++---
 bmp/reader_test.go        |   2 ++
 testdata/colormap-0.bmp   | Bin 0 -> 16818 bytes
 testdata/colormap-0.png   | Bin 0 -> 12572 bytes
 testdata/colormap-251.bmp | Bin 0 -> 16798 bytes
 testdata/colormap-251.png | Bin 0 -> 12254 bytes
 6 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/bmp/reader.go b/bmp/reader.go
index e165c2e..1939c11 100644
--- a/bmp/reader.go
+++ b/bmp/reader.go
@@ -191,14 +191,22 @@ func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown b
 	}
 	switch bpp {
 	case 8:
-		if offset != fileHeaderLen+infoLen+256*4 {
+		colorUsed := readUint32(b[46:50])
+		// If colorUsed is 0, it is set to the maximum number of colors for the given bpp, which is 2^bpp.
+		if colorUsed == 0 {
+			colorUsed = 256
+		} else if colorUsed > 256 {
 			return image.Config{}, 0, false, false, ErrUnsupported
 		}
-		_, err = io.ReadFull(r, b[:256*4])
+
+		if offset != fileHeaderLen+infoLen+colorUsed*4 {
+			return image.Config{}, 0, false, false, ErrUnsupported
+		}
+		_, err = io.ReadFull(r, b[:colorUsed*4])
 		if err != nil {
 			return image.Config{}, 0, false, false, err
 		}
-		pcm := make(color.Palette, 256)
+		pcm := make(color.Palette, colorUsed)
 		for i := range pcm {
 			// BMP images are stored in BGR order rather than RGB order.
 			// Every 4th byte is padding.
diff --git a/bmp/reader_test.go b/bmp/reader_test.go
index 8325f34..003d64f 100644
--- a/bmp/reader_test.go
+++ b/bmp/reader_test.go
@@ -41,6 +41,8 @@ func compare(img0, img1 image.Image) error {
 func TestDecode(t *testing.T) {
 	testCases := []string{
 		"colormap",
+		"colormap-0",
+		"colormap-251",
 		"video-001",
 		"yellow_rose-small",
 		"yellow_rose-small-v5",
diff --git a/testdata/colormap-0.bmp b/testdata/colormap-0.bmp
new file mode 100644
index 0000000..03a9a6a
Binary files /dev/null and b/testdata/colormap-0.bmp differ
diff --git a/testdata/colormap-0.png b/testdata/colormap-0.png
new file mode 100644
index 0000000..7a6b866
Binary files /dev/null and b/testdata/colormap-0.png differ
diff --git a/testdata/colormap-251.bmp b/testdata/colormap-251.bmp
new file mode 100644
index 0000000..6b8dad6
Binary files /dev/null and b/testdata/colormap-251.bmp differ
diff --git a/testdata/colormap-251.png b/testdata/colormap-251.png
new file mode 100644
index 0000000..81c489c
Binary files /dev/null and b/testdata/colormap-251.png differ