//----------------------------------------------------------------------- // // Copyright © 2012 Nils Hammar. All rights reserved. // //----------------------------------------------------------------------- /* * Software to access vehicle information via the OBD-II connector. * * Copyright © 2012 Nils Hammar * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Alternative licensing is possible, see the licensing document. * * The above text may not be removed or modified. */ namespace Gauges.TelltalePanel { using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Windows.Forms; /// /// Create one telltale from image using the given size. /// /// The image shall be a PNG image with ARGB colorspace composed as follows: /// /// /// Transparent = Transparent part of icon to display the background. /// /// /// Black = Primary Static indication color. /// /// /// Green = Primary Flashing indication color. /// /// /// Red = Secondary Static indication color. /// /// /// Actual colors for a telltale shall be configured in a database by the user and provided as parameters to the constructor. /// /// public class TellTale : PictureBox { /// /// 'true' if the icon has flashing part. /// private bool hasFlash = false; /// /// Initializes a new instance of the class. /// /// Image containing actual icon. /// Icon size. /// Primary Color for static indication. (Must be a color in the palette) /// Secondary color for static indication. (Must be a color in the palette) /// Primary color for flashing indication. (Must be a color in the palette) /// Primary palette for icon. /// Border style for icon. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Reviewed.")] public TellTale(Image img, int size, Color primaryColor, Color secondaryColor, Color flashColor, ColorPalette palette1, BorderStyle borderStyle) { byte indicationIx = PaletteCreator.getColorIndex(primaryColor, false); byte secondaryIx = PaletteCreator.getColorIndex(secondaryColor, false); byte flashIx = PaletteCreator.getColorIndex(flashColor, true); Bitmap bmp0 = getScaledImage2(img, size, size, 0.9F); try { PixelFormat pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed; Bitmap bmp1 = new Bitmap(bmp0.Width, bmp0.Height, pixelFormat); bmp1.Palette = palette1; Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height); BitmapData bmpData = bmp1.LockBits(rect, ImageLockMode.ReadWrite, pixelFormat); IntPtr ptr = bmpData.Scan0; int numBytes = bmp1.Height * bmpData.Stride; byte[] rgbValues = new byte[numBytes]; Marshal.Copy(ptr, rgbValues, 0, numBytes); for (int y = 0; y < bmp0.Height; y++) { int rowOffset = y * bmpData.Stride; for (int x = 0; x < bmp0.Width; x++) { Color col1 = bmp0.GetPixel(x, y); int argb = col1.ToArgb(); if ((argb & 0xff000000) != 0) { int rgb = argb & 0xffffff; byte ix; if (rgb == 0) { ix = indicationIx; } else { if ((rgb & 0xff00) != 0) { ix = flashIx; this.hasFlash = (flashColor != Color.Black); } else { ix = secondaryIx; } } rgbValues[x + rowOffset] = ix; } else { rgbValues[x + rowOffset] = 0; } } } Marshal.Copy(rgbValues, 0, ptr, numBytes); bmp1.UnlockBits(bmpData); this.Size = new Size(size, size); this.SizeMode = PictureBoxSizeMode.Normal; this.Image = bmp1; this.BorderStyle = borderStyle; } finally { bmp0.Dispose(); } } /// /// Set color palette. /// /// Switching between palettes is a way to make icons flash with little effort. /// /// /// Palette to set. public void setPalette(ColorPalette palette) { if (this.hasFlash) { this.Image.Palette = palette; this.Invalidate(); } } /// /// Resize an image to the given size using the proportions of the original image. /// /// There is an additional scaling that allows for shrinking of the image to make it fit better. /// /// /// Notice: This works best if height and width has the same value. /// /// /// Image to process. /// Height of new image. /// Width of new image. /// Additional scaling. /// Scaled image. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")] private static Bitmap getScaledImage2(Image img, int height, int width, float scale) { float proportion = (float)img.Height / (float)img.Width; int w; int h; int x; int y; if (proportion < 1) { h = (int)(scale * height * proportion); w = (int)(scale * width); x = 0; y = (height - h) / 2; } else { h = (int)(scale * height); w = (int)(scale * width / proportion); x = (width - w) / 2; y = 0; } Bitmap bmp = new Bitmap(height, width); using (Graphics g = Graphics.FromImage(bmp)) { g.DrawImage(img, new Rectangle(x, y, w, h)); } return bmp; } } }