From 9c028a9c07d7040dc6ebea2e48970fb1f6d814d6 Mon Sep 17 00:00:00 2001 From: Valeriy Mironov Date: Mon, 20 Aug 2018 01:53:54 +0300 Subject: [PATCH] Added unpacking of 32-bit images appeared in some new official WFs --- Resources/Image/Reader.cs | 117 +++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/Resources/Image/Reader.cs b/Resources/Image/Reader.cs index 9fcd63d..894b385 100644 --- a/Resources/Image/Reader.cs +++ b/Resources/Image/Reader.cs @@ -31,7 +31,17 @@ namespace Resources.Image throw new InvalidResourceException("Image signature doesn't match."); ReadHeader(); - ReadPalette(); + if (_paletteColors > 256) + throw new InvalidResourceException( + "Too many palette colors."); + + if (_paletteColors > 0) + ReadPalette(); + else if (_bitsPerPixel == 8 || _bitsPerPixel == 16 || _bitsPerPixel == 24 || _bitsPerPixel == 32) + Logger.Trace("The image doesn't use a palette."); + else + throw new InvalidResourceException( + "The image format is not supported. Please report the issue on https://bitbucket.org/valeronm/amazfitbiptools"); return ReadImage(); } @@ -65,7 +75,6 @@ namespace Resources.Image if (padding != 0) Logger.Warn("Palette item {0} last byte is not zero: {1:X2}", i, padding); var isColorValid = (r == 0 || r == 0xff) && (g == 0 || g == 0xff) && (b == 0 || b == 0xff); - if (isColorValid) Logger.Trace("Palette item {0}: R {1:X2}, G {2:X2}, B {3:X2}", i, r, g, b); else @@ -77,6 +86,16 @@ namespace Resources.Image } private Bitmap ReadImage() + { + if (_paletteColors > 0) return ReadPaletteImage(); + if (_bitsPerPixel == 8) return Read8BitImage(); + if (_bitsPerPixel == 16) return Read16BitImage(); + if (_bitsPerPixel == 24) return Read24BitImage(); + if (_bitsPerPixel == 32) return Read32BitImage(); + throw new InvalidResourceException($"Unsupported bits per pixel value: {_bitsPerPixel}"); + } + + private Bitmap ReadPaletteImage() { var image = new Bitmap(_width, _height); using (var context = image.CreateUnsafeContext()) @@ -88,7 +107,99 @@ namespace Resources.Image for (var x = 0; x < _width; x++) { var pixelColorIndex = bitReader.ReadBits(_bitsPerPixel); - var color = _palette[(int) pixelColorIndex]; + var color = _palette[(int)pixelColorIndex]; + context.SetPixel(x, y, color); + } + } + } + + return image; + } + + private Bitmap Read8BitImage() + { + var image = new Bitmap(_width, _height); + using (var context = image.CreateUnsafeContext()) + { + for (var y = 0; y < _height; y++) + { + var rowBytes = _reader.ReadBytes(_rowLengthInBytes); + for (var x = 0; x < _width; x++) + { + var data = rowBytes[x]; + var color = Color.FromArgb(0xff, data, data, data); + context.SetPixel(x, y, color); + } + } + } + + return image; + } + + private Bitmap Read16BitImage() + { + var image = new Bitmap(_width, _height); + using (var context = image.CreateUnsafeContext()) + { + for (var y = 0; y < _height; y++) + { + var rowBytes = _reader.ReadBytes(_rowLengthInBytes); + var bitReader = new BitReader(rowBytes); + for (var x = 0; x < _width; x++) + { + var firstByte = (int)bitReader.ReadByte(); + var secondByte = (int)bitReader.ReadByte(); + var b = (byte)((secondByte >> 3) & 0x1f) << 3; + var g = (byte)(((firstByte >> 5) & 0x7) | ((secondByte & 0x07) << 3)) << 2; + var r = (byte)(firstByte & 0x1f) << 3; + var color = Color.FromArgb(0xff, r, g, b); + context.SetPixel(x, y, color); + } + } + } + + return image; + } + + private Bitmap Read24BitImage() + { + var image = new Bitmap(_width, _height); + using (var context = image.CreateUnsafeContext()) + { + for (var y = 0; y < _height; y++) + { + var rowBytes = _reader.ReadBytes(_rowLengthInBytes); + var bitReader = new BitReader(rowBytes); + for (var x = 0; x < _width; x++) + { + var alpha = (int)bitReader.ReadByte(); + var b = (int)(bitReader.ReadBits(5) << 3); + var g = (int)(bitReader.ReadBits(6) << 2); + var r = (int)(bitReader.ReadBits(5) << 3); + var color = Color.FromArgb(0xff - alpha, r, g, b); + context.SetPixel(x, y, color); + } + } + } + + return image; + } + + private Bitmap Read32BitImage() + { + var image = new Bitmap(_width, _height); + using (var context = image.CreateUnsafeContext()) + { + for (var y = 0; y < _height; y++) + { + var rowBytes = _reader.ReadBytes(_rowLengthInBytes); + for (var x = 0; x < _width; x++) + { + var r = rowBytes[x * 4]; + var g = rowBytes[x * 4 + 1]; + var b = rowBytes[x * 4 + 2]; + var alpha = rowBytes[x * 4 + 3]; + var color = Color.FromArgb(0xff - alpha, r, g, b); context.SetPixel(x, y, color); } }