//-----------------------------------------------------------------------
//
// 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;
}
}
}