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