aboutsummaryrefslogtreecommitdiff
path: root/source/ShiftUI/Internal/ImageListStreamer.cs
diff options
context:
space:
mode:
authorMichaelTheShifter <[email protected]>2016-07-20 09:40:36 -0400
committerMichaelTheShifter <[email protected]>2016-07-20 09:40:36 -0400
commitd40fed5ce2bc806a91245adb18039634eac13ed0 (patch)
treef1d7168aee6db109ac2c738ad18c9db667a6ba69 /source/ShiftUI/Internal/ImageListStreamer.cs
parentf1856e8ed30ed882229fd3fa2a4038122a5fb441 (diff)
downloadshiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.tar.gz
shiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.tar.bz2
shiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.zip
Move ShiftUI source code to ShiftOS
This'll be a lot easier to work on.
Diffstat (limited to 'source/ShiftUI/Internal/ImageListStreamer.cs')
-rw-r--r--source/ShiftUI/Internal/ImageListStreamer.cs338
1 files changed, 338 insertions, 0 deletions
diff --git a/source/ShiftUI/Internal/ImageListStreamer.cs b/source/ShiftUI/Internal/ImageListStreamer.cs
new file mode 100644
index 0000000..3186747
--- /dev/null
+++ b/source/ShiftUI/Internal/ImageListStreamer.cs
@@ -0,0 +1,338 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2002-2006 Novell, Inc.
+//
+// Authors:
+// Jackson Harper ([email protected])
+// Gonzalo Paniagua Javier ([email protected])
+//
+// Based on work done by:
+// Dennis Hayes ([email protected])
+// Aleksey Ryabchuk ([email protected])
+
+using System.IO;
+using System.Drawing;
+using System.Collections;
+using System.Drawing.Imaging;
+using System.Runtime.Serialization;
+using System.Runtime.InteropServices;
+using System;
+
+
+namespace ShiftUI {
+ [Serializable]
+ public sealed class ImageListStreamer : ISerializable {
+ readonly ImageList.ImageCollection imageCollection;
+ Image [] images;
+ Size image_size;
+ Color back_color;
+
+ internal ImageListStreamer (ImageList.ImageCollection imageCollection)
+ {
+ this.imageCollection = imageCollection;
+ }
+
+ private ImageListStreamer (SerializationInfo info, StreamingContext context)
+ {
+ byte [] data = (byte []) info.GetValue ("Data", typeof (byte []));
+ if (data == null || data.Length <= 4) { // 4 is the signature
+ return;
+ }
+
+ // check the signature ( 'MSFt' )
+ if (data [0] != 77 || data [1] != 83 || data [2] != 70 || data [3] != 116) {
+ return;
+ }
+
+ MemoryStream decoded = GetDecodedStream (data, 4, data.Length - 4);
+ decoded.Position = 4; // jumps over 'magic' and 'version', which are 16-bits each
+
+ BinaryReader reader = new BinaryReader (decoded);
+ ushort nimages = reader.ReadUInt16 ();
+ reader.ReadUInt16 (); // cMaxImage
+ ushort grow = reader.ReadUInt16 (); // cGrow
+ ushort cx = reader.ReadUInt16 ();
+ ushort cy = reader.ReadUInt16 ();
+ uint bkcolor = reader.ReadUInt32 ();
+ back_color = Color.FromArgb ((int) bkcolor);
+ reader.ReadUInt16 (); // flags
+
+ short [] ovls = new short [4];
+ for (int i = 0; i < 4; i++) {
+ ovls[i] = reader.ReadInt16 ();
+ }
+
+ byte [] decoded_buffer = decoded.GetBuffer ();
+ int bmp_offset = 28;
+ // FileSize field from the bitmap file header
+ int filesize = decoded_buffer [bmp_offset + 2] + (decoded_buffer [bmp_offset + 3] << 8) +
+ (decoded_buffer [bmp_offset + 4] << 16) + (decoded_buffer [bmp_offset + 5] << 24);
+ // ImageSize field from the info header (can be 0)
+ int imagesize = decoded_buffer [bmp_offset + 34] + (decoded_buffer [bmp_offset + 35] << 8) +
+ (decoded_buffer [bmp_offset + 36] << 16) + (decoded_buffer [bmp_offset + 37] << 24);
+
+ int bmp_length = imagesize + filesize;
+ MemoryStream bmpms = new MemoryStream (decoded_buffer, bmp_offset, bmp_length);
+ Bitmap bmp = null;
+ Bitmap mask = null;
+ bmp = new Bitmap (bmpms);
+ MemoryStream mask_stream = new MemoryStream (decoded_buffer,
+ bmp_offset + bmp_length,
+ (int) (decoded.Length - bmp_offset - bmp_length));
+
+ if (mask_stream.Length > 0)
+ mask = new Bitmap (mask_stream);
+
+ if (bkcolor == 0xFFFFFFFF)
+ back_color = bmp.GetPixel (0, 0);
+
+ if (mask != null) {
+ int width = bmp.Width;
+ int height = bmp.Height;
+ Bitmap newbmp = new Bitmap (bmp);
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ Color mcolor = mask.GetPixel (x, y);
+ if (mcolor.B != 0) {
+ newbmp.SetPixel (x, y, Color.Transparent);
+ }
+ }
+ }
+ bmp.Dispose ();
+ bmp = newbmp;
+ mask.Dispose ();
+ mask = null;
+ }
+ images = new Image [nimages];
+ image_size = new Size (cx, cy);
+ Rectangle dest_rect = new Rectangle (0, 0, cx, cy);
+ if (grow * bmp.Width > cx) // Some images store a wrong 'grow' factor
+ grow = (ushort) (bmp.Width / cx);
+
+ for (int r = 0 ; r < nimages ; r++) {
+ int col = r % grow;
+ int row = r / grow;
+ Rectangle area = new Rectangle (col * cx, row * cy, cx, cy);
+ Bitmap b = new Bitmap (cx, cy);
+ using (Graphics g = Graphics.FromImage (b)) {
+ g.DrawImage (bmp, dest_rect, area, GraphicsUnit.Pixel);
+ }
+
+ images [r] = b;
+ }
+ bmp.Dispose ();
+ }
+
+ /*
+ static void WriteToFile (MemoryStream st)
+ {
+ st.Position = 0;
+ FileStream fs = File.OpenWrite (Path.GetTempFileName ());
+ Console.WriteLine ("Writing to {0}", fs.Name);
+ st.WriteTo (fs);
+ fs.Close ();
+ }
+ */
+
+ static byte [] header = new byte []{ 77, 83, 70, 116, 73, 76, 1, 1 };
+ public void GetObjectData (SerializationInfo si, StreamingContext context)
+ {
+ MemoryStream stream = new MemoryStream ();
+ BinaryWriter writer = new BinaryWriter (stream);
+ writer.Write (header);
+
+ Image [] images = (imageCollection != null) ? imageCollection.ToArray () : this.images;
+ int cols = 4;
+ int rows = images.Length / cols;
+ if (images.Length % cols > 0)
+ ++rows;
+
+ writer.Write ((ushort) images.Length);
+ writer.Write ((ushort) images.Length);
+ writer.Write ((ushort) 0x4);
+ writer.Write ((ushort) (images [0].Width));
+ writer.Write ((ushort) (images [0].Height));
+ writer.Write (0xFFFFFFFF); //BackColor.ToArgb ()); //FIXME: should set the right one here.
+ writer.Write ((ushort) 0x21);
+ for (int i = 0; i < 4; i++)
+ writer.Write ((short) -1);
+
+ Bitmap main = new Bitmap (cols * ImageSize.Width, rows * ImageSize.Height);
+ using (Graphics g = Graphics.FromImage (main)) {
+ g.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), 0, 0,
+ main.Width, main.Height);
+ for (int i = 0; i < images.Length; i++) {
+ g.DrawImage (images [i], (i % cols) * ImageSize.Width,
+ (i / cols) * ImageSize.Height);
+ }
+ }
+
+ MemoryStream tmp = new MemoryStream ();
+ main.Save (tmp, ImageFormat.Bmp);
+ tmp.WriteTo (stream);
+
+ Bitmap mask = Get1bppMask (main);
+ main.Dispose ();
+ main = null;
+
+ tmp = new MemoryStream ();
+ mask.Save (tmp, ImageFormat.Bmp);
+ tmp.WriteTo (stream);
+ mask.Dispose ();
+
+ stream = GetRLEStream (stream, 4);
+ si.AddValue ("Data", stream.ToArray (), typeof (byte []));
+ }
+
+ unsafe Bitmap Get1bppMask (Bitmap main)
+ {
+ Rectangle rect = new Rectangle (0, 0, main.Width, main.Height);
+ Bitmap result = new Bitmap (main.Width, main.Height, PixelFormat.Format1bppIndexed);
+ BitmapData dresult = result.LockBits (rect, ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
+
+ int w = images [0].Width;
+ int h = images [0].Height;
+ byte *scan = (byte *) dresult.Scan0.ToPointer ();
+ int stride = dresult.Stride;
+ Bitmap current = null;
+ for (int idx = 0; idx < images.Length; idx++) {
+ current = (Bitmap) images [idx];
+ // Hack for newly added images.
+ // Probably has to be done somewhere else.
+ Color c1 = current.GetPixel (0, 0);
+ if (c1.A != 0 && c1 == back_color)
+ current.MakeTransparent (back_color);
+ //
+ }
+
+ int yidx = 0;
+ int imgidx = 0;
+ int localy = 0;
+ int localx = 0;
+ int factor_y = 0;
+ int factor_x = 0;
+ for (int y = 0; y < main.Height; y++) {
+ if (localy == h) {
+ localy = 0;
+ factor_y += 4;
+ }
+ factor_x = 0;
+ localx = 0;
+ for (int x = 0; x < main.Width; x++) {
+ if (localx == w) {
+ localx = 0;
+ factor_x++;
+ }
+ imgidx = factor_y + factor_x;
+ if (imgidx >= images.Length)
+ break;
+ current = (Bitmap) images [imgidx];
+ Color color = current.GetPixel (localx, localy);
+ if (color.A == 0) {
+ int ptridx = yidx + (x >> 3);
+ scan [ptridx] |= (byte) (0x80 >> (x & 7));
+ }
+ localx++;
+ }
+ if (imgidx >= images.Length)
+ break;
+ yidx += stride;
+ localy++;
+ }
+ result.UnlockBits (dresult);
+
+ return result;
+ }
+
+ static MemoryStream GetDecodedStream (byte [] bytes, int offset, int size)
+ {
+ byte [] buffer = new byte [512];
+ int position = 0;
+ int count, data;
+ MemoryStream result = new MemoryStream ();
+ while (size > 0) {
+ count = (int) bytes [offset++];
+ data = (int) bytes [offset++];
+ if ((512 - count) < position) {
+ result.Write (buffer, 0, position);
+ position = 0;
+ }
+
+ for (int i = 0; i < count; i++)
+ buffer [position++] = (byte) data;
+ size -= 2;
+ }
+
+ if (position > 0)
+ result.Write (buffer, 0, position);
+
+ result.Position = 0;
+ return result;
+ }
+
+ //TODO: OptimizeMe
+ static MemoryStream GetRLEStream (MemoryStream input, int start)
+ {
+ MemoryStream result = new MemoryStream ();
+ byte [] ibuffer = input.GetBuffer ();
+ result.Write (ibuffer, 0, start);
+ input.Position = start;
+
+ int prev = -1;
+ int count = 0;
+ int current;
+ while ((current = input.ReadByte ()) != -1) {
+ if (prev != current || count == 255) {
+ if (prev != -1) {
+ result.WriteByte ((byte) count);
+ result.WriteByte ((byte) prev);
+ }
+ prev = current;
+ count = 0;
+ }
+ count++;
+ }
+
+ if (count > 0) {
+ result.WriteByte ((byte) count);
+ result.WriteByte ((byte) current);
+ }
+
+ return result;
+ }
+
+ internal Image [] Images {
+ get { return images; }
+ }
+
+ internal Size ImageSize {
+ get { return image_size; }
+ }
+
+ internal ColorDepth ColorDepth {
+ get { return ColorDepth.Depth32Bit; }
+ }
+
+ internal Color BackColor {
+ get { return back_color; }
+ }
+ }
+}
+