diff --git a/SRC/Aura_OS/Aura_OS.csproj b/SRC/Aura_OS/Aura_OS.csproj index 00a2748f..aaa9ed34 100644 --- a/SRC/Aura_OS/Aura_OS.csproj +++ b/SRC/Aura_OS/Aura_OS.csproj @@ -24,11 +24,16 @@ True + + + + + diff --git a/SRC/Aura_OS/Files.cs b/SRC/Aura_OS/Files.cs index 34c3bd92..2505915c 100644 --- a/SRC/Aura_OS/Files.cs +++ b/SRC/Aura_OS/Files.cs @@ -19,6 +19,9 @@ public class Files [ManifestResourceStream(ResourceName = "Aura_OS.Resources.wallpaper-1.bmp")] public static byte[] Wallpaper; + [ManifestResourceStream(ResourceName = "Aura_OS.Resources.wallpaper-1.png")] + public static byte[] WallpaperPng; + [ManifestResourceStream(ResourceName = "Aura_OS.Resources.wallpaper-2.bmp")] public static byte[] Wallpaper2; @@ -52,6 +55,9 @@ public static void LoadFiles() Kernel.wallpaper1 = new Bitmap(Files.Wallpaper); CustomConsole.WriteLineOK("wallpaper-1.bmp wallpaper loaded."); + Kernel.wallpaper1png = new Png(Files.WallpaperPng); + CustomConsole.WriteLineOK("wallpaper-1.png wallpaper loaded."); + Kernel.wallpaper2 = new Bitmap(Files.Wallpaper2); CustomConsole.WriteLineOK("wallpaper-2.bmp wallpaper loaded."); diff --git a/SRC/Aura_OS/Kernel.cs b/SRC/Aura_OS/Kernel.cs index 1066e410..481e2775 100644 --- a/SRC/Aura_OS/Kernel.cs +++ b/SRC/Aura_OS/Kernel.cs @@ -85,6 +85,7 @@ public static bool NetworkConnected public static Bitmap CosmosLogo; public static Bitmap wallpaper1; + public static Png wallpaper1png; public static Bitmap wallpaper2; public static Bitmap auralogo_white; diff --git a/SRC/Aura_OS/Properties/VersionInfo.cs b/SRC/Aura_OS/Properties/VersionInfo.cs index 881edc93..a84f2bcc 100644 --- a/SRC/Aura_OS/Properties/VersionInfo.cs +++ b/SRC/Aura_OS/Properties/VersionInfo.cs @@ -2,6 +2,6 @@ namespace Aura_OS { public class VersionInfo { - public static string revision = "130320241316"; + public static string revision = "130320241712"; } } diff --git a/SRC/Aura_OS/Resources/wallpaper-1.png b/SRC/Aura_OS/Resources/wallpaper-1.png new file mode 100644 index 00000000..7471466c Binary files /dev/null and b/SRC/Aura_OS/Resources/wallpaper-1.png differ diff --git a/SRC/Aura_OS/Resources/wallpaper-1.png.bak b/SRC/Aura_OS/Resources/wallpaper-1.png.bak new file mode 100644 index 00000000..2763c385 Binary files /dev/null and b/SRC/Aura_OS/Resources/wallpaper-1.png.bak differ diff --git a/SRC/Aura_OS/System/Compression/BinaryReader.cs b/SRC/Aura_OS/System/Compression/BinaryReader.cs new file mode 100644 index 00000000..5bce5ec5 --- /dev/null +++ b/SRC/Aura_OS/System/Compression/BinaryReader.cs @@ -0,0 +1,98 @@ +namespace CosmosGL.System +{ + public class BinaryReader + { + private int _pos = 0; + private byte[] _data; + + public BinaryReader(byte[] data) + { + _data = data; + } + + public int Seek(int pos) + { + var oldPos = _pos; + _pos = pos; + return oldPos; + } + + public int Tell() + { + return _pos; + } + + public byte GetUint8() + { + return _data[_pos++]; + } + + public ushort GetUint16() + { + return (ushort)(((GetUint8() << 8) | GetUint8()) >> 0); + } + + public uint GetUint32() + { + return (uint)GetInt32(); + } + + public short GetInt16() + { + // var result = GetUint16(); + // if ((result & 0x8000) == 1) + // { + // result -= (1 << 16); + // } + // return result; + + return (short)GetUint16(); + } + + public int GetInt32() + { + return ((GetUint8() << 24) | + (GetUint8() << 16) | + (GetUint8() << 8) | + (GetUint8())); + } + + public short GetFword() + { + return GetInt16(); + } + + public int Get2Dot14() + { + return GetInt16() / (1 << 14); + } + + public int GetFixed() + { + return GetInt32() / (1 << 16); + } + + public string GetString(int length) + { + var result = ""; + for (var i = 0; i < length; i++) + { + result += (char)GetUint8(); + } + return result; + } + + public void GetDate() + { + GetUint32(); + GetUint32(); + /* var macTime = GetUint32() * 0x100000000 + GetUint32(); + return new DateTime(macTime, DateTimeKind.Utc);*/ + } + + public char GetChar() + { + return (char)GetUint8(); + } + } +} \ No newline at end of file diff --git a/SRC/Aura_OS/System/Compression/Deflate.cs b/SRC/Aura_OS/System/Compression/Deflate.cs new file mode 100644 index 00000000..6a7f7917 --- /dev/null +++ b/SRC/Aura_OS/System/Compression/Deflate.cs @@ -0,0 +1,368 @@ +using System; +using System.Collections.Generic; + +namespace CosmosGL.System +{ + /// + /// public domain zlib decode + /// original: v0.2 Sean Barrett 2006-11-18 + /// ported to C# by Tammo Hinrichs, 2012-08-02 + /// simple implementation + /// - all input must be provided in an upfront buffer + /// - all output is written to a single output buffer + /// - Warning: This is SLOW. It's no miracle .NET as well as Mono implement DeflateStream natively. + /// + public class ZlibDecoder + { + /// + /// Decode deflated data + /// + /// deflated input data + /// uncompressed output + public static List Inflate(IList compressed) + { + return new ZlibDecoder { In = compressed }.Inflate(); + } + + #region internal + + // fast-way is faster to check than jpeg huffman, but slow way is slower + private const int FastBits = 9; // accelerate all cases in default tables + private const int FastMask = ((1 << FastBits) - 1); + + private static readonly int[] DistExtra = new[] + { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13 + }; + + private static readonly int[] LengthBase = new[] + { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, + 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, + 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + }; + + private static readonly int[] LengthExtra = new[] + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, + 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 + }; + + private static readonly int[] DistBase = new[] + { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, + 12289, 16385, 24577, 0, 0 + }; + + private static readonly int[] LengthDezigzag = new[] + { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, + 14, + 1, 15 + }; + + // @TODO: should statically initialize these for optimal thread safety + private static readonly byte[] DefaultLength = new byte[288]; + private static readonly byte[] DefaultDistance = new byte[32]; + + private List Out; + private UInt32 CodeBuffer; + private int NumBits; + + private Huffman Distance; + private Huffman Length; + + private int InPos; + private IList In; + + private static void InitDefaults() + { + int i; // use <= to match clearly with spec + for (i = 0; i <= 143; ++i) DefaultLength[i] = 8; + for (; i <= 255; ++i) DefaultLength[i] = 9; + for (; i <= 279; ++i) DefaultLength[i] = 7; + for (; i <= 287; ++i) DefaultLength[i] = 8; + + for (i = 0; i <= 31; ++i) DefaultDistance[i] = 5; + } + + private static int BitReverse16(int n) + { + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; + } + + private static int BitReverse(int v, int bits) + { + // Debug.Assert(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return BitReverse16(v) >> (16 - bits); + } + + private int Get8() + { + return InPos >= In.Count ? 0 : In[InPos++]; + } + + private void FillBits() + { + do + { + // Debug.Assert(CodeBuffer < (1U << NumBits)); + CodeBuffer |= (uint)(Get8() << NumBits); + NumBits += 8; + } while (NumBits <= 24); + } + + private uint Receive(int n) + { + if (NumBits < n) FillBits(); + var k = (uint)(CodeBuffer & ((1 << n) - 1)); + CodeBuffer >>= n; + NumBits -= n; + return k; + } + + private int HuffmanDecode(Huffman z) + { + int s; + if (NumBits < 16) FillBits(); + int b = z.Fast[CodeBuffer & FastMask]; + if (b < 0xffff) + { + s = z.Size[b]; + CodeBuffer >>= s; + NumBits -= s; + return z.Value[b]; + } + + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + int k = BitReverse((int)CodeBuffer, 16); + for (s = FastBits + 1; ; ++s) + if (k < z.MaxCode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16 - s)) - z.FirstCode[s] + z.FirstSymbol[s]; + // Debug.Assert(z.Size[b] == s); + CodeBuffer >>= s; + NumBits -= s; + return z.Value[b]; + } + + private void ParseHuffmanBlock() + { + for (; ; ) + { + int z = HuffmanDecode(Length); + if (z < 256) + { + if (z < 0) throw new Exception("bad huffman code"); // error in huffman codes + Out.Add((byte)z); + } + else + { + if (z == 256) return; + z -= 257; + int len = LengthBase[z]; + if (LengthExtra[z] != 0) len += (int)Receive(LengthExtra[z]); + z = HuffmanDecode(Distance); + if (z < 0) throw new Exception("bad huffman code"); + int dist = DistBase[z]; + if (DistExtra[z] != 0) dist += (int)Receive(DistExtra[z]); + dist = Out.Count - dist; + if (dist < 0) throw new Exception("bad dist"); + for (int i = 0; i < len; i++, dist++) + Out.Add(Out[dist]); + } + } + } + + private void ComputeHuffmanCodes() + { + var lenCodes = new byte[286 + 32 + 137]; //padding for maximum single op + var codeLengthSizes = new byte[19]; + + uint hlit = Receive(5) + 257; + uint hdist = Receive(5) + 1; + uint hclen = Receive(4) + 4; + + for (int i = 0; i < hclen; ++i) + codeLengthSizes[LengthDezigzag[i]] = (byte)Receive(3); + + var codeLength = new Huffman(new ArraySegment(codeLengthSizes)); + + int n = 0; + while (n < hlit + hdist) + { + int c = HuffmanDecode(codeLength); + // Debug.Assert(c >= 0 && c < 19); + if (c < 16) + lenCodes[n++] = (byte)c; + else if (c == 16) + { + c = (int)Receive(2) + 3; + for (int i = 0; i < c; i++) lenCodes[n + i] = lenCodes[n - 1]; + n += c; + } + else if (c == 17) + { + c = (int)Receive(3) + 3; + for (int i = 0; i < c; i++) lenCodes[n + i] = 0; + n += c; + } + else + { + //Debug.Assert(c == 18); + c = (int)Receive(7) + 11; + for (int i = 0; i < c; i++) lenCodes[n + i] = 0; + n += c; + } + } + if (n != hlit + hdist) throw new Exception("bad codelengths"); + Length = new Huffman(new ArraySegment(lenCodes, 0, (int)hlit)); + Distance = new Huffman(new ArraySegment(lenCodes, (int)hlit, (int)hdist)); + } + + private void ParseUncompressedBlock() + { + var header = new byte[4]; + if ((NumBits & 7) != 0) + Receive(NumBits & 7); // discard + // drain the bit-packed data into header + int k = 0; + while (NumBits > 0) + { + header[k++] = (byte)(CodeBuffer & 255); // wtf this warns? + CodeBuffer >>= 8; + NumBits -= 8; + } + //Debug.Assert(NumBits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = (byte)Get8(); + int len = header[1] * 256 + header[0]; + int nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) throw new Exception("zlib corrupt"); + if (InPos + len > In.Count) throw new Exception("read past buffer"); + + // TODO: this sucks. DON'T USE LINQ. + var tmp = new List(); + + for (int i = InPos; i < InPos + len; i++) + { + Out.Add(In[i]); + } + InPos += len; + } + + private List Inflate() + { + Out = new List(); + NumBits = 0; + CodeBuffer = 0; + + bool final; + do + { + final = Receive(1) != 0; + var type = (int)Receive(2); + if (type == 0) + { + ParseUncompressedBlock(); + } + else if (type == 3) + { + throw new Exception("invalid block type"); + } + else + { + if (type == 1) + { + // use fixed code lengths + if (DefaultDistance[31] == 0) InitDefaults(); + Length = new Huffman(new ArraySegment(DefaultLength)); + Distance = new Huffman(new ArraySegment(DefaultDistance)); + } + else + { + ComputeHuffmanCodes(); + } + ParseHuffmanBlock(); + } + } while (!final); + + return Out; + } + + + private class Huffman + { + public readonly UInt16[] Fast = new UInt16[1 << FastBits]; + public readonly UInt16[] FirstCode = new UInt16[16]; + public readonly UInt16[] FirstSymbol = new UInt16[16]; + public readonly int[] MaxCode = new int[17]; + public readonly Byte[] Size = new Byte[288]; + public readonly UInt16[] Value = new UInt16[288]; + + public Huffman(ArraySegment sizeList) + { + int i; + int k = 0; + var nextCode = new int[16]; + var sizes = new int[17]; + + // DEFLATE spec for generating codes + for (i = 0; i < Fast.Length; i++) Fast[i] = 0xffff; + for (i = 0; i < sizeList.Count; ++i) + ++sizes[sizeList.Array[i + sizeList.Offset]]; + sizes[0] = 0; + /* for (i = 1; i < 16; ++i) + Debug.Assert(sizes[i] <= (1 << i));*/ + int code = 0; + for (i = 1; i < 16; ++i) + { + nextCode[i] = code; + FirstCode[i] = (UInt16)code; + FirstSymbol[i] = (UInt16)k; + code = (code + sizes[i]); + if (sizes[i] != 0) + if (code - 1 >= (1 << i)) throw new Exception("bad codelengths"); + MaxCode[i] = code << (16 - i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + MaxCode[16] = 0x10000; // sentinel + for (i = 0; i < sizeList.Count; ++i) + { + int s = sizeList.Array[i + sizeList.Offset]; + if (s != 0) + { + int c = nextCode[s] - FirstCode[s] + FirstSymbol[s]; + Size[c] = (byte)s; + Value[c] = (UInt16)i; + if (s <= FastBits) + { + int j = BitReverse(nextCode[s], s); + while (j < (1 << FastBits)) + { + Fast[j] = (UInt16)c; + j += (1 << s); + } + } + ++nextCode[s]; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/SRC/Aura_OS/System/Graphics/UI/GUI/Components/Component.cs b/SRC/Aura_OS/System/Graphics/UI/GUI/Components/Component.cs index b1868a8e..1e38b92d 100644 --- a/SRC/Aura_OS/System/Graphics/UI/GUI/Components/Component.cs +++ b/SRC/Aura_OS/System/Graphics/UI/GUI/Components/Component.cs @@ -533,7 +533,12 @@ public void DrawLine(Color color, int xStart, int yStart, int width, int height) _buffer.DrawLine(color.ToArgb(), xStart, yStart, width, height); } - public void DrawImage(Bitmap image, int x, int y) + public void DrawImageNoAlpha(Image image, int x, int y) + { + _buffer.DrawImage(image, x, y); + } + + public void DrawImage(Image image, int x, int y) { _buffer.DrawImageAlpha(image, x, y); } diff --git a/SRC/Aura_OS/System/Graphics/UI/GUI/Desktop.cs b/SRC/Aura_OS/System/Graphics/UI/GUI/Desktop.cs index 7cfedaae..73cdc697 100644 --- a/SRC/Aura_OS/System/Graphics/UI/GUI/Desktop.cs +++ b/SRC/Aura_OS/System/Graphics/UI/GUI/Desktop.cs @@ -16,7 +16,7 @@ public class Desktop : Component { public FilesystemPanel MainPanel; private string _wallpaperPath; - private Bitmap _wallpaper; + private Image _wallpaper; public Desktop(int x, int y, int width, int height) : base(x, y, width, height) { @@ -29,7 +29,7 @@ public Desktop(int x, int y, int width, int height) : base(x, y, width, height) else { _wallpaperPath = "Embedded"; - _wallpaper = new Bitmap(Files.Wallpaper); + _wallpaper = Kernel.wallpaper1png; MarkDirty(); } @@ -47,7 +47,7 @@ public override void Draw() { base.Draw(); - DrawImage(_wallpaper, X, Y); + DrawImageNoAlpha(_wallpaper, X, Y); MainPanel.UpdateCurrentFolder(); MainPanel.Draw(this); diff --git a/SRC/Aura_OS/System/Graphics/UI/GUI/DirectBitmap.cs b/SRC/Aura_OS/System/Graphics/UI/GUI/DirectBitmap.cs index a8e2947d..7525a5e6 100644 --- a/SRC/Aura_OS/System/Graphics/UI/GUI/DirectBitmap.cs +++ b/SRC/Aura_OS/System/Graphics/UI/GUI/DirectBitmap.cs @@ -339,7 +339,7 @@ protected void TrimLine(ref int x1, ref int y1, ref int x2, ref int y2) y2 = (int)num4; } - public void DrawImage(Bitmap image, int x, int y) + public void DrawImage(Image image, int x, int y) { for (int yi = 0; yi < image.Height; yi++) { @@ -381,7 +381,7 @@ public static void OpacitySSE(uint* pixelPtr, int w, int h, int bpl, uint a) // PLUGGED } - public void DrawImageAlpha(Bitmap image, int x, int y, byte alpha = 0xFF) + public void DrawImageAlpha(Image image, int x, int y, byte alpha = 0xFF) { if (image.RawData.Length > Bitmap.RawData.Length) { diff --git a/SRC/Aura_OS/System/Graphics/UI/GUI/Images/Png.cs b/SRC/Aura_OS/System/Graphics/UI/GUI/Images/Png.cs new file mode 100644 index 00000000..8073d07b --- /dev/null +++ b/SRC/Aura_OS/System/Graphics/UI/GUI/Images/Png.cs @@ -0,0 +1,386 @@ +//#define COSMOSDEBUG +using Aura_OS.System; +using Aura_OS.System.Graphics.UI.GUI; +using CosmosGL.System; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.PortableExecutable; +using System.Security; +using System.Text; + +namespace Cosmos.System.Graphics +{ + /// + /// Represents a png image. + /// + public class Png : Image + { + /// + /// Initializes a new instance of class. + /// + /// The width of the image. + /// The height of the image. + /// The color depth. + /// Thrown when either the width or height is lower than 0. + public Png(uint width, uint height, ColorDepth colorDepth) : base(width, height, colorDepth) + { + if (width < 0) + { + throw new ArgumentOutOfRangeException(nameof(width)); + } + + if (height < 0) + { + throw new ArgumentOutOfRangeException(nameof(height)); + } + + RawData = new int[width * height]; + } + + /// + /// Initializes a new instance of class from a byte array + /// representing the pixels. + /// + /// The width of the png. + /// The height of the png. + /// A byte array which includes the values for each pixel. + /// The format of the pixel data. + /// Thrown if color depth is not 32. + /// Thrown if png size is bigger than Int32.MaxValue. + /// Thrown on fatal error. + /// Thrown on memory error. + /// Thrown on fatal error. + public Png(uint width, uint height, byte[] pixelData, ColorDepth colorDepth) : base(width, height, colorDepth) + { + RawData = new int[width * height]; + if (colorDepth != ColorDepth.ColorDepth32 && colorDepth != ColorDepth.ColorDepth24) + { + Global.Debugger.Send("Only color depths 24 and 32 are supported!"); + throw new NotImplementedException("Only color depths 24 and 32 are supported!"); + } + + for (int i = 0; i < RawData.Length; i++) + { + if (colorDepth == ColorDepth.ColorDepth32) + { + RawData[i] = BitConverter.ToInt32(new byte[] { pixelData[i * 4], pixelData[i * 4 + 1], pixelData[i * 4 + 2], pixelData[i * 4 + 3] }, 0); + } + else + { + RawData[i] = BitConverter.ToInt32(new byte[] { 0, pixelData[i * 3], pixelData[i * 3 + 1], pixelData[i * 3 + 2] }, 0); + } + } + } + + /// + /// Initializes a new instance of the class, using the specified path to a BMP file. + /// + /// Path to file. + /// + /// + /// Thrown if path is invalid. + /// Memory error. + /// + /// + /// + /// + /// Thrown if path is null. + /// Memory error. + /// + /// + /// Thrown on fatal error. + /// Thrown on IO error. + /// + /// + /// Thrown on fatal error. + /// The path refers to non-file. + /// + /// + /// Thrown if the stream is closed. + /// + /// + /// Thrown if header is not from a BMP. + /// Info header size has the wrong value. + /// Number of planes is not 1. Can not read file. + /// Total Image Size is smaller than pure image size. + /// + /// + /// Thrown if pixelsize is other then 32 / 24 or the file compressed. + /// Thrown if the caller does not have permissions to read / write the file. + /// Thrown if the file cannot be found. + /// Thrown if the specified path is invalid. + /// Thrown if the specified path is exceed the system-defined max length. + public Png(string path) : this(path, ColorOrder.BGR) + { + } + + /// + /// Initializes a new instance of the class, with a specified path to a BMP file. + /// + /// Path to file. + /// Order of colors in each pixel. + /// + /// + /// Thrown if path is invalid. + /// Memory error. + /// + /// + /// + /// + /// Thrown if path is null. + /// Memory error. + /// + /// + /// Thrown on fatal error. + /// Thrown on IO error. + /// + /// + /// Thrown on fatal error. + /// The path refers to non-file. + /// + /// + /// Thrown if the stream is closed. + /// + /// + /// Thrown if header is not from a BMP. + /// Info header size has the wrong value. + /// Number of planes is not 1. Can not read file. + /// Total Image Size is smaller than pure image size. + /// + /// + /// Thrown if pixelsize is other then 32 / 24 or the file compressed. + /// Thrown if the caller does not have permissions to read / write the file. + /// Thrown if the file cannot be found. + /// Thrown if the specified path is invalid. + /// Thrown if the specified path is exceed the system-defined max length. + public Png(string path, ColorOrder colorOrder = ColorOrder.BGR) : base(0, 0, ColorDepth.ColorDepth32) //Call the image constructor with wrong values + { + CreatePng(File.ReadAllBytes(path), colorOrder); + } + + /// + /// Initializes a new instance of the class, with the specified image data byte array. + /// + /// byte array. + /// Thrown if imageData is null / memory error. + /// Thrown on memory error. + /// Thrown on fatal error. + /// Thrown on IO error. + /// Thrown on fatal error. + /// Thrown on fatal error. + /// + /// + /// Thrown if header is not from a BMP. + /// Info header size has the wrong value. + /// Number of planes is not 1. + /// Total Image Size is smaller than pure image size. + /// + /// + /// Thrown if pixelsize is other then 32 / 24 or the file compressed. + public Png(byte[] imageData) : this(imageData, ColorOrder.BGR) //Call the image constructor with wrong values + { + } + + /// + /// Initializes a new instance of the class, with the specified image data byte array. + /// + /// byte array. + /// Order of colors in each pixel. + /// Thrown if imageData is null / memory error. + /// Thrown on memory error. + /// Thrown on fatal error. + /// Thrown on IO error. + /// Thrown on fatal error. + /// Thrown on fatal error. + /// + /// + /// Thrown if header is not from a BMP. + /// Info header size has the wrong value. + /// Number of planes is not 1. + /// Total Image Size is smaller than pure image size. + /// + /// + /// Thrown if pixelsize is other then 32 / 24 or the file compressed. + public Png(byte[] imageData, ColorOrder colorOrder = ColorOrder.BGR) : base(0, 0, ColorDepth.ColorDepth32) //Call the image constructor with wrong values + { + CreatePng(imageData, colorOrder); + } + + + // For more information about the format: https://docs.microsoft.com/en-us/previous-versions/ms969901(v=msdn.10)?redirectedfrom=MSDN + /// + /// Creates a png from the given I/O stream. + /// + /// Stream. + /// Order of colors in each pixel. + /// Thrown on memory error. + /// Thrown on memory error. + /// Thrown on fatal error. + /// Thrown on IO error. + /// + /// + /// Thrown on fatal error. + /// The stream does not support seeking. + /// + /// + /// Thrown if the stream is closed. + /// + /// + /// Thrown if header is not from a BMP. + /// Info header size has the wrong value. + /// Number of planes is not 1. Can not read file. + /// Total Image Size is smaller than pure image size. + /// + /// + /// Thrown if pixelsize is other then 32 / 24 or the file compressed. + private void CreatePng(byte[] bytes, ColorOrder colorOrder) + { + var reader = new CosmosGL.System.BinaryReader(bytes); + + if (reader.GetUint8() != 137) return ; + if (reader.GetUint8() != 80) return ; + if (reader.GetUint8() != 78) return ; + if (reader.GetUint8() != 71) return ; + if (reader.GetUint8() != 13) return ; + if (reader.GetUint8() != 10) return ; + if (reader.GetUint8() != 26) return ; + if (reader.GetUint8() != 10) return ; + + + DirectBitmap re = null; + + while (reader.Tell() < bytes.Length) + { + var len = reader.GetUint32(); + var name = reader.GetString(4); + + var pos = reader.Tell(); + + bool done = false; + + switch (name) + { + case "IHDR": + re = new DirectBitmap((int)reader.GetUint32(), (int)reader.GetUint32()); + var bitdepth = reader.GetUint8(); + var colortype = reader.GetUint8(); + var compression = reader.GetUint8(); + var filtermethod = reader.GetUint8(); + var interlace = reader.GetUint8(); + CustomConsole.WriteLineInfo("IHDR"); + break; + case "PLTE": + CustomConsole.WriteLineInfo("PLTE"); + break; + case "IDAT": + CustomConsole.WriteLineInfo("IDAT in"); + var buf = new List(); + reader.GetUint8(); + reader.GetUint8(); + for (int i = 2; i < len; i++) + { + buf.Add(reader.GetUint8()); + } + + var data = ZlibDecoder.Inflate(buf); + + var d = new CosmosGL.System.BinaryReader(data.ToArray()); + + var totalScanlines = data.Count / (re.Width + 1) / 4; + + var prevScanline = new List(); + + for (int y = 0; y < totalScanlines; y++) + { + var filter = d.GetUint8(); + + var dat = new List(); + + for (int x = 0; x < re.Width * 4; x++) + { + dat.Add(d.GetUint8()); + } + var scanline = new List(); + + if (filter == 1) + { + scanline.Add(dat[0]); + for (var index = 1; index < dat.Count; index++) + { + scanline.Add((byte) ((scanline[index - 4 > 0 ? index - 4 : 0] + dat[index - 1]) % 256)); + //scanline.Add((byte) (255)); + } + } + else if (filter == 2) + { + for (var index = 0; index < dat.Count; index++) + { + scanline.Add((byte) ((prevScanline[index] + dat[index]) % 256)); + //scanline.Add((byte) (255)); + } + } + else + { + } + + var line = new CosmosGL.System.BinaryReader(scanline.ToArray()); + prevScanline.Clear(); + prevScanline.AddRange(scanline); + + for (int x = 0; x < re.Width; x++) + { + var a = line.GetUint8(); + + var r = line.GetUint8(); + var g = line.GetUint8(); + var b = line.GetUint8(); + + + // if (b == 55 || r == 55 || g == 55) Debugger.Break(); + + var argb = (a << 24) | (r << 16) | (g << 8) | b; + + re.SetPixel(x, y, argb); + } + + /* //re.SetPixel(x, y, d.GetUint32()); + + var b = UnSub(d, x, decoded); + var g = UnSub(d, x, decoded); + var r = UnSub(d, x, decoded); + var a = UnSub(d, x, decoded); + + var c = new Color(r, g, b); + + if (c.ToHex() == 0) c = new Color(prev); + + prev = c.ToHex(); + + + //if(b == 55 || r == 55 || g == 55) Debugger.Break(); + + re.SetPixel(x, y, c);*/ + } + + CustomConsole.WriteLineInfo("IDAT out"); + break; + case "IEND": + CustomConsole.WriteLineInfo("IEND"); + done = true; + break; + } + + if (done) break; + + reader.Seek((int) (pos + len)); + var crc = reader.GetUint32(); + } + + CustomConsole.WriteLineInfo("oe"); + + global::System.Console.ReadKey(); + } + } +}