2016-07-09 22:30:12 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Drawing.Imaging;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
2017-02-01 03:35:18 +00:00
|
|
|
|
namespace PKHeX.WinForms
|
2016-07-09 22:30:12 +00:00
|
|
|
|
{
|
2017-01-12 01:55:42 +00:00
|
|
|
|
public static class ImageUtil
|
2016-07-09 22:30:12 +00:00
|
|
|
|
{
|
|
|
|
|
// Image Layering/Blending Utility
|
2017-01-08 07:54:09 +00:00
|
|
|
|
public static Bitmap LayerImage(Image baseLayer, Image overLayer, int x, int y, double trans)
|
2016-07-09 22:30:12 +00:00
|
|
|
|
{
|
2016-12-16 07:17:17 +00:00
|
|
|
|
if (baseLayer == null)
|
|
|
|
|
return overLayer as Bitmap;
|
2016-07-09 22:30:12 +00:00
|
|
|
|
Bitmap img = new Bitmap(baseLayer.Width, baseLayer.Height);
|
|
|
|
|
using (Graphics gr = Graphics.FromImage(img))
|
|
|
|
|
{
|
2017-12-17 02:29:10 +00:00
|
|
|
|
gr.DrawImage(baseLayer, new Rectangle(0, 0, baseLayer.Width, baseLayer.Height));
|
2017-08-13 07:21:42 +00:00
|
|
|
|
Image o = trans == 1f ? overLayer : ChangeOpacity(overLayer, trans);
|
2016-07-09 22:30:12 +00:00
|
|
|
|
gr.DrawImage(o, new Rectangle(x, y, overLayer.Width, overLayer.Height));
|
|
|
|
|
}
|
|
|
|
|
return img;
|
|
|
|
|
}
|
2017-01-08 07:54:09 +00:00
|
|
|
|
public static Bitmap ChangeOpacity(Image img, double trans)
|
2016-07-09 22:30:12 +00:00
|
|
|
|
{
|
|
|
|
|
if (img == null)
|
|
|
|
|
return null;
|
|
|
|
|
if (img.PixelFormat.HasFlag(PixelFormat.Indexed))
|
|
|
|
|
return (Bitmap)img;
|
|
|
|
|
|
2017-10-02 04:25:23 +00:00
|
|
|
|
var bmp = (Bitmap)img.Clone();
|
|
|
|
|
GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data);
|
2016-07-09 22:30:12 +00:00
|
|
|
|
|
2017-10-02 04:25:23 +00:00
|
|
|
|
Marshal.Copy(ptr, data, 0, data.Length);
|
|
|
|
|
SetAllTransparencyTo(data, trans);
|
|
|
|
|
Marshal.Copy(data, 0, ptr, data.Length);
|
2016-07-09 22:30:12 +00:00
|
|
|
|
bmp.UnlockBits(bmpData);
|
|
|
|
|
|
2016-10-31 02:15:48 +00:00
|
|
|
|
return bmp;
|
|
|
|
|
}
|
2017-01-08 07:54:09 +00:00
|
|
|
|
public static Bitmap ChangeAllColorTo(Image img, Color c)
|
2016-10-31 02:15:48 +00:00
|
|
|
|
{
|
|
|
|
|
if (img == null)
|
|
|
|
|
return null;
|
|
|
|
|
if (img.PixelFormat.HasFlag(PixelFormat.Indexed))
|
|
|
|
|
return (Bitmap)img;
|
|
|
|
|
|
2017-10-02 04:25:23 +00:00
|
|
|
|
var bmp = (Bitmap)img.Clone();
|
|
|
|
|
GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data);
|
2016-10-31 02:15:48 +00:00
|
|
|
|
|
2017-10-02 04:25:23 +00:00
|
|
|
|
Marshal.Copy(ptr, data, 0, data.Length);
|
|
|
|
|
SetAllColorTo(data, c);
|
|
|
|
|
Marshal.Copy(data, 0, ptr, data.Length);
|
2016-10-31 02:15:48 +00:00
|
|
|
|
bmp.UnlockBits(bmpData);
|
|
|
|
|
|
2017-06-18 04:49:14 +00:00
|
|
|
|
return bmp;
|
|
|
|
|
}
|
|
|
|
|
public static Bitmap ToGrayscale(Image img)
|
|
|
|
|
{
|
|
|
|
|
if (img == null)
|
|
|
|
|
return null;
|
|
|
|
|
if (img.PixelFormat.HasFlag(PixelFormat.Indexed))
|
|
|
|
|
return (Bitmap)img;
|
|
|
|
|
|
2017-10-02 04:25:23 +00:00
|
|
|
|
var bmp = (Bitmap)img.Clone();
|
|
|
|
|
GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data);
|
2017-06-18 04:49:14 +00:00
|
|
|
|
|
2017-10-02 04:25:23 +00:00
|
|
|
|
Marshal.Copy(ptr, data, 0, data.Length);
|
|
|
|
|
SetAllColorToGrayScale(data);
|
|
|
|
|
Marshal.Copy(data, 0, ptr, data.Length);
|
2017-06-18 04:49:14 +00:00
|
|
|
|
bmp.UnlockBits(bmpData);
|
|
|
|
|
|
2016-07-09 22:30:12 +00:00
|
|
|
|
return bmp;
|
|
|
|
|
}
|
2017-10-02 04:25:23 +00:00
|
|
|
|
private static void GetBitmapData(Bitmap bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data)
|
|
|
|
|
{
|
|
|
|
|
bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
|
|
|
|
ptr = bmpData.Scan0;
|
|
|
|
|
data = new byte[bmp.Width * bmp.Height * 4];
|
|
|
|
|
}
|
2018-01-22 01:22:31 +00:00
|
|
|
|
public static Bitmap GetBitmap(byte[] data, int width, int height, int stride = -1, PixelFormat format = PixelFormat.Format32bppArgb)
|
2018-01-10 07:30:44 +00:00
|
|
|
|
{
|
2018-01-22 01:22:31 +00:00
|
|
|
|
if (stride == -1 && format == PixelFormat.Format32bppArgb)
|
|
|
|
|
stride = 4 * width; // defaults
|
2018-01-10 07:30:44 +00:00
|
|
|
|
return new Bitmap(width, height, stride, format, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0));
|
|
|
|
|
}
|
|
|
|
|
public static byte[] GetPixelData(Bitmap bitmap)
|
|
|
|
|
{
|
|
|
|
|
var argbData = new byte[bitmap.Width * bitmap.Height * 4];
|
|
|
|
|
var bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
|
|
|
|
Marshal.Copy(bd.Scan0, argbData, 0, bitmap.Width * bitmap.Height * 4);
|
|
|
|
|
bitmap.UnlockBits(bd);
|
|
|
|
|
return argbData;
|
|
|
|
|
}
|
2017-10-02 04:25:23 +00:00
|
|
|
|
private static void SetAllTransparencyTo(byte[] data, double trans)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < data.Length; i += 4)
|
|
|
|
|
data[i + 3] = (byte)(data[i + 3] * trans);
|
|
|
|
|
}
|
|
|
|
|
private static void SetAllColorTo(byte[] data, Color c)
|
|
|
|
|
{
|
|
|
|
|
byte R = c.R;
|
|
|
|
|
byte G = c.G;
|
|
|
|
|
byte B = c.B;
|
|
|
|
|
for (int i = 0; i < data.Length; i += 4)
|
|
|
|
|
{
|
|
|
|
|
if (data[i + 3] == 0)
|
|
|
|
|
continue;
|
|
|
|
|
data[i + 0] = B;
|
|
|
|
|
data[i + 1] = G;
|
|
|
|
|
data[i + 2] = R;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private static void SetAllColorToGrayScale(byte[] data)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < data.Length; i += 4)
|
|
|
|
|
{
|
|
|
|
|
if (data[i + 3] == 0)
|
|
|
|
|
continue;
|
|
|
|
|
byte greyS = (byte)((0.3 * data[i + 2] + 0.59 * data[i + 1] + 0.11 * data[i + 0]) / 3);
|
|
|
|
|
data[i + 0] = greyS;
|
|
|
|
|
data[i + 1] = greyS;
|
|
|
|
|
data[i + 2] = greyS;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-14 22:08:14 +00:00
|
|
|
|
|
|
|
|
|
public static Color ColorBaseStat(int v)
|
|
|
|
|
{
|
|
|
|
|
const float maxval = 180; // shift the green cap down
|
|
|
|
|
float x = 100f * v / maxval;
|
|
|
|
|
if (x > 100)
|
|
|
|
|
x = 100;
|
|
|
|
|
double red = 255f * (x > 50 ? 1 - 2 * (x - 50) / 100.0 : 1.0);
|
|
|
|
|
double green = 255f * (x > 50 ? 1.0 : 2 * x / 100.0);
|
|
|
|
|
|
|
|
|
|
return Blend(Color.FromArgb((int)red, (int)green, 0), Color.White, 0.4);
|
|
|
|
|
}
|
|
|
|
|
public static Color Blend(Color color, Color backColor, double amount)
|
|
|
|
|
{
|
|
|
|
|
byte r = (byte)(color.R * amount + backColor.R * (1 - amount));
|
|
|
|
|
byte g = (byte)(color.G * amount + backColor.G * (1 - amount));
|
|
|
|
|
byte b = (byte)(color.B * amount + backColor.B * (1 - amount));
|
|
|
|
|
return Color.FromArgb(r, g, b);
|
|
|
|
|
}
|
2016-07-09 22:30:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|