Utilities/IconFactory.cs
author moel.mich
Sun, 27 May 2012 14:23:31 +0000
changeset 344 3145aadca3d2
parent 40 2392f7402fb6
child 384 76f859f4aea1
permissions -rw-r--r--
Changed the license to the Mozilla Public License 2.0 and update the licensing information.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2009-2010 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Collections.Generic;
    13 using System.Drawing;
    14 using System.Drawing.Imaging;
    15 using System.IO;
    16 using System.Text;
    17 
    18 namespace OpenHardwareMonitor.Utilities {
    19   public class IconFactory {
    20 
    21     private struct BITMAPINFOHEADER {
    22       public uint Size;
    23       public int Width;
    24       public int Height;
    25       public ushort Planes;
    26       public ushort BitCount;
    27       public uint Compression;
    28       public uint SizeImage;
    29       public int XPelsPerMeter;
    30       public int YPelsPerMeter;
    31       public uint ClrUsed;
    32       public uint ClrImportant;
    33 
    34       public BITMAPINFOHEADER(int width, int height, int bitCount) {
    35         this.Size = 40;
    36         this.Width = width;
    37         this.Height = height;
    38         this.Planes = 1;
    39         this.BitCount = (ushort)bitCount;
    40         this.Compression = 0;
    41         this.SizeImage = 0;
    42         this.XPelsPerMeter = 0;
    43         this.YPelsPerMeter = 0;
    44         this.ClrUsed = 0;
    45         this.ClrImportant = 0;
    46       }
    47 
    48       public void Write(BinaryWriter bw) {
    49         bw.Write(Size);
    50 			  bw.Write(Width);
    51 			  bw.Write(Height);
    52 			  bw.Write(Planes);
    53 			  bw.Write(BitCount);
    54 			  bw.Write(Compression);
    55 			  bw.Write(SizeImage);
    56 			  bw.Write(XPelsPerMeter);
    57 			  bw.Write(YPelsPerMeter);
    58 			  bw.Write(ClrUsed);
    59 			  bw.Write(ClrImportant);
    60       }
    61     }
    62 
    63     private struct ICONIMAGE {
    64       public BITMAPINFOHEADER Header;
    65       public byte[] Colors;
    66       public byte[] XOR;
    67       public byte[] AND;
    68 
    69       public ICONIMAGE(int width, int height, byte[] colors) {
    70         this.Header = new BITMAPINFOHEADER(width, height << 1, 
    71           (8 * colors.Length) / (width * height));
    72         this.Colors = colors;
    73         int maskSize = (width * height) >> 3;
    74         this.XOR = new byte[maskSize];
    75         this.AND = new byte[maskSize];
    76       }
    77 
    78       public void Write(BinaryWriter bw) {
    79         Header.Write(bw);
    80         int stride = Header.Width << 2;
    81         for (int i = (Header.Height >> 1) - 1; i >= 0; i--)
    82           bw.Write(Colors, i * stride, stride);
    83         bw.Write(XOR);        
    84         bw.Write(AND);
    85       }
    86     }
    87 
    88     private struct ICONDIRENTRY {
    89       public byte Width;
    90       public byte Height;
    91       public byte ColorCount;
    92       public byte Reserved;
    93       public ushort Planes;
    94       public ushort BitCount;
    95       public uint BytesInRes;
    96       public uint ImageOffset;
    97 
    98       public ICONDIRENTRY(ICONIMAGE image, int imageOffset) {
    99         this.Width = (byte)image.Header.Width;
   100         this.Height = (byte)(image.Header.Height >> 1);
   101         this.ColorCount = 0;
   102         this.Reserved = 0;
   103         this.Planes = image.Header.Planes;
   104         this.BitCount = image.Header.BitCount;
   105         this.BytesInRes = (uint)(image.Header.Size +
   106           image.Colors.Length + image.XOR.Length + image.AND.Length);
   107         this.ImageOffset = (uint)imageOffset;
   108       }
   109 
   110       public void Write(BinaryWriter bw) {
   111         bw.Write(Width);
   112         bw.Write(Height);
   113         bw.Write(ColorCount);
   114         bw.Write(Reserved);
   115         bw.Write(Planes);
   116         bw.Write(BitCount);
   117         bw.Write(BytesInRes);
   118         bw.Write(ImageOffset);
   119       }
   120 
   121       public uint Size {
   122         get { return 16; }
   123       }
   124     }
   125 
   126     private struct ICONDIR {
   127       public ushort Reserved;
   128       public ushort Type;
   129       public ushort Count;
   130       public ICONDIRENTRY[] Entries;
   131 
   132       public ICONDIR(ICONDIRENTRY[] entries) {
   133         this.Reserved = 0;
   134         this.Type = 1;
   135         this.Count = (ushort)entries.Length;
   136         this.Entries = entries;
   137       }
   138 
   139       public void Write(BinaryWriter bw) {
   140         bw.Write(Reserved);
   141         bw.Write(Type);
   142         bw.Write(Count);
   143         for (int i = 0; i < Entries.Length; i++)
   144           Entries[i].Write(bw);
   145       }
   146 
   147       public uint Size {
   148         get { return (uint)(6 + Entries.Length * 
   149           (Entries.Length > 0 ? Entries[0].Size : 0)); } 
   150       }
   151     }
   152 	
   153     public static Icon Create(byte[] colors, int width, int height, 
   154       PixelFormat format) {
   155       if (format != PixelFormat.Format32bppArgb)
   156         throw new NotImplementedException();
   157 
   158       ICONIMAGE image = new ICONIMAGE(width, height, colors);
   159       ICONDIR dir = new ICONDIR(
   160         new ICONDIRENTRY[] { new ICONDIRENTRY(image, 0) } );
   161       dir.Entries[0].ImageOffset = dir.Size;
   162 
   163       Icon icon;
   164       using (BinaryWriter bw = new BinaryWriter(new MemoryStream())) {
   165 				dir.Write(bw);
   166         image.Write(bw);
   167 
   168 				bw.BaseStream.Position = 0;
   169         icon = new Icon(bw.BaseStream);
   170 			}
   171 
   172       return icon;
   173     }
   174 
   175   }
   176 }