You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
389 lines
14 KiB
389 lines
14 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Drawing.Imaging;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace GummingCommon
|
|
{
|
|
public static class ExtBitmap
|
|
{
|
|
/*
|
|
ExtBitmap.EdgeFilterType filterType =
|
|
((ExtBitmap.EdgeFilterType)cmbFilterType.SelectedItem);
|
|
|
|
ExtBitmap.DerivativeLevel derivitaveLevel =
|
|
(rdFirstDerivative.Checked ?
|
|
ExtBitmap.DerivativeLevel.First :
|
|
ExtBitmap.DerivativeLevel.Second);
|
|
|
|
if (filterType == ExtBitmap.EdgeFilterType.None)
|
|
{
|
|
bitmapResult = selectedSource;
|
|
}
|
|
else
|
|
{
|
|
bitmapResult = selectedSource.GradientBasedEdgeDetectionFilter(
|
|
filterType, derivitaveLevel,
|
|
trcRedValue.Value / 100.0f,
|
|
trcGreenValue.Value / 100.0f,
|
|
trcBlueValue.Value / 100.0f,
|
|
(byte)trcThreshold.Value);
|
|
}
|
|
//*/
|
|
|
|
public enum EdgeFilterType
|
|
{
|
|
None,
|
|
EdgeDetectMono,
|
|
EdgeDetectGradient,
|
|
Sharpen,
|
|
SharpenGradient,
|
|
}
|
|
|
|
public enum DerivativeLevel
|
|
{
|
|
First = 1,
|
|
Second = 2
|
|
}
|
|
|
|
public enum IconSizeDimensions
|
|
{
|
|
IconSize16x16Pixels = 16,
|
|
IconSize24x24Pixels = 24,
|
|
IconSize32x32Pixels = 32,
|
|
IconSize48x48Pixels = 48,
|
|
IconSize64x64Pixels = 64,
|
|
IconSize96x96Pixels = 96,
|
|
IconSize128x128Pixels = 128
|
|
}
|
|
|
|
public static Bitmap Format32bppArgbCopy(this Bitmap sourceBitmap)
|
|
{
|
|
Bitmap copyBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height, PixelFormat.Format32bppArgb);
|
|
|
|
using (Graphics graphicsObject = Graphics.FromImage(copyBitmap))
|
|
{
|
|
graphicsObject.CompositingQuality = CompositingQuality.HighQuality;
|
|
graphicsObject.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
graphicsObject.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
|
graphicsObject.SmoothingMode = SmoothingMode.HighQuality;
|
|
|
|
graphicsObject.DrawImage(sourceBitmap,
|
|
new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height),
|
|
new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), GraphicsUnit.Pixel);
|
|
}
|
|
|
|
return copyBitmap;
|
|
}
|
|
|
|
public static Bitmap CopyToSquareCanvas(this Bitmap sourceBitmap, Color canvasBackground)
|
|
{
|
|
int maxSide = sourceBitmap.Width > sourceBitmap.Height ? sourceBitmap.Width : sourceBitmap.Height;
|
|
|
|
Bitmap bitmapResult = new Bitmap(maxSide, maxSide, PixelFormat.Format32bppArgb);
|
|
|
|
using (Graphics graphicsResult = Graphics.FromImage(bitmapResult))
|
|
{
|
|
graphicsResult.Clear(canvasBackground);
|
|
|
|
int xOffset = (sourceBitmap.Width - maxSide) / 2;
|
|
int yOffset = (sourceBitmap.Height - maxSide) / 2;
|
|
|
|
graphicsResult.DrawImage(sourceBitmap, new Point(xOffset, xOffset));
|
|
}
|
|
|
|
return bitmapResult;
|
|
}
|
|
|
|
public static Icon CreateIcon(this Bitmap sourceBitmap, IconSizeDimensions iconSize)
|
|
{
|
|
Bitmap squareCanvas = sourceBitmap.CopyToSquareCanvas(Color.Transparent);
|
|
squareCanvas = (Bitmap)squareCanvas.GetThumbnailImage((int)iconSize, (int)iconSize, null, new IntPtr());
|
|
|
|
Icon iconResult = Icon.FromHandle(squareCanvas.GetHicon());
|
|
|
|
return iconResult;
|
|
}
|
|
|
|
public static Bitmap GradientBasedEdgeDetectionFilter(
|
|
this Bitmap sourceBitmap,
|
|
EdgeFilterType filterType,
|
|
DerivativeLevel derivativeLevel,
|
|
float redFactor = 1.0f,
|
|
float greenFactor = 1.0f,
|
|
float blueFactor = 1.0f,
|
|
byte threshold = 0)
|
|
{
|
|
BitmapData sourceData =
|
|
sourceBitmap.LockBits(new Rectangle(0, 0,
|
|
sourceBitmap.Width, sourceBitmap.Height),
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb);
|
|
|
|
|
|
byte[] pixelBuffer = new byte[sourceData.Stride *
|
|
sourceData.Height];
|
|
|
|
|
|
byte[] resultBuffer = new byte[sourceData.Stride *
|
|
sourceData.Height];
|
|
|
|
|
|
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0,
|
|
pixelBuffer.Length);
|
|
|
|
|
|
sourceBitmap.UnlockBits(sourceData);
|
|
|
|
|
|
int derivative = (int)derivativeLevel;
|
|
int byteOffset = 0;
|
|
int blueGradient, greenGradient, redGradient = 0;
|
|
double blue = 0, green = 0, red = 0;
|
|
|
|
|
|
bool exceedsThreshold = false;
|
|
|
|
|
|
for (int offsetY = 1; offsetY < sourceBitmap.Height - 1; offsetY++)
|
|
{
|
|
for (int offsetX = 1; offsetX <
|
|
sourceBitmap.Width - 1; offsetX++)
|
|
{
|
|
byteOffset = offsetY * sourceData.Stride +
|
|
offsetX * 4;
|
|
|
|
|
|
blueGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - 4] -
|
|
pixelBuffer[byteOffset + 4]) / derivative;
|
|
|
|
|
|
blueGradient +=
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + sourceData.Stride]) / derivative;
|
|
|
|
|
|
byteOffset++;
|
|
|
|
|
|
greenGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - 4] -
|
|
pixelBuffer[byteOffset + 4]) / derivative;
|
|
|
|
|
|
greenGradient +=
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + sourceData.Stride]) / derivative;
|
|
|
|
|
|
byteOffset++;
|
|
|
|
|
|
redGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - 4] -
|
|
pixelBuffer[byteOffset + 4]) / derivative;
|
|
|
|
|
|
redGradient +=
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + sourceData.Stride]) / derivative;
|
|
|
|
|
|
if (blueGradient + greenGradient + redGradient > threshold)
|
|
{ exceedsThreshold = true; }
|
|
else
|
|
{
|
|
byteOffset -= 2;
|
|
|
|
|
|
blueGradient = Math.Abs(pixelBuffer[byteOffset - 4] -
|
|
pixelBuffer[byteOffset + 4]);
|
|
byteOffset++;
|
|
|
|
|
|
greenGradient = Math.Abs(pixelBuffer[byteOffset - 4] -
|
|
pixelBuffer[byteOffset + 4]);
|
|
byteOffset++;
|
|
|
|
|
|
redGradient = Math.Abs(pixelBuffer[byteOffset - 4] -
|
|
pixelBuffer[byteOffset + 4]);
|
|
|
|
|
|
if (blueGradient + greenGradient + redGradient > threshold)
|
|
{ exceedsThreshold = true; }
|
|
else
|
|
{
|
|
byteOffset -= 2;
|
|
|
|
|
|
blueGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + sourceData.Stride]);
|
|
|
|
|
|
byteOffset++;
|
|
|
|
|
|
greenGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + sourceData.Stride]);
|
|
|
|
|
|
byteOffset++;
|
|
|
|
|
|
redGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + sourceData.Stride]);
|
|
|
|
|
|
if (blueGradient + greenGradient +
|
|
redGradient > threshold)
|
|
{ exceedsThreshold = true; }
|
|
else
|
|
{
|
|
byteOffset -= 2;
|
|
|
|
|
|
blueGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - 4 - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + 4 + sourceData.Stride]) / derivative;
|
|
|
|
|
|
blueGradient +=
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride + 4] -
|
|
pixelBuffer[byteOffset + sourceData.Stride - 4]) / derivative;
|
|
|
|
|
|
byteOffset++;
|
|
|
|
|
|
greenGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - 4 - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + 4 + sourceData.Stride]) / derivative;
|
|
|
|
|
|
greenGradient +=
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride + 4] -
|
|
pixelBuffer[byteOffset + sourceData.Stride - 4]) / derivative;
|
|
|
|
|
|
byteOffset++;
|
|
|
|
|
|
redGradient =
|
|
Math.Abs(pixelBuffer[byteOffset - 4 - sourceData.Stride] -
|
|
pixelBuffer[byteOffset + 4 + sourceData.Stride]) / derivative;
|
|
|
|
|
|
redGradient +=
|
|
Math.Abs(pixelBuffer[byteOffset - sourceData.Stride + 4] -
|
|
pixelBuffer[byteOffset + sourceData.Stride - 4]) / derivative;
|
|
|
|
|
|
if (blueGradient + greenGradient + redGradient > threshold)
|
|
{ exceedsThreshold = true; }
|
|
else
|
|
{ exceedsThreshold = false; }
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
byteOffset -= 2;
|
|
|
|
|
|
if (exceedsThreshold)
|
|
{
|
|
if (filterType == EdgeFilterType.EdgeDetectMono)
|
|
{
|
|
blue = green = red = 255;
|
|
}
|
|
else if (filterType == EdgeFilterType.EdgeDetectGradient)
|
|
{
|
|
blue = blueGradient * blueFactor;
|
|
green = greenGradient * greenFactor;
|
|
red = redGradient * redFactor;
|
|
}
|
|
else if (filterType == EdgeFilterType.Sharpen)
|
|
{
|
|
blue = pixelBuffer[byteOffset] * blueFactor;
|
|
green = pixelBuffer[byteOffset + 1] * greenFactor;
|
|
red = pixelBuffer[byteOffset + 2] * redFactor;
|
|
}
|
|
else if (filterType == EdgeFilterType.SharpenGradient)
|
|
{
|
|
blue = pixelBuffer[byteOffset] + blueGradient * blueFactor;
|
|
green = pixelBuffer[byteOffset + 1] + greenGradient * greenFactor;
|
|
red = pixelBuffer[byteOffset + 2] + redGradient * redFactor;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (filterType == EdgeFilterType.EdgeDetectMono ||
|
|
filterType == EdgeFilterType.EdgeDetectGradient)
|
|
{
|
|
blue = green = red = 0;
|
|
}
|
|
else if (filterType == EdgeFilterType.Sharpen ||
|
|
filterType == EdgeFilterType.SharpenGradient)
|
|
{
|
|
blue = pixelBuffer[byteOffset];
|
|
green = pixelBuffer[byteOffset + 1];
|
|
red = pixelBuffer[byteOffset + 2];
|
|
}
|
|
}
|
|
|
|
|
|
blue = (blue > 255 ? 255 :
|
|
(blue < 0 ? 0 :
|
|
blue));
|
|
|
|
|
|
green = (green > 255 ? 255 :
|
|
(green < 0 ? 0 :
|
|
green));
|
|
|
|
|
|
red = (red > 255 ? 255 :
|
|
(red < 0 ? 0 :
|
|
red));
|
|
|
|
|
|
resultBuffer[byteOffset] = (byte)blue;
|
|
resultBuffer[byteOffset + 1] = (byte)green;
|
|
resultBuffer[byteOffset + 2] = (byte)red;
|
|
resultBuffer[byteOffset + 3] = 255;
|
|
}
|
|
}
|
|
|
|
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width,
|
|
sourceBitmap.Height);
|
|
|
|
|
|
BitmapData resultData =
|
|
resultBitmap.LockBits(new Rectangle(0, 0,
|
|
resultBitmap.Width, resultBitmap.Height),
|
|
ImageLockMode.WriteOnly,
|
|
PixelFormat.Format32bppArgb);
|
|
|
|
|
|
Marshal.Copy(resultBuffer, 0, resultData.Scan0,
|
|
resultBuffer.Length);
|
|
|
|
|
|
resultBitmap.UnlockBits(resultData);
|
|
|
|
|
|
return resultBitmap;
|
|
}
|
|
}
|
|
}
|