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

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