using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Windows.Forms;
namespace PaintDotNet
{
///
/// Defines miscellaneous constants and static functions.
///
public sealed class Utility
{
private Utility()
{
}
public static Keys LetterOrDigitCharToKeys(char c)
{
if (c >= 'a' && c <= 'z')
{
return (Keys)((int)(c - 'a') + (int)Keys.A);
}
else if (c >= 'A' && c <= 'Z')
{
return (Keys)((int)(c - 'A') + (int)Keys.A);
}
else if (c >= '0' && c <= '9')
{
return (Keys)((int)(c - '0') + (int)Keys.D0);
}
else
{
return Keys.None;
}
}
public static Control FindFocus()
{
foreach (Form form in Application.OpenForms)
{
Control focused = FindFocus(form);
if (focused != null)
{
return focused;
}
}
return null;
}
private static Control FindFocus(Control c)
{
if (c.Focused)
{
return c;
}
foreach (Control child in c.Controls)
{
Control f = FindFocus(child);
if (f != null)
{
return f;
}
}
return null;
}
public static void DrawColorRectangle(Graphics g, Rectangle rect, Color color, bool drawBorder)
{
int inflateAmt = drawBorder ? -2 : 0;
Rectangle colorRectangle = Rectangle.Inflate(rect, inflateAmt, inflateAmt);
Brush colorBrush = new LinearGradientBrush(colorRectangle, Color.FromArgb(255, color), color, 90.0f, false);
HatchBrush backgroundBrush = new HatchBrush(HatchStyle.LargeCheckerBoard, Color.FromArgb(191, 191, 191), Color.FromArgb(255, 255, 255));
if (drawBorder)
{
g.DrawRectangle(Pens.Black, rect.Left, rect.Top, rect.Width - 1, rect.Height - 1);
g.DrawRectangle(Pens.White, rect.Left + 1, rect.Top + 1, rect.Width - 3, rect.Height - 3);
}
PixelOffsetMode oldPOM = g.PixelOffsetMode;
g.PixelOffsetMode = PixelOffsetMode.Half;
g.FillRectangle(backgroundBrush, colorRectangle);
g.FillRectangle(colorBrush, colorRectangle);
g.PixelOffsetMode = oldPOM;
backgroundBrush.Dispose();
colorBrush.Dispose();
}
public static Font CreateFont(string name, float size, FontStyle style)
{
Font returnFont;
try
{
returnFont = new Font(name, size, style);
}
catch (Exception)
{
returnFont = new Font(FontFamily.GenericSansSerif, size);
}
return returnFont;
}
public static readonly Color TransparentKey = Color.FromArgb(192, 192, 192);
private static bool allowGCFullCollect = true;
public static bool AllowGCFullCollect
{
get
{
return allowGCFullCollect;
}
set
{
allowGCFullCollect = value;
}
}
public static void GCFullCollect()
{
if (AllowGCFullCollect)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
public static bool IsArrowKey(Keys keyData)
{
Keys key = keyData & Keys.KeyCode;
if (key == Keys.Up || key == Keys.Down || key == Keys.Left || key == Keys.Right)
{
return true;
}
else
{
return false;
}
}
public static bool DoesControlHaveMouseCaptured(Control control)
{
bool result = false;
result |= control.Capture;
foreach (Control c in control.Controls)
{
result |= DoesControlHaveMouseCaptured(c);
}
return result;
}
public static void SplitRectangle(Rectangle rect, Rectangle[] rects)
{
int height = rect.Height;
for (int i = 0; i < rects.Length; ++i)
{
Rectangle newRect = Rectangle.FromLTRB(rect.Left,
rect.Top + ((height * i) / rects.Length),
rect.Right,
rect.Top + ((height * (i + 1)) / rects.Length));
rects[i] = newRect;
}
}
public static bool CheckNumericUpDown(NumericUpDown upDown)
{
int a;
bool result = int.TryParse(upDown.Text, out a);
if (result && (a <= (int)upDown.Maximum) && (a >= (int)upDown.Minimum))
{
return true;
}
else
{
return false;
}
}
public static void SetNumericUpDownValue(NumericUpDown upDown, decimal newValue)
{
if (upDown.Value != newValue)
{
upDown.Value = newValue;
}
}
public static void SetNumericUpDownValue(NumericUpDown upDown, int newValue)
{
SetNumericUpDownValue(upDown, (decimal)newValue);
}
public static void ErrorBox(IWin32Window parent, string message)
{
MessageBox.Show(parent, message, PdnInfo.GetBareProductName(), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
public static DialogResult AskYesNo(IWin32Window parent, string question)
{
return MessageBox.Show(parent, question, PdnInfo.GetBareProductName(), MessageBoxButtons.YesNo, MessageBoxIcon.Question);
}
public static Icon ImageToIcon(Image image)
{
return ImageToIcon(image, Utility.TransparentKey);
}
public static Icon ImageToIcon(Image image, bool disposeImage)
{
return ImageToIcon(image, Utility.TransparentKey, disposeImage);
}
public static Icon ImageToIcon(Image image, Color seeThru)
{
return ImageToIcon(image, seeThru, false);
}
///
/// Converts an Image to an Icon.
///
/// The Image to convert to an icon. Must be an appropriate icon size (32x32, 16x16, etc).
/// The color that will be treated as transparent in the icon.
/// Whether or not to dispose the passed-in Image.
/// An Icon representation of the Image.
public static Icon ImageToIcon(Image image, Color seeThru, bool disposeImage)
{
Bitmap bitmap = new Bitmap(image);
for (int y = 0; y < bitmap.Height; ++y)
{
for (int x = 0; x < bitmap.Width; ++x)
{
if (bitmap.GetPixel(x, y) == seeThru)
{
bitmap.SetPixel(x, y, Color.FromArgb(0));
}
}
}
Icon icon = Icon.FromHandle(bitmap.GetHicon());
bitmap.Dispose();
if (disposeImage)
{
image.Dispose();
}
return icon;
}
///
/// Converts a RectangleF to RectangleF by rounding down the Location and rounding
/// up the Size.
///
public static Rectangle RoundRectangle(RectangleF rectF)
{
float left = (float)Math.Floor(rectF.Left);
float top = (float)Math.Floor(rectF.Top);
float right = (float)Math.Ceiling(rectF.Right);
float bottom = (float)Math.Ceiling(rectF.Bottom);
return Rectangle.Truncate(RectangleF.FromLTRB(left, top, right, bottom));
}
///
/// Allows you to find the bounding box for a "region" that is described as an
/// array of bounding boxes.
///
/// The "region" you want to find a bounding box for.
/// A RectangleF structure that surrounds the Region.
public static RectangleF GetRegionBounds(RectangleF[] rectsF, int startIndex, int length)
{
if (rectsF.Length == 0)
{
return RectangleF.Empty;
}
float left = rectsF[startIndex].Left;
float top = rectsF[startIndex].Top;
float right = rectsF[startIndex].Right;
float bottom = rectsF[startIndex].Bottom;
for (int i = startIndex + 1; i < startIndex + length; ++i)
{
RectangleF rectF = rectsF[i];
if (rectF.Left < left)
{
left = rectF.Left;
}
if (rectF.Top < top)
{
top = rectF.Top;
}
if (rectF.Right > right)
{
right = rectF.Right;
}
if (rectF.Bottom > bottom)
{
bottom = rectF.Bottom;
}
}
return RectangleF.FromLTRB(left, top, right, bottom);
}
///
/// Allows you to find the bounding box for a "region" that is described as an
/// array of bounding boxes.
///
/// The "region" you want to find a bounding box for.
/// A RectangleF structure that surrounds the Region.
public static Rectangle GetRegionBounds(Rectangle[] rects, int startIndex, int length)
{
if (rects.Length == 0)
{
return Rectangle.Empty;
}
int left = rects[startIndex].Left;
int top = rects[startIndex].Top;
int right = rects[startIndex].Right;
int bottom = rects[startIndex].Bottom;
for (int i = startIndex + 1; i < startIndex + length; ++i)
{
Rectangle rect = rects[i];
if (rect.Left < left)
{
left = rect.Left;
}
if (rect.Top < top)
{
top = rect.Top;
}
if (rect.Right > right)
{
right = rect.Right;
}
if (rect.Bottom > bottom)
{
bottom = rect.Bottom;
}
}
return Rectangle.FromLTRB(left, top, right, bottom);
}
public static double Clamp(double x, double min, double max)
{
if (x < min)
{
return min;
}
else if (x > max)
{
return max;
}
else
{
return x;
}
}
public static int Clamp(int x, int min, int max)
{
if (x < min)
{
return min;
}
else if (x > max)
{
return max;
}
else
{
return x;
}
}
public static byte ClampToByte(double x)
{
if (x > 255)
{
return 255;
}
else if (x < 0)
{
return 0;
}
else
{
return (byte)x;
}
}
public static byte ClampToByte(float x)
{
if (x > 255)
{
return 255;
}
else if (x < 0)
{
return 0;
}
else
{
return (byte)x;
}
}
public static byte ClampToByte(int x)
{
if (x > 255)
{
return 255;
}
else if (x < 0)
{
return 0;
}
else
{
return (byte)x;
}
}
public static float Lerp(float from, float to, float frac)
{
return (from + frac * (to - from));
}
public static double Lerp(double from, double to, double frac)
{
return (from + frac * (to - from));
}
public static void ShowHelp(Control parent,int type)
{
//string helpFileUrlFormat = PdnResources.GetString("HelpFile.Url.Format");
//string baseSiteUrl = Application.StartupPath + @"\最新显微镜图像处理与分析系统 (修正版本)20210206.chm";//InvariantStrings.WebsiteUrl;
//string helpFileUrl = baseSiteUrl;// string.Format(helpFileUrlFormat, baseSiteUrl);
string filePath = Application.StartupPath + @"\最新显微镜图像处理与分析系统 (修正版本)20210206.chm";
if (!System.IO.File.Exists(filePath))
{
return;
}
if (type == 1)
{
Help.ShowHelp(parent, filePath);
}
else {
Help.ShowHelp(parent, filePath, HelpNavigator.Index);
}
//JScript\JScript
//PdnInfo.OpenUrl(parent, helpFileUrl);
}
///
/// Reads a 16-bit unsigned integer from a Stream in little-endian format.
///
///
/// -1 on failure, else the 16-bit unsigned integer that was read.
public static int ReadUInt16(Stream stream)
{
int byte1 = stream.ReadByte();
if (byte1 == -1)
{
return -1;
}
int byte2 = stream.ReadByte();
if (byte2 == -1)
{
return -1;
}
return byte1 + (byte2 << 8);
}
public static void WriteUInt16(Stream stream, UInt16 word)
{
stream.WriteByte((byte)(word & 0xff));
stream.WriteByte((byte)(word >> 8));
}
public static void WriteUInt24(Stream stream, int uint24)
{
stream.WriteByte((byte)(uint24 & 0xff));
stream.WriteByte((byte)((uint24 >> 8) & 0xff));
stream.WriteByte((byte)((uint24 >> 16) & 0xff));
}
public static void WriteUInt32(Stream stream, UInt32 uint32)
{
stream.WriteByte((byte)(uint32 & 0xff));
stream.WriteByte((byte)((uint32 >> 8) & 0xff));
stream.WriteByte((byte)((uint32 >> 16) & 0xff));
stream.WriteByte((byte)((uint32 >> 24) & 0xff));
}
///
/// Reads a 24-bit unsigned integer from a Stream in little-endian format.
///
///
/// -1 on failure, else the 24-bit unsigned integer that was read.
public static int ReadUInt24(Stream stream)
{
int byte1 = stream.ReadByte();
if (byte1 == -1)
{
return -1;
}
int byte2 = stream.ReadByte();
if (byte2 == -1)
{
return -1;
}
int byte3 = stream.ReadByte();
if (byte3 == -1)
{
return -1;
}
return byte1 + (byte2 << 8) + (byte3 << 16);
}
///
/// Reads a 32-bit unsigned integer from a Stream in little-endian format.
///
///
/// -1 on failure, else the 32-bit unsigned integer that was read.
public static long ReadUInt32(Stream stream)
{
int byte1 = stream.ReadByte();
if (byte1 == -1)
{
return -1;
}
int byte2 = stream.ReadByte();
if (byte2 == -1)
{
return -1;
}
int byte3 = stream.ReadByte();
if (byte3 == -1)
{
return -1;
}
int byte4 = stream.ReadByte();
if (byte4 == -1)
{
return -1;
}
return unchecked((long)((uint)(byte1 + (byte2 << 8) + (byte3 << 16) + (byte4 << 24))));
}
public static int ReadFromStream(Stream input, byte[] buffer, int offset, int count)
{
int totalBytesRead = 0;
while (totalBytesRead < count)
{
int bytesRead = input.Read(buffer, offset + totalBytesRead, count - totalBytesRead);
if (bytesRead == 0)
{
throw new IOException("ran out of data");
}
totalBytesRead += bytesRead;
}
return totalBytesRead;
}
public static void Swap(ref T a, ref T b)
{
T t;
t = a;
a = b;
b = t;
}
public static byte FastScaleByteByByte(byte a, byte b)
{
int r1 = a * b + 0x80;
int r2 = ((r1 >> 8) + r1) >> 8;
return (byte)r2;
}
}
}